无法从通用方法

时间:2018-04-24 06:12:53

标签: java generics extends

我不明白为什么以下代码无法编译。我已宣布扩展T的泛型CustomerCustomer的类型为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

5 个答案:

答案 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限制为CustomerCustomer本身的子类。然而,您返回Customer的实例。如果调用者将T指定为AngryCustomerCustomer的子类),则会产生矛盾。调用者希望您返回AngryCustomer但是您返回了Customer

要解决此问题,您可以将extends更改为super,以便T可以是CustomerCustomer本身的任何超类。现在一切都有道理。如果来电者指定TObject,则Customer类型与Object兼容,但与AngryCustomer不兼容。

或者,根本不要使用泛型。您当前对此方法的实现似乎不适合通用。

答案 3 :(得分:2)

T延伸CustomerCustomer不会延伸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 ?这是不可能的。