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

时间:2010-08-09 20:21:55

标签: java keyword var

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

15 个答案:

答案 0 :(得分:237)

没有。唉,你必须输入完整的类型名称。

编辑:发布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())来影响方法,不要忘记非虚方法受到类型的影响。

    我无法想象一个现实世界的场景,这表明设计很好,但这可能无法按预期工作:

    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 关键字。

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

答案 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中所列举的那样):

  • 带有初始化程序的局部变量
  • 增强型for循环中的索引
  • 以传统的for-loop声明的本地人

因此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中看到它的实际效果。

JEP 286

  

增强Java语言,以使用初始化程序将类型推断扩展为局部变量的声明。

所以现在不是写作:

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

你写道:

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

注意:

  • var现在是reserved type name
  • Java 仍然承诺静态输入!
  • 它只能用于 local 变量声明

如果您想在本地系统上安装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#,

  

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不是合法的类型名称。

答案 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