不能 return 从泛型方法对象
Cannot return object from generic method
我不明白为什么以下代码无法编译。我已经声明了扩展 Customer
的泛型类型 T
。 Customer
是 Customer
类型,所以为什么我不能 return 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
您需要显式转换:
public <T extends Customer> T processCustomer(Customer customer) {
return (T) new Customer();
}
当然,您需要注意运行时的这种类型转换,因为您不能这样做:
class Client extends Customer {
}
这样,以下调用将在运行时失败并出现 class 转换异常:
Client client = new CustomerExample().processCustomer(new Client());
那是因为运行时 classes 不匹配。这只是意味着您的 processCustomer
实现必须有效地通用(无论如何都不能绑定到一种静态类型)
假设您调用了您的方法:
Customer customer = ...
SomeCustomerSubClass c = processCustomer(customer);
在那种情况下,编译器期望 processCustomer
到 return 一个 SomeCustomerSubClass
,所以它不允许你的 processCustomer
到 return 一个 Customer
.
如果您正在 return 创建一个 Customer
实例,您应该问自己为什么首先要使用泛型类型参数。
请记住,作为方法的作者,您无法决定方法的通用参数是什么。你不能断言 T
一定是 Customer
。来电者可以。
在您的例子中,您将 T
限制为 Customer
或 Customer
本身的子类。然而你 return 是 Customer
的实例。如果调用者将 T
指定为 AngryCustomer
(Customer
的子类),则会产生矛盾。来电者希望您 return 一个 AngryCustomer
但您 return 一个 Customer
!
要解决此问题,您可以将 extends
更改为 super
,以便 T
可以是 Customer
或 Customer
本身的任何超类。现在一切都说得通了。如果调用者指定T
为Object
,则Customer
类型兼容Object
,但不兼容AngryCustomer
。
或者,根本不要使用泛型。您当前对该方法的实现似乎不适合通用。
T
扩展了 Customer
但 Customer
没有扩展 T
。
在您的实际代码中:
public <T extends Customer> T processCustomer(Customer customer) {
return new Customer();
}
你 return 一个超级 class 实例 (Customer
) 在声明为 returned 的方法中键入它的子class (T
).
没有向下转型是无效的,因为将超级 class 变量分配给子 class 变量是无效的,例如 :
T t = customer;
你应该写:
T t = (T)customer;
因此您还需要在此处转换为 T
:
public <T extends Customer> T processCustomer(Customer customer) {
return (T) new Customer();
}
很简单,客户不执行T
例如让我们像这样创建 T:
class T extends Customer {
int i;
public T(int i) {
this.i = i;
}
}
您想如何使用 Customer 创建 T?不可能。
我不明白为什么以下代码无法编译。我已经声明了扩展 Customer
的泛型类型 T
。 Customer
是 Customer
类型,所以为什么我不能 return 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
您需要显式转换:
public <T extends Customer> T processCustomer(Customer customer) {
return (T) new Customer();
}
当然,您需要注意运行时的这种类型转换,因为您不能这样做:
class Client extends Customer {
}
这样,以下调用将在运行时失败并出现 class 转换异常:
Client client = new CustomerExample().processCustomer(new Client());
那是因为运行时 classes 不匹配。这只是意味着您的 processCustomer
实现必须有效地通用(无论如何都不能绑定到一种静态类型)
假设您调用了您的方法:
Customer customer = ...
SomeCustomerSubClass c = processCustomer(customer);
在那种情况下,编译器期望 processCustomer
到 return 一个 SomeCustomerSubClass
,所以它不允许你的 processCustomer
到 return 一个 Customer
.
如果您正在 return 创建一个 Customer
实例,您应该问自己为什么首先要使用泛型类型参数。
请记住,作为方法的作者,您无法决定方法的通用参数是什么。你不能断言 T
一定是 Customer
。来电者可以。
在您的例子中,您将 T
限制为 Customer
或 Customer
本身的子类。然而你 return 是 Customer
的实例。如果调用者将 T
指定为 AngryCustomer
(Customer
的子类),则会产生矛盾。来电者希望您 return 一个 AngryCustomer
但您 return 一个 Customer
!
要解决此问题,您可以将 extends
更改为 super
,以便 T
可以是 Customer
或 Customer
本身的任何超类。现在一切都说得通了。如果调用者指定T
为Object
,则Customer
类型兼容Object
,但不兼容AngryCustomer
。
或者,根本不要使用泛型。您当前对该方法的实现似乎不适合通用。
T
扩展了 Customer
但 Customer
没有扩展 T
。
在您的实际代码中:
public <T extends Customer> T processCustomer(Customer customer) {
return new Customer();
}
你 return 一个超级 class 实例 (Customer
) 在声明为 returned 的方法中键入它的子class (T
).
没有向下转型是无效的,因为将超级 class 变量分配给子 class 变量是无效的,例如 :
T t = customer;
你应该写:
T t = (T)customer;
因此您还需要在此处转换为 T
:
public <T extends Customer> T processCustomer(Customer customer) {
return (T) new Customer();
}
很简单,客户不执行T
例如让我们像这样创建 T:
class T extends Customer {
int i;
public T(int i) {
this.i = i;
}
}
您想如何使用 Customer 创建 T?不可能。