Java 参数化在Collections.EmptyList类中如何工作?
我只是想知道执行后会发生什么:Java 参数化在Collections.EmptyList类中如何工作?,java,generics,Java,Generics,我只是想知道执行后会发生什么: List List=Collections.emptyList() 以下是收集代码: public static final List EMPTY_LIST = new Collections.EmptyList(null); public static final <T> List<T> emptyList() { return EMPTY_LIST; } private static class EmptyLi
List List=Collections.emptyList()代码>
以下是收集代码:
public static final List EMPTY_LIST = new Collections.EmptyList(null);
public static final <T> List<T> emptyList() {
return EMPTY_LIST;
}
private static class EmptyList<E> extends AbstractList<E>
implements RandomAccess, Serializable {
private EmptyList() {
}
//...
}
public static final List EMPTY\u List=new Collections.EmptyList(null);
公共静态最终列表emptyList(){
返回空的_列表;
}
私有静态类EmptyList扩展了AbstractList
实现随机访问,可序列化{
私有空列表(){
}
//...
}
当EmptyList
没有带参数的构造函数时,如何调用EmptyList(null)
请给我解释一下Collection
的方法泛型T
如何变成EmptyList
的泛型E
我只是想知道我执行后会发生什么
没有发生任何事情,因为有关泛型和类型参数的一切都在编译时进行
当EmptyList
没有带参数的构造函数时,如何调用EmptyList(null)
这是不可能的,但是我看到的JDK代码没有通过将null
传递给构造函数来创建空列表。不要相信反编译器代码
请解释集合
的方法泛型类型T
如何变成EmptyList
的泛型类型E
的过程
T
是一个类型变量,它捕获在emptyList()
的每个调用站点推断的类型。此变量被“传递”(在静态类型分析期间)到emptyList
,因此返回值的类型为List
E
是EmptyList
的类型参数的名称,该类型参数在该特定类型实例化中假定值为T
。这非常类似于当您说new ArrayList()
时,ArrayList
的E
变成String
我只是想知道我执行后会发生什么
没有发生任何事情,因为有关泛型和类型参数的一切都在编译时进行
当EmptyList
没有带参数的构造函数时,如何调用EmptyList(null)
这是不可能的,但是我看到的JDK代码没有通过将null
传递给构造函数来创建空列表。不要相信反编译器代码
请解释集合
的方法泛型类型T
如何变成EmptyList
的泛型类型E
的过程
T
是一个类型变量,它捕获在emptyList()
的每个调用站点推断的类型。此变量被“传递”(在静态类型分析期间)到emptyList
,因此返回值的类型为List
E
是EmptyList
的类型参数的名称,该类型参数在该特定类型实例化中假定值为T
。这非常类似于当您说new ArrayList()
您的反编译代码时,ArrayList
的E
变成String
:
public static final List EMPTY_LIST = new Collections.EmptyList(null);
public static final <T> List<T> emptyList() {
return EMPTY_LIST;
}
实际代码
@SuppressWarnings("unchecked")
public static final List EMPTY_LIST = new EmptyList<>();
@SuppressWarnings(“未选中”)
public static final List EMPTY_List=new EmptyList();
在实际代码中,构造函数没有参数
您的反编译代码:
public static final List EMPTY_LIST = new Collections.EmptyList(null);
public static final <T> List<T> emptyList() {
return EMPTY_LIST;
}
public静态最终列表emptyList(){
返回空的_列表;
}
实际代码:
@SuppressWarnings("unchecked")
public static final <T> List<T> emptyList() {
return (List<T>) EMPTY_LIST;
}
@SuppressWarnings(“未选中”)
公共静态最终列表emptyList(){
返回(列表)空_列表;
}
那么,至于类型T
如何变成E
?通过欺骗EMPTY_LIST
是一种原始类型,它们显式地将其强制转换为LIST
,并在创建原始EMPTY_LIST
和此显式转换时抑制警告
实际上,这是非常安全的,因为列表是空的,并且将保持为空
这个故事的寓意是:不要相信反编译器,尤其是在泛型方面,因为对于类型擦除,反编译器很难知道原始源代码中实际发生了什么。如果您想查看各种开源Java项目(包括OpenJDK)的源代码,请使用有用的(尽管速度较慢)。您的反编译代码:
public static final List EMPTY_LIST = new Collections.EmptyList(null);
public static final <T> List<T> emptyList() {
return EMPTY_LIST;
}
实际代码
@SuppressWarnings("unchecked")
public static final List EMPTY_LIST = new EmptyList<>();
@SuppressWarnings(“未选中”)
public static final List EMPTY_List=new EmptyList();
在实际代码中,构造函数没有参数
您的反编译代码:
public static final List EMPTY_LIST = new Collections.EmptyList(null);
public static final <T> List<T> emptyList() {
return EMPTY_LIST;
}
public静态最终列表emptyList(){
返回空的_列表;
}
实际代码:
@SuppressWarnings("unchecked")
public static final <T> List<T> emptyList() {
return (List<T>) EMPTY_LIST;
}
@SuppressWarnings(“未选中”)
公共静态最终列表emptyList(){
返回(列表)空_列表;
}
那么,至于类型T
如何变成E
?通过欺骗EMPTY_LIST
是一种原始类型,它们显式地将其强制转换为LIST
,并在创建原始EMPTY_LIST
和此显式转换时抑制警告
实际上,这是非常安全的,因为列表是空的,并且将保持为空
这个故事的寓意是:不要相信反编译器,尤其是在泛型方面,因为对于类型擦除,反编译器很难知道原始源代码中实际发生了什么。如果您想查看各种开源Java项目(包括OpenJDK)的源代码,请使用有用的(尽管速度较慢)。除了@MarkoTopolnik answer之外,我可以解释为什么反编译器显示null
被传递到构造函数参数中
当您创建没有显式构造函数的私有类时,字节码中会生成默认的no arg构造函数作为private:
private static class EmptyList<E> {
private EmptyList() {
}
...
}
从JVM的角度来看,没有“嵌套类”这样的东西。EmptyList
类只是另一个类(名为Collections$Emp