Java中的类型推断(àlaC#)

Ion*_*tan 12 java generics type-inference

自从我听说类型推断(在Haskell中)以来,我就认为Java恰恰相反,即它没有类型推断.最近,我有一个aha时刻,并意识到Java在其泛型实现中使用类型推断.

然后,我读了Gilad Bracha的两篇论文(根据我的理解,这是Java中泛型实现背后的人之一).第一篇论文是关于泛型(PDF)的教程,其中他明确表示编译器将推断用于替换格式类型参数的实际类型参数.那么,Java中有类型推断,但为什么只有泛型,为什么不能像C#的var关键字?这是我的问题.

为什么Java没有内置到编译器中的更多类型推断?

我会建议一个答案,这与我读到的第二篇论文" Pluggable Type Systems(PDF)"有关.看来,Gilad Bracha认为推理部分不应该是编译器的一部分,而是IDE功能或类似功能(上述论文中的第4节第6段):

更好的工程方法是将类型推断实现为IDE中提供的单独工具.发现输入类型注释令人厌烦的程序员可以根据需要调用推理器.

你怎么看?

hui*_*ker 2

好吧,我认为Java 中的类型推断主要是出于历史原因:为了适合具有强大遗留约束的语言,Java 的改进是谨慎且渐进的(正如 JCP所示,尽管类型推断的一些改进设法完成)。有了仿制药,历史悠久的GJ实现在包含在 Java\xc2\xa05 中之前经过了彻底的评估。

\n\n
\n

在 Java 5 发布之前,Java 中没有类型推断。(...) 当 Java 5 中引入泛型 (...) 时,该语言保留了对变量、方法和分配的这种要求。但是多态方法(按类型参数化)的引入决定了要么(i)程序员在每个多态方法调用站点提供方法类型参数,要么(ii)语言支持方法类型参数的推断。为了避免给程序员带来额外的文书负担,Java 5 的设计者选择执行类型推断来确定多态方法调用的类型参数。(来源

\n
\n\n

但这并不意味着 Java 中存在强大的普遍类型推断文化。根据规格

\n\n
\n

另请注意,类型推断不会以任何方式影响健全性。如果推断的类型无意义,则调用将产生类型错误。类型推断算法应被视为一种启发式算法,旨在在实践中表现良好。如果无法推断出所需的结果,则可以使用显式类型参数。

\n
\n\n

我确实认为 Java 的更多类型推断将是一个福音(Scala 已经是这方面的一个非常有趣的改进)。恕我直言,类型推断使类型检查器的反馈循环变得不那么机械,同时也同样健全,让您编写更少的类型,但让您进行同样多的类型检查。由于类型的一个主要好处是指导程序搜索的心理过程(“让您在类型良好的程序空间中编写,而不是在 ascii 字符的空间中编写”),因此与类型检查器交互的这种舒适感似乎是无价的:你需要一个类型检查器来验证你的思维是否正确,并训练你这样做,而不是让你在每一行都考虑它。

\n\n

现在,类型推断应该发生在哪个阶段是另一个问题。我认为希望将“推理器”与运行时分开可以解决遗留问题:它避免要求您拥有始终向后兼容的类型推理算法。但关键就变成了你的标准/主要库的样子:你发布并与其他人交换的源代码是否带有注释?

\n\n

虽然无论推理引擎的强度如何,带注释的源都可以进行有价值的类型检查,但我仍然希望编译器中有一个类型推理器,因为这不仅仅是我不这样做不想 List<CacheDecoratorFactory> cacheDecoratorFactories = new ArrayList<CacheDecoratorFactory>();,只是不想。就此而言,当我重构预先存在的源代码时,我也不想处理它。在与源交互之前,我需要一个类型“隐藏器”来擦除注释,但是如果类型推断引擎不完整,那么要擦除哪些注释以及确保擦除之后的类型重建是双射的问题就会变得棘手(特别是如果你的推理引擎不返回主要类型)...如果我们无论如何都必须解决一个棘手的问题,为什么不让它成为一个好的、尽可能完整的类型推理算法呢?我的预感是,超过一定的质量水平(特别是返回类型的通用性),遗留问题将开始消失。

\n