Java 当我们在泛型类中还需要一个参数时,菱形操作符会做什么? 类GenericBase{ 私有T基变量; 公共部门得不到{ 返回基变量; } 公共无效集(T){ baseVariable=t; } } 类GenericSubTwo扩展了GenericBase{ 私有V子变量2; 公共V get2(){ 返回子变量2; } } 公共测试类{ 公共静态void main(字符串[]args){ GenericBase sub2=新的GenericSubTwo(); } }

Java 当我们在泛型类中还需要一个参数时,菱形操作符会做什么? 类GenericBase{ 私有T基变量; 公共部门得不到{ 返回基变量; } 公共无效集(T){ baseVariable=t; } } 类GenericSubTwo扩展了GenericBase{ 私有V子变量2; 公共V get2(){ 返回子变量2; } } 公共测试类{ 公共静态void main(字符串[]args){ GenericBase sub2=新的GenericSubTwo(); } },java,generics,Java,Generics,在这种情况下,菱形操作符是否真的生成了新的GenericSubTwo(); 或者别的什么。。我不明白发生了什么,因为在GenericSubTwo中,我需要两个参数。这真的没关系,因为您无论如何都看不到V是什么 V推断为对象,因为这是V上的边界 更新 实际上,似乎V被推断为?,因为它可以被转换为任何对象 GenericBase sub2=新的GenericSubTwo(); //有效强制转换:T必须是整数,但V可以是任何值 GenericSubTwo x=(GenericSubTwo)sub2;

在这种情况下,菱形操作符是否真的生成了新的GenericSubTwo();
或者别的什么。。我不明白发生了什么,因为在GenericSubTwo中,我需要两个参数。

这真的没关系,因为您无论如何都看不到
V
是什么

V
推断为
对象,因为这是
V
上的边界

更新

实际上,似乎
V
被推断为
,因为它可以被转换为任何对象

GenericBase sub2=新的GenericSubTwo();
//有效强制转换:T必须是整数,但V可以是任何值
GenericSubTwo x=(GenericSubTwo)sub2;
“钻石操作员在这种情况下真的会做出新的GenericSubTwo()吗?”;"

不,那不是真的

“或者其他什么”

是的。其他的东西。而“其他的东西”是
对象
。这是因为


因此,实际的参数化类型应该是
GenericSubTwo()
,就像你做的那样
GenericBase sub2=new-GenericSubTwo()
这是一个哲学问题,因为在编译的字节码中,
new-GenericSubTwo()
new-GenericSubTwo()
新的GenericSubTwo()
。因此,如果您说它使用了特定的类型参数,但不影响结果,那么它真的存在吗

请记住,对象在运行时不知道其泛型类型参数,因此在运行时创建对象时,您不需要知道泛型类型参数。
new
中提供的泛型类型参数仅在编译时用于类型检查(例如,检查与参数类型(如果有)的一致性,并检查该返回类型是否有效)。在类型检查之后,这些类型参数不再重要,因为它们不会被发送到编译的字节码中。在这种特殊情况下,由于构造函数没有参数,并且返回值被分配给
GenericBase
,其中
GenericSubTwo
V
未使用,因此对w没有限制帽子
V
可以是

因此,我们可以考虑编译器使用菱形来考虑对象创建表达式的不同方式:

  • 编译器可以尝试为每个类型参数“推断”某些确切的类型参数,并检查该选择是否与参数和返回上下文一起工作;或者
  • 编译器可以尝试证明存在至少一个类型参数选项,使其能够编译并进行类型检查,并且只要它能够证明至少存在一个类型参数选项,它就不需要选择它是哪一个类型参数,因为在发出字节码时不使用实际的类型参数

我很确定它是
,尽管我找不到任何关于这方面的文档。这很重要,因为你可以使用
(GenericSubTwo)sub2
@昆仑是一个原始类型的转换,所以它仍然不重要,因为没有
V
。实际上,似乎
V
被推断为
,因为它可以转换为任何东西…-引用变量
sub2
可以“转换为任何东西”。但当我刚刚做
x.set(“666”)时
在一个测试您的示例的实验中,我得到:“
不兼容的类型:java.lang.String不能转换为java.lang.Integer”
?您认为这是为什么?TIA。@dedupler 1)
sub2
不能强制转换为任何对象,例如,is不能强制转换为
GenericSubTwo
,因为
T
必须是
Integer
——2)它失败,因为
T
Integer
并且方法是
set(T)
,所以它与这个问题没有任何关系,这个问题是关于
V
@dedupler你在讨论
列表
列表
之间的区别,所以你基本上是在问:泛型的好处是什么。对于这个问题,这完全是离题的。
class GenericBase<T> {
    private T baseVariable;
    
    public T get() {
        return baseVariable;
    }
    
    public void set(T t){
        baseVariable = t;
    }
}
class GenericSubTwo<T, V> extends GenericBase<T>{

    private V subVariable2;
    
    public V get2(){
        return subVariable2;
    }
}


public TestClass{

public static void main(String[] args){
GenericBase<Integer> sub2 = new GenericSubTwo<>();
}
}