作者:哈哈 | 来源:互联网 | 2022-12-08 19:25
当我尝试编译以下代码时,编译失败并出现以下错误.我不知道为什么它应该,因为我只返回一个实现合同的类
public interface Contract {
static T get() {
return new ConcreteContract();
}
}
class ConcreteContract implements Contract {
}
Contract.java:3: error: incompatible types: ConcreteContract cannot be converted to T
return new ConcreteContract();
^
where T is a type-variable:
T extends Contract declared in method get()
1 error
有没有人知道为什么java表现这种方式(或)我错过了一些明显的东西
PS:在发布此查询之前,我已在SO中阅读了超过10个热门搜索
1> Eran..:
由于您的方法返回泛型类型T
,并且T
可以是任何实现的类Contract
,因此可以使用以下方法调用它(例如)
OtherConcreteContract variable = Contract.get();
并且您不能将a赋值ConcreteContract
给OtherConcreteContract
变量(假设ConcreteContract
不是子类OtherConcreteContract
).
要避免该错误,您应该返回接口类型:
static Contract get() {
return new ConcreteContract();
}
或具体类型:
static ConcreteContract get() {
return new ConcreteContract();
}
前者(返回接口类型)通常是更好的选择.
仿制药在这里没有帮助你.
@AshokKoyi当你让你的方法有一个泛型返回类型时,你允许方法的调用者决定那个类型是什么.因此,您的方法必须返回一个匹配调用者可能做出的任何选择的实例.如果调用者选择将此方法的结果分配给某个其他类型的变量(也实现接口),则返回`ConcreteContract`实例不起作用.
`new ArrayList <>`对运行时没有影响,它只是让你不再重复已经用变量类型声明的东西,如果你使用`<>`而不是具体的话,隐式地认为你的意思是相同的泛型类型.在你的情况下,你正在调用一种方法.如果您没有为其提供在运行时告诉它的参数,则此方法无法猜测其调用者希望您执行的操作.
@AshokKoyi更多的是泛型和推理,而不仅仅是或多或少聪明.Java的泛型是一种完全编译时类型的安全验证工具,而大多数语言将其泛型定义为运行时工具,具有其优点和不便之处.但无论如何,如果你更喜欢打字稿而不是Java,那么只需使用它就是一个非常好的选择.
泛型没有其他目的,只有编译器拒绝这样的程序.它们的存在纯粹是为了帮助确保类型安全,而且你坚持不关心类型安全,因此不尊重它.因此,仿制药只存在于您所做的事情被拒绝.编译器绝对不能知道它在运行时是有效的,因为如果调用者期望一个显然会失败的OtherConcreteClass,它在运行时很可能无效.该消息很有用:事实上,ConcreteClass无法转换为T,它就是这样说的.