- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
让我在这个问题前先说一下,我了解 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/
我感到困惑...... 我在 .jsp 中编写了一个小例程。最后需要关闭ResultSet、Statement和Connection。我也在finally { }中编写了结束代码,但是当页面运行时,它
我在 Stack Overflow 上读到一些 C 函数是“过时的”或“应该避免”。你能给我一些这种功能的例子以及原因吗? 这些功能有哪些替代方案? 我们可以安全地使用它们 - 有什么好的做法吗? 最
我正在构建一个应用程序,它可以拍照、显示图片,然后一旦被点击,就会在点击的任何地方返回图片的颜色。 它在崩溃之前到达了水龙头。我得到 x 必须是 < bitmap.width() 的错误 就我的理解而
我试图根据几个因素向用户提出建议: •建议只能是同一所大学的学生•建议必须至少匹配一个其他字段 我以为我有它,但问题是这个查询将返回同一所学校的所有学生,而不管其他情况: PUT /user/.per
我的应用程序必须从第三方读取 SSL 网址。我如何最好地将第三方凭证存储在我自己的数据库中,以保护第三方凭证不被泄露?兼顾绝对的安全性和实用性。对凭据进行单向哈希处理没有用,因为我必须将凭据恢复为明文
在我的 Rails API 中,我希望 Mongo 对象作为 JSON 字符串返回,Mongo UID 作为“id”属性而不是“_id”对象。 我希望我的 API 返回以下 JSON: { "
假设应用层协议(protocol)是通过UDP实现的。客户端需要超时,因此服务器需要保留与其通信的每个客户端的状态。 还假设使用了select。 实现多线程服务器总是最好的吗?我认为链接列表也会做同样
考虑一个非常短的程序,我在其中分配了一点内存。我被告知,GC 在程序分配大量内存并且分配达到限制的情况下运行。 我不知道这个限制到底是多少,但我认为它必须足够高,这样 GC 才不会频繁运行并减慢程序的
根据 Cocoa with Love当应用程序需要 WiFi(而不是蜂窝网络)时需要可达性,例如如果应用加载大量视频并且不适合在 3G 网络上使用。 我的应用程序使用互联网,无论是 WiFi 还是 3
我正在寻找更好的解决方案来解决我面临的这个问题。 如果您将鼠标悬停在缩略图上,它会淡出较大的镜头并淡入新的镜头,这很好,但是当转到目标缩略图并且您的鼠标再悬停一些时,它会更改为您的鼠标经过并拍摄的其他
启用 UAC 并使用管理帐户登录后,您将获得两个 token : 提升的 token ;这已启用 Administrators 组,具有高完整性(即强制性完整性标签 SID 为 S-1-16-1228
我想知道在 React 中创建动态选择组件的规范方法是什么。我是否必须创建一个单独的组件来根据下面的代码返回选项,以便能够通过每个条目的 props 自定义值,然后将它们包含到单独的选择组件中? p>
我有一个启用了分页的数据网格。我根据过滤条件在数据网格中显示结果。我已经过滤了数据,现在有 2 页。当我转到第二页时。我正在再次执行搜索功能以缩小结果范围。然后我收到类似“无效的 CurrentPag
我有原始文本列,其值类似于“2012-07-26T10:33:34”和“2012-07-26T10:56:16”。在使用 Joda-Time 的 Java 中,我可以通过调用 轻松地将其转换为日期/从
您好,我被分配了一项棘手的任务。我需要让一个方形 div 到达顶部的一个点。基本上它看起来像一个正方形 div,顶部有一个宽三 Angular 形。请参阅下面的屏幕截图。顶部的深蓝色只是堆叠在白色 d
我想知道,为什么我们在 android 中使用不同的启动器图标(大小)。目前您“必须”将图标大小调整为: LDPI - 36 x 36 MDPI - 48 x 48 HDPI - 72 x 72 XH
在 SO 的几个地方,声称必须知道对象的确切类型并基于此做出决定(以 if-then-else 方式)指向一个设计缺陷,例如here . 我想知道是否总是如此。在当前的一个小型教育项目(我正在使用它来
据我了解,迭代器是一种为客户端提供接口(interface)以观察/迭代/传递自定义集合等内容的机制,而不破坏信息隐藏原则。 STL 容器有自己的迭代器,所以我们可以毫无问题地对它们使用 for (
我在 Golang 中编写了一个包装函数,用于从多个文件中渲染模板,如下所示: func RenderTemplate(w http.ResponseWriter, data interface{},
据我了解,size_type 和 difference_type 的目的不仅仅是符号——它也是为了解决例如分段架构等,它们可能具有不同的大小。 在这种情况下,如果我有一个带有随机访问迭代器的容器,那么
我是一名优秀的程序员,十分优秀!