在C#中使用 var 关键字是隐式类型声明。 var 的Java等效语法是什么?
答案 0 :(得分:237)
没有。唉,你必须输入完整的类型名称。
编辑:发布7年后,在Java 10中添加了局部变量的类型推断(使用var
)。
编辑:发布后6年,收集下面的一些评论:
C#具有var
关键字的原因是因为可以在.NET中使用没有名称的类型。例如:
var myData = new { a = 1, b = "2" };
在这种情况下,不可能为myData
提供合适的类型。 6年前,这在Java中是不可能的(所有类型都有名字,即使它们非常冗长和不适合)。我不知道这个时间是否有所改变。
var
与dynamic
不同。 var
iables仍然是100%静态类型。这不会编译:
var myString = "foo";
myString = 3;
var
也很有用。例如:
var currentUser = User.GetCurrent();
我可以说,在我负责的任何代码中,currentUser
都有User
或派生类。显然,如果你的User.GetCurrent
实现返回一个int,那么这可能对你有害。
这与var
无关,但是如果你有奇怪的继承层次结构,你用其他方法(例如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;
答案 1 :(得分:43)
如果您将Lombok添加到项目中,则可以使用其 val 关键字。
答案 2 :(得分:26)
JEP - JDK Enhancement-Proposal
http://openjdk.java.net/jeps/286
JEP 286:局部变量类型推断
作者Brian Goetz
// Goals:
var list = new ArrayList<String>(); // infers ArrayList<String>
var stream = list.stream(); // infers Stream<String>
答案 3 :(得分:20)
我为IntelliJ制作了一个插件 - 在某种程度上 - 用Java提供var
。这是一个黑客,所以通常的免责声明适用,但如果您使用IntelliJ进行Java开发并想要尝试它,它就在https://bitbucket.org/balpha/varsity。
答案 4 :(得分:13)
随着3月20日JDK 10的发布,Java现在包含var
保留类型名称(不是关键字 - 见下文),如JEP 286中所述。对于局部变量,以下内容现在在Java 10或更高版本中有效:
var map = new HashMap<String, Integer>();
Java中的var
保留类型名称与C#中的var
关键字几乎相同,因为它们都允许隐式类型(请参阅下面的重要差异)。 Java中的var
只能用于以下上下文中的隐式类型推断(如JEP 286: Goals中所列举的那样):
因此var
不能用于字段,返回类型,类名或接口名称。它的基本原理是在声明和定义局部变量时不需要包含长类型名称,如JEP 286中所述(由Brian Goetz撰写):
我们通过减少仪式来寻求改善开发者体验 与编写Java代码相关联,同时保持Java的承诺 通过允许开发人员来避免静态类型安全 经常不必要的局部变量类型的清单声明。
var
在Java中确定范围
应该注意,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循环中的索引和声明的本地 传统的循环;它不适用于方法正式, 构造函数形式,方法返回类型,字段,捕获形式,或 任何其他类型的变量声明。
Java中var
之间的差异&amp; C#强>
这是C#中var
之间的一个值得注意的区别,Java包含以下内容:var
可以在C#中用作类型名称,但不能在Java中用作类名或接口名。根据{{3}}:
如果名为
var
的类型在范围内,则var
关键字将解析为 该类型名称,不会被视为隐式类型的一部分 局部变量声明。
在C#中使用var
作为类型名称的能力会产生一些复杂性并引入一些复杂的解决规则,这些规则在Java中被var
通过禁止var
作为一个类或界面名称。有关C#中var
类型名称的复杂性的信息,请参阅C# documentation (Implicitly Typed Local Variables)。有关`var in Java的范围界定决策背后的基本原理的更多信息,请参阅Restrictions apply to implicitly-typed variable declarations。
答案 5 :(得分:11)
它将在JDK 10中得到支持。甚至可以在early access build中看到它的实际效果。
增强Java语言,以使用初始化程序将类型推断扩展为局部变量的声明。
所以现在不是写作:
List<> list = new ArrayList<String>();
Stream<> stream = myStream();
你写道:
var list = new ArrayList<String>();
var stream = myStream();
注意:
var
现在是reserved type name 如果您想在本地系统上安装Java而尝试尝试,我创建了一个安装了JDK 10的Docker image:
$ 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 ==> []
答案 6 :(得分:8)
一个简单的解决方案(假设您正在使用一个不错的IDE)只需键入&#39; int&#39;无处不在,然后让它为你设置类型。
我实际上刚刚添加了一个名为&#39; var&#39;所以我不必输入不同的东西。
代码仍然过于冗长,但至少你不必输入它!
答案 7 :(得分:5)
您可以通过JetBrains查看Kotlin,但它是val。不是变种。
答案 8 :(得分:5)
Java 10确实得到了局部变量类型推断,所以它现在有var
,它几乎等同于C#(据我所知)。
它还可以推断出不可表示的类型(程序员不能在那个地方命名的类型;虽然哪些类型是不可表示的,例如Java不会&#39 ; t等效于C#匿名类型。)
我能找到的一个区别是在C#,
在Java 10中,var
不是合法的类型名称。
答案 9 :(得分:3)
我知道这是旧的,但为什么不创建一个var类并创建具有不同类型的构造函数,并且根据调用的构造函数,您可以获得不同类型的var。您甚至可以构建将一种类型转换为另一种类型的方法。
答案 10 :(得分:3)
Lombok
supports 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);
Here是在IntelliJ IDEA
尝试使用它时要避免的陷阱。它似乎按预期工作,虽然包括自动完成和一切。在存在“非hacky”解决方案之前(例如由于JEP 286: Local-Variable Type Inference),这可能是您现在最好的选择。
请注意val
也支持Lombok
,而无需修改或创建lombok.config
。
答案 11 :(得分:3)
从Java 10开始,等效的是...... var
。
答案 12 :(得分:2)
您可以在Java 10中,但仅适用于本地变量,意思是
你可以,
var anum = 10; var aString = "Var";
但不能,
var anull = null; // Since the type can't be inferred in this case
查看spec了解详情。
答案 13 :(得分:0)
一般情况下,您可以将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);
答案 14 :(得分:-1)
此功能现在可在Java SE 10中使用。静态的,类型安全的var终于进入了java世界:)
来源:https://www.oracle.com/corporate/pressrelease/Java-10-032018.html