- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我对阅读用 Java 编写的这篇文章有疑问 tutorial :
In the introduction, we saw invocations of the generic type declaration List, such as List. In the invocation (usually called a parameterized type), all occurrences of the formal type parameter (E in this case) are replaced by the actual type argument (in this case, Integer).
但如果没有限制形式类型参数不被Object代替?为什么说E换成Integer?
此外,here ,在 Java 教程中说:
To reference the generic Box class from within your code, you must perform a generic type invocation, which replaces T with some concrete value, such as Integer:
但是,再次感谢删除,盒子类中的编译时间 T 被替换了按对象而不是整数。整数类型仅用于转换操作。
其实还是一样的tutorial据说:
During the type erasure process, the Java compiler erases all type parameters and replaces each with its first bound if the type parameter is bounded, or Object if the type parameter is unbounded.
我真的很困惑。哪个是真相?T
是替换为 Integer
还是替换为 Object
?
最佳答案
你们说的是不同的东西。
教程中的引文谈到类型实例化。这与类型删除无关,后者是一个恕我直言的错误命名概念,只是意味着泛型类型在运行时不再可用。
但在编译时它们是,并且实例化发生在编译时。
要回答您的问题,“在编译时”是一个宽泛的概念。以下内容全部发生在编译时:
请注意,该列表绝不是完整的。但是,如您所见,在类型检查期间,编译器知道您的类型实例化并可以检查它们。
稍后,它发出字节码,由于字节码无法表示泛型,类型被“删除”,这意味着,强制转换被插入到各处。
因此,您认为“编译时间”是某种程度上所有事情同时发生的瞬间的假设是不正确的。
进一步编辑:
我认为您从字面上理解了所有这些(即“替换”一词)。当然,编译器有一些数据结构,其中保存了程序中所有项目的类型、名称和范围。
看,原则上很简单,如果我们有:
static <X> List<X> meth(X[] arr) { .... }
稍后,您会:
Integer arr = new Integer[100];
List<Integer> list = meth(arr);
Integer foo = list.get(1);
然后你正在实例化 meth 方法的类型:
static List<Integer> meth(Integer[] arr) { .... }
泛型的重点是说 meth
适用于任何类型。这正是编译器检查的内容。它会知道,对于 所有 X,如果您传递一个 X 数组,您将返回一个 X 列表,因此,由于您传递了 Integer[],结果必须是 List<Integer>
和 list
分配是正确的。此外,编译器知道,对于所有 X **,如果您从 List<X>
中获取元素, 它将是一个 X。
因此,编译器注意到并检查 foo 是一个 Integer
.稍后,在代码生成时,它将插入一个到 Integer 的转换,因为由于类型删除,List.get 的返回值是 Object。
另请注意,“替换”并不意味着编译器以某种方式更改您的代码。它只是从通用类型签名创建(可能是临时的)一个非通用类型签名(通过替换 - 如果你更喜欢这个 - 所有类型参数及其实际类型),并使用它来检查类型。
这就像在数学中,如果我说:请将 a 替换为 42 并检查等式是否正确:
一个 + 1 = 43
那么问这个替换发生的“确切位置”是没有意义的。很可能在您的大脑中。
关于java - 通用和删除过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19834369/
我使用 AppFuse 创建项目已经有一段时间了。我已经知道有两种方法可以开发 DAO 和 Manager 类: GenericDao/GenericManager 方法 UniversalDao/U
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
在普通的单线程程序中,捕获异常只需要通过try ... catch ... finally ...代码块就可以了。那么,在并发情况下,比如在父线程中启动了子线程,如何在父线程中捕获来自子线程的异常,
假设我有一个这样的界面 interface Example { first_name: string, last_name: string, home_town: string
我已经成为 hg 用户几年了,对此我很高兴! 我必须开始一个我以前从未做过的项目。我们的想法是开发一个具有批处理模式和 GUI 的软件。 因此,批处理模式和 GUI 模式都有共同的源,但每种模式也都包
我可以在Silverlight中使用generic.xaml来设置应用程序中所有TextBlock的样式吗? 我原以为它会起作用,但它没
顶部 map 有 3 个子 map ,每个子 map 都有不同的对象。 像下面的代码,如何将通用添加到 map 顶部? Map top = new ConcurrentHashMap();
我想创建一个hashmap,其中键是接口(interface)A,值是接口(interface)B。然后我想用实现A和B的类来初始化它。是否可以使用java泛型来做到这一点? 也就是说,我想要类似的东
Enum 位于 java.lang.Enum 中,Object 位于 java.lang.Object 中>。那么,为什么 Enum 不是 Object 呢? (我收到一个java.lang.Clas
我有一种方法,check,它有两个 HashMap 作为参数。这些映射的键是 String,值是 String 或 Arraylist。 哪个是更好的解决方案: public static boole
我启动了针对iPhone的应用程序,现在我也想将其应用程序用于iPad。当我开始做iPhone项目时,即使我添加了iPad xib,它也无法正确显示,如何转换我的项目同时适用于iPhone和iPad(
这行代码(代码1)有什么区别 auto l1 = [](auto a) { static int l = 0; std::cout operator() for type const char*) 被
使用 Generic#to,我可以获得 case class 的 HList 表示: import shapeless._ case class F(x: Int, y: String) scala>
我有一个 BiDiMap 类。如何使其通用,不仅接受 String 而且接受 Object 类型的对象作为输入参数,同时保持所有原始函数正常工作。例如,我希望能够使用函数 put() 和 Object
我在编译 foreach 循环时遇到问题。我很确定这是我的泛型处理的问题,因为该错误是对象兼容性问题。我已搜索解决方案,但找不到任何可以解决该问题的内容。 这是定义 Iterable adjList
大约有 6 个 POJO 类(域实体、DTO、DMO)都具有几乎相同的字段。为了从一个对象转换为另一个对象,我传递一个对象并调用它的 getter 将其设置到另一个对象中。 private UserT
有没有什么方法可以创建一个通用的 for 循环,它可以正确地循环遍历数组或对象?我知道我可以编写以下 for 循环,但它也会遍历将添加到数组的其他属性。 for (item in x) { co
我已经有一段时间没有写js了,显然有点生疏了。试图理解以下问题。 getCurrentPosition successCallback 中的警报正确显示纬度,但最后一行警报未定义。为什么我的 clie
请帮助我,我从来没有用 xib 为 iPhone/iPad 制作过通用的 UIViewControllers。如何使用 .m 和 .h 文件以及 _iphone.xib 和 _ipad.xib 创建类
我正在尝试创建一个 createRequest 函数,我可以将其重新用于我的所有网络调用,有些需要发布 JSON 而其他则不需要,所以我正在考虑创建一个采用可选通用对象的函数;理论上是这样的: str
我是一名优秀的程序员,十分优秀!