我不明白为什么以下代码无法编译。我已宣布扩展T
的泛型Customer
。 Customer
的类型为Customer
,那么为什么我不能在没有强制转换的情况下从此方法返回Customer
个对象?
public class CustomerExample {
public <T extends Customer> T processCustomer(Customer customer) {
return new Customer();
}
}
class Customer {
}
我得到java: incompatible types: Customer cannot be converted to T
答案 0 :(得分:4)
您需要明确投射:
public <T extends Customer> T processCustomer(Customer customer) {
return (T) new Customer();
}
当然,你需要知道运行时的这种类型转换,因为你不能这样做:
class Client extends Customer {
}
这样,以下调用将在运行时因类抛出异常而失败:
Client client = new CustomerExample().processCustomer(new Client());
那是因为运行时类不匹配。这只是意味着processCustomer
的实现必须是有效的通用(无论如何不要绑定到一个静态类型)
答案 1 :(得分:2)
假设您使用以下方法调用了方法:
Customer customer = ...
SomeCustomerSubClass c = processCustomer(customer);
在这种情况下,编译器希望processCustomer
返回SomeCustomerSubClass
,因此不允许processCustomer
返回Customer
。
如果要返回Customer
实例,您应该问自己为什么要首先使用泛型类型参数。
答案 2 :(得分:2)
请记住,作为方法的作者,您无法确定方法的通用参数是什么。您无法断言T
必须 Customer
。来电者可以。
在您的情况下,您将T
限制为Customer
或Customer
本身的子类。然而,您返回Customer
的实例。如果调用者将T
指定为AngryCustomer
(Customer
的子类),则会产生矛盾。调用者希望您返回AngryCustomer
但是您返回了Customer
!
要解决此问题,您可以将extends
更改为super
,以便T
可以是Customer
或Customer
本身的任何超类。现在一切都有道理。如果来电者指定T
为Object
,则Customer
类型与Object
兼容,但与AngryCustomer
不兼容。
或者,根本不要使用泛型。您当前对此方法的实现似乎不适合通用。
答案 3 :(得分:2)
T
延伸Customer
但Customer
不会延伸T
。
在您的实际代码中:
public <T extends Customer> T processCustomer(Customer customer) {
return new Customer();
}
在一个方法中返回一个超类实例(Customer
),该方法将返回类型声明为它的子类(T
)。
没有向下转换它是无效的,因为将超类变量分配给子类变量是无效的,例如:
T t = customer;
你应该写:
T t = (T)customer;
因此,您还需要在此处转换为T
:
public <T extends Customer> T processCustomer(Customer customer) {
return (T) new Customer();
}
答案 4 :(得分:0)
很简单,客户不实施 T
e.g。让我们创建T:
class T extends Customer {
int i;
public T(int i) {
this.i = i;
}
}
您希望如何使用客户创建 T ?这是不可能的。