gpt4 book ai didi

java - 为什么 Java 必须采用类型删除来保持向后兼容性?

转载 作者:太空宇宙 更新时间:2023-11-04 12:44:53 25 4
gpt4 key购买 nike

让我在这个问题前先说一下,我了解 Java 能做什么、不能做什么,并且我不会问这个问题。我想知道从 JVM 和编译器的角度来看,需要编译器按照其方式运行的实际技术挑战是什么。

每当我看到有关 java 类型删除的弱点或最令人讨厌的方面的讨论时,它似乎总是位于 Java 开发人员列表的顶部附近(对我来说!)。如果我的历史是正确的,Java 1.0 除了传递对象和重铸它们之外从未实现任何类型检查。当需要更好的类型系统时,Sun 必须在完全类型支持(这会破坏向后可比性)和采用他们选择的不会破坏旧代码的泛型解决方案之间做出决定。

与此同时,C# 也遇到了同样的问题,并采取了相反的方式,打破了向后可比性,从而在同一时间实现了更复杂的类型系统(我相信)。

我的主要问题是为什么这对于两种语言来说是一个非此即彼的问题?编译器过程意味着无法在不破坏旧代码中的向后可比性的情况下支持 C# 风格的类型处理,这是怎么回事?我理解问题的一部分在于,确切的类型在编译时并不总是已知,但乍一看似乎有时可以在编译时知道,或者可以在编译时未知并在运行时使用某种反射方法进行处理。

问题是它无法实现,还是仅仅被认为实现运行时解决方案太慢了?

更进一步,让我们使用一个简单的通用工厂代码示例作为类型删除感觉相当麻烦的地方的示例。

public class GenericFactory<FinalType, BuilderType<FinalType> extends GenericBuilder<FinalType>>{

private Class builderClass;

public GenericFactory(Class<BuilderType> builderClass){
this.builderClass=builderClass;
}

public FinalType create(){

GenericBuilder builder=builderClass.newInstance();

builder.setFoo(getSystemProperty("foo");
builder.setBar(getSystemProperty("bar");
builder.setBaz(getSystemProperty("baz");

return builder.build();
}
}

这个例子,假设我没有在某个地方搞砸语法,显示了类型删除的两个特殊烦恼,乍一看似乎它们应该更容易处理。

首先,不太相关的是,我必须添加 FinalType 参数,然后才能引用 BuilderType extends GenericBuilder,尽管 FinalType 似乎可以从 BuilderType 推断出来。我说不太相关,因为这可能更多地涉及泛型语法/实现,然后编译器限制强制类型删除。

第二个问题是,我必须将 BuilderClass 对象传递给构造函数,以便使用反射来构建构建器,尽管它已经由泛型定义了。看起来编译器存储这里使用的泛型类(只要它不使用 ? 语法)以允许反射查找泛型然后构造它是相对容易的。

既然这还没有完成,我认为有一个很好的理由没有这样做。我试图了解这些原因是什么,是什么迫使 JVM 坚持使用类型删除来保持向后兼容性?

最佳答案

我不确定你所描述的(两个“烦恼”)是类型删除的结果。

I had to add a FinalType parameter before I could refer to BuilderType extends GenericBuilder, even though it seems like FinalType could be inferred from BuilderType

BuilderType<FinalType>除非我错过了 Java 8 中的一些更改,否则它不是有效的泛型类型名称。因此它应该是 BuilderType extends GenericBuilder<FinalType>这很好。 FinalType这里无法推断,编译器应该如何知道要提供哪种类型?

The second issue is that I had to pass in my BuilderClass object to the constructor in order to use reflection to build the builder, despite it being defined by the generics already.

这不是真的。通用参数没有定义什么 FinalType实际上是。我可以创建一个 GenericFactory<String, StringBuilderType> (与 StringBuilderType extends GenericBuilder<String> )以及 GenericFactory<Integer, IntegerBuilderType> (与 IntegerBuilderType extends GenericBuilder<Integer> )。

在这里,如果您向变量定义或方法调用提供类型参数,就会发生类型删除。至于为什么可以引用Andy的评论。

但是,如果您有一个字段或子类,例如private GenericFactory<String, StringBuilderType> stringFactory ,没有类型删除。可以从反射数据中提取通用类型(不幸的是没有简单的内置方法,但请看这里: http://www.artima.com/weblogs/viewpost.jsp?thread=208860 )。

关于java - 为什么 Java 必须采用类型删除来保持向后兼容性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36431505/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com