如何返回泛型类型的子类

时间:2016-07-24 17:53:15

标签: java generics wildcard generic-programming

我有这个课程:

public abstract class Parent {}
public class Child extends Parent{}

我创建了类Connector,我希望T类型将采用Parent的子类:

public class Connector <T extends Parent>{
    T t;
    public Connector(T t){
        this.t=t;
    }
    public T getObject(T t){
        Child p = new Child();
        return (T) p;       
    }
}

实现:

Child c1  = new Child();
Connector<Parent> cConnector = new Connector<Parent>(c1);
Child c2 = cConnector.getObject(c1); 

一切都与演员合作,但我不明白为什么我必须在getObject方法中添加一个强制转换,如果T扩展为父

4 个答案:

答案 0 :(得分:0)

您在Child p中引入的本地T变量与通用类型Connector之间没有任何关联。 T t方法中未使用字段T t和参数getObject,因此需要显式cat。

如果您提供以下getObject实施:

public T getObject(){
    return t;       
}

不再需要演员了。

答案 1 :(得分:0)

问题是T假定与Child类没有任何关联。创建另一个名为Pet的类,其扩展为Parent

public class Pet extends Parent{
    ...
}

现在让我们重新审视您的getObject方法。用Pet

替换T的所有实例

总的来说,我们现在有了

Pet p  = new Pet();
Connector<Pet> cConnector = new Connector<Pet>(p);

在Connector类中,

//** symbol is used as placeholder, not actually part of the code
public *Pet* getObject(*Pet* t){
    Child p = new Child();
    return (*Pet*) p;       
}

需要演员表的原因是无法保证PetChild相关。如果省略了强制转换,那么当返回类型为Child时,将返回类型为Pet的对象,这会导致错误,因为Pet不等于{{1} }。如果你想返回Child类型的新对象,那么我建议你做这样的事情(因为你之前没有使用它,所以可以省略参数),

Child

public Child getObject(){
     Child p = new Child();
     return p;
}

答案 2 :(得分:0)

getObject方法中,当结果应为Child的任何子项时,您创建Parent的实例。如果您尝试将其与任何其他类型AnotherChild extends Parent

一起使用,此代码将会中断

解决此问题的方法是为子对象传递工厂方法。

public class Connector <T extends Parent>{
    Supplier<T> factory;
    T t;
    public Connector(T t, Supplier<T> factory){
        this.t=t;
        this.factory = factory;
    }
    public T getObject(T t){
        return factory.get();
    }
}

然后用法看起来像

Child someChild = new Child();
Connector<Child> connector = new Connector<>(someChild, Child::new);

答案 3 :(得分:0)

你是什么意思&#34;一切都适合演员&#34;当然,它有效,但它容易出错,顺便说一句,你使用泛型,错误的方式。

当你写作时:

TestOne

这意味着您的类接受作为Parent子类的每个类型T.为了使其更清晰,请参阅此代码:

<T extends Parent>

因为在你的课程定义中,你明确表示你接受从水果延伸的类型,所以不必担心从你的水果篮中添加或检索到的obj(不需要施法),如果有人试图要将dog添加到您的fruitbasket中,他将获得编译时异常,您可以捕获并修复它并防止运行时异常。