C中var关键字的一种用法是隐式类型声明。VaR的Java等价语法是什么?
- 如果使用特定的"Java替换"语言,EDCOX1〔0〕(或var);
- @那就是斯卡拉吗?嗯,是的。
- 对于Intellij,我提交了一个功能请求:youtrack.jetbrains.com/issue/ide a-102808,即使底层代码没有,IDE也可以折叠代码来显示val或var。
- @乔恩,我为intellij拼凑了些东西,看看我的答案。
- 在Java 8中仍然没有var关键字/类型推断,对吗?left斜.net/wp/2013/07/25/…
- 现在有一个建议将这个特性包含在Java-OpenJDK.JavaNET/JEPS/86中。
- 也许你可以试试kotlin kotlinlang.org。关于kotlin的精彩讨论。Youtu.be/r0j_jl7bky8号
- @麦金现在还活着。
没有。唉,您必须输入完整的类型名。
编辑:在发布7年后,在Java 10中添加了局部变量的类型推断(使用EDCOX1(0))。
编辑:发布6年后,收集以下评论:
C拥有var关键字的原因是因为.NET中可能有没有名称的类型。如:
1
| var myData = new { a = 1, b ="2" }; |
在这种情况下,不可能给myData一个合适的类型。6年前,在Java中这是不可能的(所有类型都有名字,即使它们非常冗长和不整洁)。我不知道这是否在同一时期发生了变化。
var与dynamic不同。variables仍然是100%静态类型。这不会编译:
1 2
| var myString ="foo";
myString = 3; |
当类型在上下文中很明显时,var也很有用。例如:
1
| var currentUser = User.GetCurrent(); |
我可以说,在我负责的任何代码中,currentUser中都有一个User或派生类。显然,如果您的User.GetCurrent的实现返回一个int,那么这可能对您不利。
这与var无关,但是如果您有奇怪的继承层次结构,在这些层次结构中,您使用其他方法(例如new public void DoAThing()隐藏方法),请不要忘记非虚拟方法受其转换为的类型的影响。
我无法想象一个现实世界中的场景,这意味着良好的设计,但这可能无法如您所期望的那样工作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| 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。
1 2 3 4 5
| 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 |
在这种情况下,只需按传统方式操作:
- 也要公平;1.这是最近才出现的,所以阿图罗不能责怪"创造者"和2。正是由于这两种语言中没有1.0的一些其他特性,它才成为一种有用的想法,而不是一种使代码不那么清晰和更容易出错的好方法。它在C 3.0中是必需的,在C 2.0中会有一些有用的情况,但在C 1.0中会是一件坏事。
- @迈克·卡伦:而且由于某些非常长的类型(没有var),这会使linq实际上无法使用。
- @pst隐式类型与多态性有什么关系?var关键字与声明具有精确表达式类型的变量完全相同。这就是全部。
- @Mike Caron:C有[默认]非虚拟呼叫,运营商不是虚拟的,所以…对于所有x和superx,var p = new X(); p.Z()与SuperX p = new X(); p.Z()不同,尽管X : SuperX不同。对于var,在上面的第一个示例中,p的静态类型始终是X,而在第二个示例中始终是SuperX。需要注意的细微但重要的区别。但你的回答是非常正确的——)
- @乔恩·汉娜:var并没有使代码变得不那么清晰。在我看来恰恰相反。例如,当您声明和实例化类型(RadioButton radioButton = new RadioButton();时,为什么要在同一行上编写两次(甚至三次)类型?当你命名变量时,var让你宁愿三思而后行,因为它把重点放在功能上而不是类型上(例如UserCollection collection = new userRepository.GetUsers();,而更自然地变成var users = userRepository.GetUsers();。如果你认为var不清楚,那只是因为它不习惯。
- @martinodhelius var非常明确地可以使代码清晰地使用,但它也可以使代码不清楚地使用得太差;就像许多格式化选项一样。根据您使用匿名对象和泛型的程度不同,这两者都不存在于.NET 1.0中,这使得它在C的第一个版本中作为假设关键字的用处更小。.I只会在工厂或辅助方法的情况下命名一个RadioButtonRadioButton,在这种情况下,按钮唯一重要的是它是一个RadioButton,否则无论有没有var,这都是疯狂的。
- @乔恩·汉娜:我曾经对var和你一样挑剔,如果不是更多的话,但我已经改变了我的看法,也许这只是一个不同意见的问题,因为我仍然认为你说你用了多少匿名对象和泛型是错误的;类型声明通常只是代码噪音,如果你没有它就无法理解代码。在这两种情况下,代码可能都不清楚。
- @马丁诺德赫利乌斯谁说我批评VaR?关于sharpdevelop2.0,我最喜欢的一点是它有一个特性,可以将类型(如? x = a.CompareTo(b);转换为int x = a.CompareTo(b);等等,这是我们在没有语言支持的情况下最接近var的特性。所以我用的是var,而不是var。
- 很抱歉,但是"var currentuser=user.getcurrent();"并不是你想要得到的东西。您可能会得到一个用户类的实例,但是您也可以很容易地得到一个字符串形式的用户名、一个整数形式的用户ID或任何组合。您在本文中正确地指出了这一点,但这个特定的示例实际上演示了var如何能够彻底地混淆一个情况,而不是澄清它。
- 您将var与匿名类型混淆了。var本身只要求编译器从赋值中推断类型;这是语法上的优势。起初我对它持怀疑态度,但我虔诚地使用它,而且还没有遇到一个它导致混乱的时期。它在实例化时消除了冗余,并且在引用时消除了检查类型的需要。Java 9中没有Java等价物。
- Java 10预期有类型推断,参见BLUG CODEFX.OR/JAVA/JAVA 10-VAR类型推断
- @Robear是唯一可能(但不必)导致混淆的地方,它是您不能使用IDE指出正确类型的地方。例如,以代码评审委员会为例。
如果你将lombok添加到你的项目中,你可以使用它的val关键字。
http://projectlombok.org/features/val.html
- @右折:引用为final的对象不一定是不可变的。以final StringBuilder strB = new StringBuilder("My reference is final"); strB.append("I'm not immutable");为例
- 由于Lombok v1.16.12,对var也有实验支持。项目lombok.org/features/experimental/var.html
- @马提亚斯堡,你的例子是错误的。在这种情况下,StringBuilder类本身是不可变的,只需使用方法向其内部结构添加字符串值,这是完全合法的。
jep-jdk增强建议
http://openjdk.java.net/jeps/286
jep286:局部变量类型推断
作者布赖恩·戈茨
1 2 3
| // Goals:
var list = new ArrayList<String>(); // infers ArrayList<String>
var stream = list.stream(); // infers Stream<String> |
- 什么版本的Java?10?
- 相关阅读:第一次与Java 10中的"var"联系
- @是的。JEP 286已经在JDK 10中被接受和发布(参见OpenJDK、Java.NET/Studio/JDK/10)下的286个特性。
我已经为iTeliJi开发了一个插件,在某种程度上,它在Java中提供了EDCOX1×0。这是一个黑客,所以通常的免责声明适用,但如果你使用的是对你的Java开发的ITELLIJ,并尝试它,它是在HTTPS://ButButk.Org/BalpHa/ValeSt.
- 在当前编辑器中有一个折叠/展开声明类型的快捷键是很好的。不过,插件很棒。
- @热键这使用了Intellij的内置代码折叠,所以您可以用ctrl-shift-numpadplus展开所有内容。当光标位于包含折叠变量声明的行上时,可以使用ctrl numpadplus和ctrl numpadminus来折叠/展开当前方法中的声明。折叠所有声明有点笨拙,您可以折叠所有内容(ctrl-shift-numpadminus),然后再次展开所有内容(ctrl-shift-numpadplus)。
与"十通释的JDK(Java 3月20 var现在包括A型(不保留关键字的域名(看下面),为的是specified 286。局部变量,下面是现在有效期在Java 10或更高。
1
| var map = new HashMap <String, Integer >(); |
《var保留在Java的类型名identical冰近两个var关键字在C allow #在那两个隐式typlng(见下面的为重要的差异)。在只读varJava可以被用来隐式inference在下面的contexts(AS enumerated的目标是:在286):
- 局部变量的初始化。
- 属性的增强环路
- locals宣布在一个传统的闭环
因此var不能被用来为田,返回的类型的名称、类或接口的名称。其理论基础是remove的需要包括长型的名称,当defining申报和局部变量,为286(除非是在城市authored Brian Goetz):
We seek to improve the developer experience by reducing the ceremony
associated with writing Java code, while maintaining Java's commitment
to static type safety, by allowing developers to elide the
often-unnecessary manifest declaration of local variable types.
在Java var范围
它应该是noted var冰槽,在Java关键字A,而A型,但保留名称。as quoted从286:是的
The identifier var is not a keyword; instead it is a reserved type
name. This means that code that uses var as a variable, method, or
package name will not be affected; code that uses var as a class or
interface name will be affected (but these names are rare in practice,
since they violate usual naming conventions).
注意,由于var类型名是一个保留关键字而不是一个静止的,它可以被用来作为包名、方法名和变量名(沿与它的新类型的干扰角色)。例如,下面的例子都有效(在Java var辨别:
1 2 3 4 5
| var i = 0;
var var = 1;
for (var i = 0; i < 10; i++) { /* ... */ }
public int var() { return 0; }
package var; |
as quoted从286:是的
This treatment would be restricted to local variables with
initializers, indexes in the enhanced for-loop, and locals declared in
a traditional for-loop; it would not be available for method formals,
constructor formals, method return types, fields, catch formals, or
any other kind of variable declaration.
之间的差异在Java var&;C #
这是一notable之间的差分varC和Java #包括以下:var可以被用来作为一种# name in C,但不能被用来作为一个类或接口的名称name in Java。根据《#文件(C型implicitly局部变量):
If a type named var is in scope, then the var keyword will resolve to
that type name and will not be treated as part of an implicitly typed
local variable declaration.
使用的能力varAS name in C A型#创建一些复杂性和introduces intricate分辨率的一些规则,这是避免在城市var市disallowing var作为一类或接口的名称。信息在complexities名大学varC型的限制,适用于#,看到两个implicitly型变量的声明。更多信息在背后的理论基础的决策"的范围是在Java中,看到的是286:选择范围。
- Java和C的区别在于,对于字段或返回类型,您不能使用EDCOX1?0字段吗?为什么需要注意?
- 在该上下文中,UED1306322不使用Java中的EDOCX1 0,不能用于字段或返回类型。这一点很重要,因为这一限制使var对上下文敏感,因为它只能在某些上下文(局部变量)中使用,而不能在其他上下文中使用。这不一定是Java和C应该注意的区别,但在Java中使用EDCOX1(0)时通常是一个重要的限制。
- 我只是抬头看了看,在C语言中,你可以将var作为类名,并以此作为类名使用。从技术上讲,这是一个"上下文关键字",但在爪哇,你似乎不能这么做。如果我错了就纠正我。
- 你说得对。在Java中,不能使用EDCOX1 0作为一个类名或接口名称(无论如何都不常见),但您可以使用它来变量名、方法名和包名。例如,EDCOX1 OR 1是一个有效的Java语句,但是试图声明一个类为EDCOX1(2)导致错误:EDCOX1×3。我已经更新了上面的答案,详细地讨论了在Java中EDOCX1的0个方面的原理,以及它与C中的EDCOX1(0)的区别。
它将在JDK 10中得到支持。甚至可以在早期的访问构建中看到它的运行。
JEP 286:
Enhance the Java Language to extend type inference to declarations of local variables with initializers.
所以现在不用写了:
1 2
| List<> list = new ArrayList<String>();
Stream<> stream = myStream(); |
你写:
1 2
| var list = new ArrayList<String>();
var stream = myStream(); |
笔记:
- var现在是保留的类型名
- Java仍然致力于静态打字!
- 它只能在局部变量声明中使用
如果您想尝试在本地系统上安装Java,我在JDK 10上安装了一个DOCKER映像:
1 2 3 4 5 6 7 8 9
| $ 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 ==> [] |
- 注意,您提供的代码(在var之前/之后)不是等效的。在var示例中,list是ArrayList类型,而不是list类型。
一个简单的解决方案(假设您使用的是一个合适的IDE)就是在任何地方键入"int",然后让它为您设置类型。
实际上,我只是添加了一个名为"var"的类,这样就不必键入不同的类型。
代码仍然太冗长,但至少您不必键入它!
- 当你说"体面的IDE"时,Eclipse*被排除在外了吗?--这在露娜似乎不起作用(至少当我刚用int试过的时候),我是否遗漏了什么?(*:虽然我永远不会称Eclipse为一个体面的IDE,但我不能为其他人做出判断…)
- @不知道我在用这个主意,以前没用过Eclipse。它不适合你吗?我习惯于C/Visual Studio/Resharper,这和想法很相似,只是它实际工作正常!在所有JetBrains的类型中,当出现错误时,您可以按alt enter来获取建议列表-因此,将type设置为int会引入一个错误,您可以按alt enter来对类型进行排序。
Java的确10 inference局部变量的类型,所以现在它具有var漂亮。这是两个等价的C #酮(SO的父亲为我意识到)。
它可以infer也非denotable类型(类型,不能被命名,在那地方的程序;但这类非denotable冰是不同的,例如Java有一个不等价的两个C #匿名类型)。
这一差异在能找到的是在C #,
If a type named var is in scope, then the var keyword will resolve to that type name and will not be treated as part of an implicitly typed local variable declaration.
在Java的10 var冰不是一个合法的类型名。
你可以通过JetBrains看看Kotlin,但它是Val,不是Var。
- Kotlin的VAL和VAR.VAL等价于在Java中声明变量的最终值,var允许重新分配。
在Java中,10当量的冰淇淋……var。
- 有什么区别吗?我的意思是你比写这样的简短的答案更清楚,你的代表级别是N。当然肯定会有一些不同。
- @用户1306322这是一个完全独立的问题!您可以检查java-10标记,因为已经询问了它的许多方面。
- 好吧,这是一个问题,看看你是否在谷歌搜索这个,因为它首先出现,并在侧边栏中的每个相关帖子中链接到。所以我想,如果你知道回答它的那个单独的问题,你至少可以链接到它,或者在你的答案中包含它的一部分。
Lombok支持var,但仍属于实验类:
1 2 3 4 5 6
| 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中使用时,要避免以下陷阱。它看起来像预期的那样工作,尽管包括自动完成和一切。除非有"非黑客"解决方案(例如,由于jep 286:局部变量类型推断),否则这可能是您目前的最佳选择。
注意,val也由Lombok支持,不需要修改或创建lombok.config。
我知道这是旧的,但为什么不创建一个var类,并创建具有不同类型的构造函数,根据调用的构造函数,您可以获得具有不同类型的var。甚至可以内置方法将一种类型转换为另一种类型。
你可以在Java中,10,但只读局部变量的意义,
你可以,
var anum = 10; var aString ="Var";
但不能,
var anull = null; // Since the type can't be inferred in this case
退房的规格的更多信息。
- 这是不正确的。var可用于多种形式的不可表示类型,包括捕获类型、交集类型和匿名类类型。并且,对于Java 11,它也可以应用于lambda参数。
- 改变了它。感谢您指出:)
在总,你可以使用任何类型的对象的类,但是你有做型铸造以后!
如:
1 2 3 4 5 6 7 8
| 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); |
- 阿迪蒂亚,请检查一下你的其他答案。他们中的许多人都有-1,可能是出于一个很好的原因。如果你不确定是正确的,就不要随便张贴。
- @用户1306322我的答案有什么问题!你能详细解释一下吗?我们不能对所有数据类型使用对象类吗?
- 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;
- 问题是你不理解这个问题。问题不是"如何使这项工作成功",而是"有这样的事情吗?"你回答错了问题。由于该语言现在正式使用了var这个词,您的答案也指的是现在老式的方式。
这个特征是现在可用的Java看到10。在静态类型安全,终于有了做为《Java的世界:)
来源:http:/ / /公司/ www.oracle.com pressrelease / java-10-032018.html