Java是否有自动类型推断功能?


113

autoJava中是否像C ++中一样有变量类型?

一个例子:

for ( auto var : object_array)
    std::cout << var << std::endl;

for( auto var : object_array)
    var.do_something_that_only_this_particular_obj_can_do();

我知道Java中有一个增强的for循环,但是有自动吗?如果不是,是否有这样做的技巧?我指的是C ++ 11中的新功能


1
可以将除基本类型以外的所有内容分配给类型变量Object,因此对于某些操作,可以Object在需要的地方使用auto
Zyx 2000

1
没有Java没有这样的变量
Aleksei Bulgak

@ Zyx2000:然后,它将使用对象的to_string功能,而不是有问题的实际对象,不是吗?
Games Brainiac

2
@GamesBrainiac:不,它将使用覆盖的版本(如果存在)。
Keppil

2
您要查找的术语不是“自动”,而是“类型推断”。关于Java中的类型推论,有很多问题,尽管它们主要是指泛型,所以我不确定如何找到重复的…

Answers:


49

在问题被编辑之前回答:

auto,Java中没有变量类型。可以通过以下方式实现相同的循环:

for ( Object var : object_array)
  System.out.println(var);

Java具有局部变量,其范围在定义它们的块内。与C和C ++类似,但是没有auto或register关键字。但是,Java编译器将不允许使用未明确初始化的局部变量,并且会产生编译错误(与C和C ++不同,后者通常仅发出警告)。礼貌:Wikipedia

不,在Java中没有像C ++这样的主流类型推断。有一个RFE,但是由于“将无法解决”而关闭,给出的原因是:

人类可以通过两种方式从类型声明的冗余中受益。首先,冗余类型可以作为有价值的文档-读者不必搜索getMap()的声明来查找返回的类型。其次,冗余允许程序员声明预期的类型,从而受益于编译器执行的交叉检查。


10
@GamesBrainiac不,方法调用在Java中总是多态的。但是,许多其他事情(例如重载解析或未在上定义的任何操作Object)无法像这样完成。这并不是一个很好的答案,它只是因为问题中的示例比较薄弱​​而起作用。

10
这个问题是关于C ++ 11中的类型推断的,而不是关于autoC和pre-C ++ 11中的旧用法。您的修改不合主题。

4
“那不是我的意思,一旦将其强制转换为对象,它将为您提供对象的to_string” False。绝对是100%错误。
Louis Wasserman

140
“人类将从冗余中受益。” 这是真的。每天早晨,我醒来时都在想:“如何使我的代码更具冗余性?”。因为好处。
ahoffer

2
而且这个答案已经过时,因为var是从Java 9.保留关键字
6infinity8

69

Java 10可能通过var关键字满足了您(和我)的需求。

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

来自JDK增强建议286


更新:是的,该功能使其成为Java 10版本!


6
是的,它是一个改进,但是该关键字只能与局部变量一起使用。不像C ++自动类型推断那么强大
texasbruce

7
次要选择:var不是关键字!从JLS:“ var不是关键字,而是具有特殊含义的标识符,作为局部变量声明的类型”。因此,与关键字不同,没有什么可以阻止您调用变量或方法“ var”。
Klitos Kyriacou

2
好点@KlitosKyriacou。但是,如果我想将“关键字”替换为“标识符”,或者甚至将“具有特殊含义的标识符用作局部变量声明的类型”,我想答案就不太清楚了。但是,var确实不在关键字列表中。
对不起,

它不是仅用于向后兼容的关键字。除了您可以使用该名称标识之外,var还充当关键字的角色。
facetus

25

Java 7引入了Diamond语法

Box<Integer> integerBox = new Box<>(); // Java 7

与旧的Java相比

Box<Integer> integerBox = new Box<Integer>(); // Before Java 7

挑剔的读者会注意到,这种新语法无助于在原始问题中编写for循环。这是正确的,而且完全是故意的。请参见引用Oracle错误数据库的其他答案。


4
的确如此,但是他(和我)正在寻找的是这样的:auto integerBox = new Box<Integer>();,通常用于从有时可能很复杂的函数中获取返回值HashMap<String, LinkedList<Operation, Set<Integer>>>
Roee Gavirel 2014年

1
这种担心正是我在代码示例之后解决的。结论是Java不会这样做,那是有目的的。
塔拉许2014年

18

在Java 8中,可以使用lambda类型推断来避免声明类型。发问者示例的类似物是:

object_array.forEach(var -> System.out.println(var)); 
object_array.forEach(var -> var.do_something_that_only_this_particular_obj_can_do());

使用方法引用也可以简化这两种方法:

object_array.forEach(System.out::println); 
object_array.forEach(ObjectType::do_something_that_only_this_particular_obj_can_do);

8

简而言之,没有,没有自动类型。如果您只是在打印该值,则可以将该值称为Object


或计算hashCodes或收集类名,或...您有主意;)列表很短。参见Object class的文档(注释供初学者使用,我确定您知道它是SimonC)
Alexander Malakhov

4

这不是一个纯Java解决方案,但是添加一个名为lombok的库将使下面的魔术能够编译和工作,非常类似于autoC ++中的关键字

List<String> strList = Arrays.asList("foo", "bar", "baz");
for (val s: strList){
    System.out.println(s.length());
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.