簡體   English   中英

Java 中 C# 'var' 關鍵字的等價物是什么?

[英]What is the equivalent of the C# 'var' keyword in Java?

C# 中var關鍵字的一種用法是隱式類型聲明。 var的 Java 等效語法是什么?

空無一人。 唉,你必須輸入完整的類型名稱。

編輯:發布 7 年后,在 Java 10 中添加了局部變量(帶有var )的類型推斷。

編輯:發布6年后,從下面收集一些評論:

  • C# 有var關鍵字的原因是因為在 .NET 中可能有沒有名稱的類型。 例如:

     var myData = new { a = 1, b = "2" };

    在這種情況下,不可能為myData提供正確的類型。 6 年前,這在 Java 中是不可能的(所有類型都有名稱,即使它們非常冗長和笨拙)。 我不知道這是否同時發生了變化。

  • vardynamic var iables仍有100%的靜態類型。 這不會編譯:

     var myString = "foo"; myString = 3;
  • 當類型從上下文中顯而易見時, var也很有用。 例如:

     var currentUser = User.GetCurrent();

    我可以說,在我負責的任何代碼中, currentUser都有一個User或派生類。 顯然,如果您的User.GetCurrent實現返回一個 int,那么這可能對您不利。

  • 這與var無關,但是如果您有奇怪的繼承層次結構,在其中使用其他方法(例如new public void DoAThing()new public void DoAThing()方法,請不要忘記非虛擬方法受它們new public void DoAThing()為的類型的影響.

    我無法想象一個現實世界的場景,這表明設計良好,但這可能不像你期望的那樣工作:

     class Foo { public void Non() {} public virtual void Virt() {} } class Bar : Foo { public new void Non() {} public override void Virt() {} } class Baz { public static Foo GetFoo() { return new Bar(); } } var foo = Baz.GetFoo(); foo.Non(); // <- Foo.Non, not Bar.Non foo.Virt(); // <- Bar.Virt var bar = (Bar)foo; bar.Non(); // <- Bar.Non, not Foo.Non bar.Virt(); // <- Still Bar.Virt

    如上所述,虛擬方法不受此影響。

  • 不,沒有非笨拙的方法來初始化沒有實際變量的var

     var foo1 = "bar"; //good var foo2; //bad, what type? var foo3 = null; //bad, null doesn't have a type var foo4 = default(var); //what? var foo5 = (object)null; //legal, but go home, you're drunk

    在這種情況下,只需按照老式的方式進行:

     object foo6;

如果您將 Lombok 添加到您的項目中,您可以使用其val關鍵字。

http://projectlombok.org/features/val.html

JEP - JDK 增強建議

http://openjdk.java.net/jeps/286

JEP 286:局部變量類型推斷

作者布賴恩·戈茨

// Goals:
var list = new ArrayList<String>();  // infers ArrayList<String>
var stream = list.stream();          // infers Stream<String>

我為 IntelliJ 編寫了一個插件,在某種程度上,它為您提供了 Java 中的var 這是一個 hack,所以通常的免責聲明適用,但如果您使用 IntelliJ 進行 Java 開發並想嘗試一下,它位於https://bitbucket.org/balpha/varsity

隨着 3 月 20 日 JDK 10 的發布,Java 現在包含JEP 286 中指定的var保留類型名稱(不是關鍵字 - 見下文)。 對於局部變量,以下內容現在在 Java 10 或更高版本中有效:

var map = new HashMap<String, Integer>();

Java 中的var保留類型名稱幾乎與 C# 中的var關鍵字相同,因為兩者都允許隱式類型(重要區別見下文)。 Java 中的var只能用於以下上下文中的隱式類型推斷(如JEP 286:目標中所列舉):

  • 帶有初始值設定項的局部變量
  • 增強的 for 循環中的索引
  • 在傳統的 for 循環中聲明的 locals

因此var不能用於字段、返回類型、類名或接口名。 它的基本原理是在聲明和定義局部變量時不需要包含長類型名稱,如JEP 286 (由 Brian Goetz 撰寫)所述:

我們尋求通過減少與編寫 Java 代碼相關的儀式來改善開發人員體驗,同時通過允許開發人員省略通常不必要的局部變量類型的清單聲明,同時保持 Java 對靜態類型安全的承諾。

Java中的var范圍

需要注意的是var在 Java 中不是關鍵字,而是保留類型名稱。 引用自 JEP 286:

標識符 var 不是關鍵字; 相反,它是一個保留的類型名稱。 這意味着使用 var 作為變量、方法或包名的代碼不會受到影響; 使用 var 作為類或接口名稱的代碼將受到影響(但這些名稱在實踐中很少見,因為它們違反了通常的命名約定)。

請注意,由於var是保留類型名稱而不是關鍵字,因此它仍可用於包名稱、方法名稱和變量名稱(以及其新的類型干擾角色)。 例如,以下是在 Java 中有效使用var所有示例:

var i = 0;
var var = 1;
for (var i = 0; i < 10; i++) { /* ... */ }
public int var() { return 0; }
package var;

引用自 JEP 286:

這種處理將僅限於具有初始值設定項的局部變量、增強的 for 循環中的索引以及在傳統 for 循環中聲明的局部變量; 它不適用於方法形式、構造函數形式、方法返回類型、字段、捕獲形式或任何其他類型的變量聲明。

Java 和 C 中var區別

這是 C# 和 Java 中var之間的一個顯着區別,包括: var可以用作 C# 中的類型名稱,但不能用作 Java 中的類名稱或接口名稱。 根據C# 文檔(隱式類型局部變量)

如果名為var的類型在范圍內,則var關鍵字將解析為該類型名稱,並且不會被視為隱式類型局部變量聲明的一部分。

在使用的能力var在C#中的類型名稱帶來了一些復雜性,並介紹了一些復雜的決策規則,這是由避免var在Java中通過禁止var作為一個類或接口的名稱。 有關 C# 中var類型名稱復雜性的信息,請參閱適用於隱式類型變量聲明的限制 有關 Java 中 `var 范圍決定背后的基本原理的更多信息,請參閱JEP 286:范圍選擇

它將在 JDK 10 中得到支持。甚至可以在早期訪問版本中看到它的運行情況。

JEP 286

增強 Java 語言以將類型推斷擴展到帶有初始值設定項的局部變量聲明。

所以現在而不是寫:

List<> list = new ArrayList<String>();
Stream<> stream = myStream();

你寫:

var list = new ArrayList<String>();
var stream = myStream();

筆記:

  • var現在是保留類型名稱
  • Java仍然致力於靜態類型!
  • 它只能用於局部變量聲明

如果您想嘗試一下而不在本地系統上安裝 Java,我創建了一個安裝了 JDK 10 的Docker 鏡像

$ docker run -it marounbassam/ubuntu-java10 bash
root@299d86f1c39a:/# jdk-10/bin/jshell
Mar 30, 2018 9:07:07 PM java.util.prefs.FileSystemPreferences$1 run
INFO: Created user preferences directory.
|  Welcome to JShell -- Version 10
|  For an introduction type: /help intro

jshell> var list = new ArrayList<String>();
list ==> []

一個簡單的解決方案(假設您使用的是不錯的 IDE)是在任何地方輸入“int”,然后讓它為您設置類型。

我實際上只是添加了一個名為“var”的類,因此我不必鍵入不同的內容。

代碼還是太冗長了,但至少不用打字了!

從 Java 10 開始,等效項是 ... var

你可以看看 JetBrains 的Kotlin ,但它是 val。 不是變種

Java 10 確實獲得了局部變量類型推斷,所以現在它有var ,它幾乎等同於 C# 一個(據我所知)。

它還可以推斷不可表示的類型(程序員無法在該位置命名的類型;盡管哪些類型是不可表示的是不同的)。 參見例如使用var和匿名類的技巧(你永遠不應該在工作中使用)

我能找到的一個區別是在 C# 中,

如果名為 var 的類型在范圍內,則 var 關鍵字將解析為該類型名稱,並且不會被視為隱式類型局部變量聲明的一部分。

在 Java 10 中var不是合法的類型名稱。

我知道這是舊的,但為什么不創建一個 var 類並創建具有不同類型的構造函數,並且根據調用的構造函數,您會得到不同類型的 var。 您甚至可以內置方法將一種類型轉換為另一種類型。

Lombok支持 var但它仍被歸類為實驗性的:

import lombok.experimental.var;

var number = 1; // Inferred type: int
number = 2; // Legal reassign since var is not final
number = "Hi"; // Compilation error since a string cannot be assigned to an int variable
System.out.println(number);

是嘗試在IntelliJ IDEA使用它時要避免的一個陷阱。 雖然包括自動完成和所有內容,但它似乎按預期工作。 直到有一個“非hacky”的解決方案(例如,由於JEP 286: Local-Variable Type Inference ),這可能是你現在最好的選擇。

請注意, Lombok也支持val ,而無需修改或創建lombok.config

你可以,在 Java 10 中,但僅限於局部變量,意思是,

你可以,

var anum = 10; var aString = "Var";

但不能,

var anull = null; // Since the type can't be inferred in this case

查看規范以獲取更多信息。

通常,您可以將 Object 類用於任何類型,但稍后您必須進行類型轉換!

例如:-

Object object = 12;
    Object object1 = "Aditya";
    Object object2 = 12.12;

    System.out.println(Integer.parseInt(object.toString()) + 2);

    System.out.println(object1.toString() + " Kumar");
    System.out.println(Double.parseDouble(object2.toString()) + 2.12);

這個特性現在在 Java SE 10 中可用。靜態的、類型安全的 var 終於進入了 Java 世界:)

來源: https : //www.oracle.com/corporate/pressrelease/Java-10-032018.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM