我一直想知道,既然Java是正确的语言,并且它的VM非常成熟,为什么Java不进行类型推断。Google的Go语言是一种具有出色的类型推断功能的语言示例,它减少了人们必须进行的键入操作。该功能不是Java的一部分有什么特殊的原因吗?
我一直想知道,既然Java是正确的语言,并且它的VM非常成熟,为什么Java不进行类型推断。Google的Go语言是一种具有出色的类型推断功能的语言示例,它减少了人们必须进行的键入操作。该功能不是Java的一部分有什么特殊的原因吗?
Answers:
从技术上讲,Java 在使用泛型时确实具有类型推断。用像这样的通用方法
public <T> T foo(T t) {
return t;
}
编写时,编译器将分析并了解
// String
foo("bar");
// Integer
foo(new Integer(42));
根据作为参数输入的内容,将为第一个调用返回一个String,为第二个调用返回一个Integer。结果,您将获得正确的编译时检查。此外,在Java 7中,可以得到一些额外的类型推断当实例化泛型像现在这样
Map<String, String> foo = new HashMap<>();
Java足以为我们填补空白。现在,为什么Java不支持将类型推断作为变量分配的一部分?有一次,在变量声明中有一个用于类型推断的RFE,但是由于“将无法解决”而被关闭,因为
人类可以通过两种方式从类型声明的冗余中受益。首先,冗余类型可作为有价值的文档-读者不必搜索getMap()的声明来查找返回的类型。其次,冗余允许程序员声明预期的类型,从而受益于编译器执行的交叉检查。
完成此操作的贡献者还指出,它只是感觉像“非Java风格”,我是一个同意的人。Java的冗长性既可以是祝福,也可以是诅咒,但这确实使语言成为了现实。
当然,那个特定的RFE并没有结束对话。在Java 7期间,再次考虑了此功能,并创建了一些测试实现,其中包括James Gosling本人。再次,此功能最终被击落。
随着Java 8的发布,我们现在将类型推断作为lambda的一部分,例如:
List<String> names = Arrays.asList("Tom", "Dick", "Harry");
Collections.sort(names, (first, second) -> first.compareTo(second));
Java编译器能够查看方法Collections#sort(List<T>, Comparator<? super T>)
,然后查看的接口Comparator#compare(T o1, T o2)
并确定,first
并且second
应该是,String
因此允许程序员放弃必须在lambda表达式中重新声明类型。
First, the redundant type serves as valuable documentation - readers do not have to search for the declaration of getMap() to find out what type it returns
-是的,如果是的HashMap<String, Integer> map = foo.getMap()
话,我同意-在C#var
中,即使可以,我通常也不会使用这种情况。但是,如果有的话,这个论点就不会成立HashMap<String, Integer> map = new HashMap<String, Integer>()
。这是真正的冗余,我看不到必须两次写入类型名称的好处。以及我如何从编译器交叉检查中受益,我一点也不明白。
var
Java 中C#的等效功能。
Humans benefit from the redundancy
是当前问题的真正答案,因为我读过的所有论据似乎都是Java设计师提供的无缘无故的借口:C#和C ++都有此功能,C#和C ++设计师的能力不亚于Java,每个人都很高兴使用它。是什么会导致Java开发人员与C#或C ++开发人员不同?这就是为什么我同意@KonradMorawski的原因,“这是在这里完成事情的方式”似乎再次是真正的幕后原因。
好吧,首先,类型推断与运行时的成熟度无关,无论该运行时是使用了30年的CPU还是这么新的VM,这些位仍然闪闪发光。都是关于编译器的。
就是说,泛型被允许使用,非泛型类型不允许使用泛型的原因似乎是由于哲学的原因,没有什么可以阻止设计人员添加它。
更新:看起来Java 10支持它--- http://openjdk.java.net/jeps/286
据我所知,在90年代初设计Java时,类型推断在主流语言中并不流行(但是它已经是一个非常著名的概念,例如ML)。因此,我可以想象可能不支持类型推断,因为Java的目标读者是来自C ++,Pascal或其他主流语言的程序员,而这些程序员都没有。
同样,Java的设计原则之一是明确地编写东西,以确保程序员和编译器对代码有相同的理解:重复信息可减少出错的机会。当然,输入更多的字符是否值得提供它提供的额外安全性可能是一个问题,但这就是Java遵循的设计哲学:明确地编写东西。
我不知道Java是否会在将来获得类型推断,但是IMO会是该语言的一大革命(正如Glenn Nelson所提到的那样,它被描述为“非Java类”),然后人们可能还会考虑删除该语言。以新名称命名Java。
如果要通过类型推断使用JVM语言,则可以使用Scala。
我可以想到一些可能的原因。一种是显式键入是自我记录。Java通常将此优先于简洁。另一个原因可能是在类型有些含糊的情况下。就像类型或任何子类型可能满足例程一样。假设您要使用一个List,但是有人来使用ArrayList专有的方法。即使您需要编译错误,JIT也会推断一个ArrayList并继续进行。
Let's say you want to use a List, but someone comes along and uses a method exclusive to ArrayList. The JIT would infer an ArrayList and carry on even if you wanted a compilation error
-我不明白这一点。类型推断发生在实例化变量的时刻,而不是在其上调用方法。您能否举例说明您的意思?