Java 为什么擦除会使函数类型的实现复杂化?

Java 为什么擦除会使函数类型的实现复杂化?,java,generics,language-design,type-erasure,Java,Generics,Language Design,Type Erasure,我从报纸上读到: 例如,将擦除作为泛型的一部分,向编程语言中添加函数类型要困难得多 编辑: 我在Brian Goetz的文章中也遇到过类似的陈述,他说Lambda只是带有语法糖的匿名类,更容易处理: 但我对函数类型的反对并不是因为我不喜欢函数类型——我喜欢函数类型——而是因为函数类型与Java类型系统的一个现有方面——擦除(erasure)打得很糟糕。删除的函数类型是两个世界中最糟糕的。所以我们从设计中删除了这个 有人能解释这些说法吗?为什么我需要lambdas的运行时类型信息?我认为他在该语句

我从报纸上读到:

例如,将擦除作为泛型的一部分,向编程语言中添加函数类型要困难得多

编辑: 我在Brian Goetz的文章中也遇到过类似的陈述,他说Lambda只是带有语法糖的匿名类,更容易处理:

但我对函数类型的反对并不是因为我不喜欢函数类型——我喜欢函数类型——而是因为函数类型与Java类型系统的一个现有方面——擦除(erasure)打得很糟糕。删除的函数类型是两个世界中最糟糕的。所以我们从设计中删除了这个


有人能解释这些说法吗?为什么我需要lambdas的运行时类型信息?

我认为他在该语句中的意思是,在运行时Java无法分辨这两个函数定义之间的区别:

void doIt(List<String> strings) {...}
void doIt(List<Integer> ints) {...}
void doIt(列表字符串){…}
void doIt(列表整数){…}
因为在编译时,有关列表包含的数据类型的信息会被删除,因此运行时环境无法确定要调用哪个函数

尝试在同一类中编译这两个方法将引发以下异常:

doIt(List<String>) clashes with doIt(List<Integer); both methods have the same erasure

doIt(List)与doIt(List)冲突的是,我的理解是,他们决定,由于擦除,采用函数类型(例如C#中的委托)的方式将变得很混乱,他们只能使用lambda表达式,这只是对单个抽象方法类语法的简化

C#中的代表:

(这里是另一个样本 )

他们在Lambda项目文件中提出的一个论点:

泛型类型将被删除,这将暴露其他位置 开发人员面临擦除的风险。例如,不会 可以重载方法m(T->U)和m(X->Y),这将是 令人困惑

第2节:

(最终的lambda表达式语法与上述文档略有不同: )

总而言之,我最清楚的理解是,只有一部分语法材料可以,实际上会被使用。 Neal Gafter最可能的意思是,不能使用委托将使标准API更难适应功能风格,而不是说javac/JVM更新更难完成


如果有人比我更了解这一点,我会很乐意阅读他的帐户。

可能是因为你真正想要的是一个类型
函数
,它由一个返回类型和一些参数类型序列参数化。但是由于擦除,你不能有一个像
p..
这样的构造,因为它只能将nto
对象[]
,该对象过于松散,无法在运行时大量使用


这纯粹是猜测。我不是一个类型理论家;我甚至没有在电视上玩过一个类型理论家。

Goetz在以下方面展开了推理:

函数类型的替代(或补充)方法, 根据一些早期的建议,可能会引入一种新的, 结构函数类型。类似于“字符串和 对象到int”可以表示为(字符串,对象)->int 这个想法被考虑并拒绝了,至少目前是这样,原因有好几个 缺点:

  • 这将增加类型系统的复杂性,并进一步混合结构和名义类型
  • 这将导致库样式的差异一些库将继续使用回调接口,而另一些库将使用结构化接口 函数类型
  • 语法可能不合适,尤其是当包含检查异常时
  • 每个不同的函数类型都不可能有运行时表示,这意味着开发人员将进一步暴露于 并且受到擦除的限制。例如,这是不可能的(也许 令人惊讶的是)重载方法m(T->U)和m(X->Y)
因此,我们选择了“使用你所需要的” 知道”-由于现有库广泛使用功能接口, 我们编纂并利用这一模式

为了举例说明,下面是JavaSE7中的一些功能接口 非常适合与新的语言特性一起使用; 下面的例子说明了其中几个的用法

  • java.lang.Runnable
  • java.util.concurrent.Callable
  • java.util.Comparator
  • java.beans.PropertyChangeListener
  • java.awt.event.ActionListener
  • javax.swing.event.ChangeListener

请注意,擦除只是考虑因素之一。一般来说,Java lambda方法与Scala的方向不同,不仅仅是类型问题。它非常以Java为中心。

-1这与问题无关。注释是关于函数类型(即:)它回答了他提出的为什么泛型使函数类型更难的问题。这不是问题所要问的。函数类型
!=
函数(方法)这两种方法是否能够过载是编译时的问题。@Anthony,考虑到缺乏“正确的理解”,你的第一个评论给人的印象是相当傲慢的似乎是你的-你会考虑编辑或删除它?这将是更好的回答一个伟大的问题-我一直在想同样的事情后,Goetz的评论。方法重载泛型的参数是一个正交的问题,以运行时化,相反,某些不正确的断言。如果用更多的方法使语言复杂化(众所周知,Java泛型类型系统并没有那么简单)。@MarianP那么你的意思是函数类型只是抱怨类型擦除的另一个原因吗?是的。让开发人员抱怨/迷惑他们更多。至少从我收集的信息来看。也包括在内
public delegate void DoSomethingDelegate(Object param1, Object param2);
...
//now assign some method to the function type variable (delegate)
DoSomethingDelegate f = DoSomething;
f(new Object(), new Object());
(x, y) => { System.out.printf("%d + %d = %d%n", x, y, x+y); }