Java中C#'var'关键字的等价物是什么?

Art*_*uro 254 java var keyword

在C#中使用var关键字是隐式类型声明.var的Java等价语法是什么?

Mik*_*ron 243

空无一人.唉,你必须输入完整的类型名称.

编辑:发布后7年,var在Java 10中添加了局部变量(with )的类型推断.

编辑:发布后6年,收集下面的一些评论:

  • C#具有var关键字的原因是因为可能在.NET中具有没有名称的类型.例如:

    var myData = new { a = 1, b = "2" };
    
    Run Code Online (Sandbox Code Playgroud)

    在这种情况下,不可能给出合适的类型myData.6年前,这在Java中是不可能的(所有类型都有名字,即使它们非常冗长和不适合).我不知道这个时间是否有所改变.

  • var是不一样的dynamic.variables仍然是100%静态类型.这不会编译:

    var myString = "foo";
    myString = 3;
    
    Run Code Online (Sandbox Code Playgroud)
  • var当类型从上下文中显而易见时,它也很有用.例如:

    var currentUser = User.GetCurrent();
    
    Run Code Online (Sandbox Code Playgroud)

    我可以说,在我负责的任何代码中,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
    
    Run Code Online (Sandbox Code Playgroud)

    如上所述,虚拟方法不受此影响.

  • 不,在没有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
    
    Run Code Online (Sandbox Code Playgroud)

    在这种情况下,只需按照老式方式进行:

    object foo6;
    
    Run Code Online (Sandbox Code Playgroud)

  • @Jon Hanna:`var`不会使代码不那么清晰.而在我看来则恰恰相反.例如,为什么在声明并实例化它时,在同一行上写入两次(甚至三次)类型(`RadioButton radioButton = new RadioButton();`)?当你命名你的变量时,`var`会让你更加三思而后行,因为它把注意力集中在功能而不是类型上(例如`UserCollection collection = new userRepository.GetUsers();`更自然地变成`var users = userRepository.GetUsers();`).如果您认为`var`不清楚,那只是因为它未使用过. (198认同)
  • @Mike Caron:C#有[默认]非虚拟调用,运算符不是虚拟的......`var p = new X(); pZ()`与`SuperX p = new X()不同; pZ()`适用于所有X和SuperX,即使是`X:SuperX`.在`var`中,`p`的*static*类型在上面的第一个例子中始终是`X`,但在第二个例子中总是`SuperX`.要注意一个微妙但重要的区别.但你的答案是非常正确的:-) (11认同)
  • @Jon Hanna:我曾经和你一样对'var'一样关键,如果不是更多,但我已经改变了我的看法,也许它就像一个不同意见的问题一样简单,因为当你说的时候我仍然认为你错了这是你使用匿名对象和泛型的问题;)类型声明通常只是代码噪声,如果没有它就无法理解代码,在任何一种情况下代码都可能不清楚. (6认同)
  • @MartinOdhelius`var`非常肯定可以使代码清晰使用得很好,但它也可以使它不清楚太使用了; 像许多格式选项.平衡取决于您使用匿名对象和泛型的程度,这两者都不存在于.NET 1.0中,因此在第一版C♯中作为假设关键字不太有用.在工厂或辅助方法的情况下,我只会命名一个`RadioButton``radioButton`,其中唯一重要的是关于按钮的是它是一个`RadioButton`,否则这是疯狂的,有或没有`var`. (4认同)
  • [匿名类型](https://docs.microsoft.com/)令人困惑[var](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/var) EN-US/DOTNET/CSHARP /编程引导/班,和结构/匿名类型).`var`本身只是要求编译器从赋值中推断出类型; 这是语法糖.起初我对此持怀疑态度,但我虔诚地使用它并且尚未遇到引起混淆的时间.它在实例化时删除冗余,并且在引用时无需检查类型.JAVA 9没有JAVA等价物. (3认同)
  • Java 10预计会有类型推断,请参阅https://blog.codefx.org/java/java-10-var-type-in​​ference/ (3认同)
  • @MartinOdhelius谁说我批评var?关于SharpDevelop2.0,我最喜欢的一件事就是它有一个可以打字输入的功能,例如`?x = a.CompareTo(b);`into`int x = a.CompareTo(b);`等等,这是我们在没有语言支持的情况下最接近`var`.所以我在`var`之前使用`var`. (2认同)

dar*_*ino 44

如果将Lombok添加到项目中,则可以使用其val关键字.

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


blu*_*xff 27

JEP - JDK增强 - 提案

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>
Run Code Online (Sandbox Code Playgroud)


bal*_*pha 20

我已经为IntelliJ制作了一个插件 - 在某种程度上 - var用Java 提供给你.这是一个黑客,所以通常的免责声明适用,但如果您使用IntelliJ进行Java开发并想要尝试,请访问https://bitbucket.org/balpha/varsity.

  • @hotkey这使用IntelliJ的内置代码折叠,因此您可以使用Ctrl-Shift-NumPadPlus展开所有内容.当光标位于包含折叠变量声明的行上时,您可以使用Ctrl-NumPadPlus和Ctrl-NumPadMinus折叠/展开当前方法中的声明.折叠所有声明有点尴尬,你已经折叠了一切(Ctrl-Shift-NumPadMinus),然后再展开一切(Ctrl-Shift-NumPadPlus). (2认同)

Jus*_*ano 15

随着3月20日JDK 10的发布,Java现在包含了JEP 286中var指定的保留类型名称(不是关键字 - 见下文).对于局部变量,以下内容现在在Java 10或更高版本中有效:

var map = new HashMap<String, Integer>();
Run Code Online (Sandbox Code Playgroud)

varJava中的保留类型名称与varC#中的关键字几乎相同,因为它们都允许隐式类型(请参阅下面的重要差异).var在Java中,只能在以下上下文中用于隐式类型推断(如JEP 286:目标中所列举的):

  • 带初始化器的局部变量
  • 增强的for循环中的索引
  • 在传统的for循环中声明的locals

因此var ,不能用于字段,返回类型,类名或接口名称.它的基本原理是去除需要包括长类型名称声明和定义局部变量的时候,在规定JEP 286 (Brian Goetz撰写着):

我们通过减少与编写Java代码相关的仪式来提高开发人员的体验,同时保持Java对静态类型安全的承诺,允许开发人员忽略局部变量类型经常不必要的清单声明.

var 在Java中确定范围

应该注意,var它不是Java中的关键字,而是保留类型名称.引自JEP 286:

标识符var不是关键字; 相反,它是一个保留类型名称.这意味着使用var作为变量,方法或包名称的代码不会受到影响; 使用var作为类或接口名称的代码将受到影响(但这些名称在实践中很少见,因为它们违反了通常的命名约定).

需要注意的是,因为var是保留类型名称,而不是一个关键字,它仍然可以用于包名,方法名和变量名(连同其新型干扰作用).例如,以下是varJava 中有效用法的所有示例:

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

引自JEP 286:

这种处理将局限于具有初始化器的局部变量,增强的for循环中的索引和传统for循环中声明的局部变量; 它不适用于方法形式,构造函数形式,方法返回类型,字段,捕获形式或任何其他类型的变量声明.

varJava和C#之间的差异

这是varC#和Java 之间的一个显着区别,包括以下内容:var可以在C#中用作类型名称,但不能在Java中用作类名或接口名.根据C#文档(隐式类型局部变量):

如果命名的类型var在范围内,则var关键字将解析为该类型名称,并且不会被视为隐式类型的局部变量声明的一部分.

var在C#中用作类型名称的能力会产生一些复杂性并引入一些复杂的解决规则,这些规则var在Java中通过禁止var作为类或接口名称来避免.有关varC#中类型名称的复杂性的信息,请参阅限制适用于隐式类型变量声明.有关`var in Java的范围界定决策背后的基本原理的更多信息,请参阅JEP 286:范围选择.


Mar*_*oun 11

它将在JDK 10中得到支持.甚至可以在早期访问构建中看到它的运行情况.

JEP 286:

增强Java语言以使用初始值设定项将类型推断扩展为局部变量的声明.

所以现在而不是写:

List<> list = new ArrayList<String>();
Stream<> stream = myStream();
Run Code Online (Sandbox Code Playgroud)

你写:

var list = new ArrayList<String>();
var stream = myStream();
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 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 ==> []
Run Code Online (Sandbox Code Playgroud)

  • 当心,您提供的代码(在var之前/之后)并不等效。在“ var”示例中,“ list”的类型为“ ArrayList”,而不是“ List”。 (2认同)

Jon*_*Raa 8

一个简单的解决方案(假设您正在使用一个不错的IDE)只是在任何地方键入'int'然后让它为您设置类型.

我实际上刚刚添加了一个名为'var'的类,所以我不必输入不同的东西.

代码仍然太冗长,但至少你不必输入它!


Bri*_*etz 6

从 Java 10 开始,等效项是 ... var


Art*_*iom 5

您可以通过JetBrains 看看Kotlin,但它是val.不是变种

  • Kotlin有val和var.val对于在java中声明变量final是等效的,var允许重新分配. (4认同)

Ale*_*nov 5

Java 10确实得到了局部变量类型的推断,所以现在它var与C#one相当(据我所知).

它还可以推断出不可表示的类型(程序员无法在该位置命名的类型;尽管哪些类型是不可表示的,但是Java不具有与C#匿名类型相同的类型).

我能找到的一个区别是在C#中,

如果名为var的类型在范围内,则var关键字将解析为该类型名称,并且不会被视为隐式类型的局部变量声明的一部分.

在Java 10 var中,不是合法的类型名称.