2016-07-24 166 views
-1

的子类我有这个类:如何返回泛型类型

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

我做出了一流的连接器,我想的是T类将承担母公司的子类:

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); 

一切与演员合作,但我不明白为什么我必须添加一个演员到什么是ret如果T延伸,请在getObject方法中使用父

+3

考虑'公共类Child2 extends Parent {}'。你的代码中断了一个'ClassCastException'。问题是:你想在这里做什么?为什么'getObject'将'T'作为参数? – Tunaki

+0

@tunaki getObject将T作为参数,因为我想对父类 – joumvaer92

+0

@ joumvaer92的子类进行操作如果您在操作它之后只是简单地返回't',那么您可以这样做,但是您不能假设't ''将始终是'Child'类型,所以这就是为什么你需要一个强制类型来返回一个'Child'类型的对象,但是我会考虑在构造'Connector'时返回't'并使'tt'类型为'Child' ' –

回答

0

Connector中介绍的本地Child p变量和泛型T之间没有任何关联。 getObject方法中既没有使用字段T t也没有使用参数T t,因此需要明确的cat。

如果您提供以下getObject实现:

public T getObject(){ 
    return t;  
} 

没有必要对投了。

0

问题是TChild类没有连接。请叫Pet扩展Parent另一个类,

public class Pet extends Parent{ 
    ... 
} 

现在让我们重新您getObject方法。与Pet替换T的实例,

在主,我们现在有

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

在连接器类,

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

为什么需要投的原因是没有保证PetChild有关系。如果省略了投射,则当返回类型为Pet时,将返回类型为Child的对象,这会导致错误,因为Pet不等于Child。如果你想返回Child类型的新的对象,然后我会建议做这样的事情(参数可以因为你以前没有使用它可以省略),

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

public Child getObject(T t){ 
    //do operations on t here 
    return t; 
} 
0

getObject方法中,当结果应该是Parent的任何子项时,您创建Child的实例。如果您尝试将其与任何其他类型一起使用,则此代码将中断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); 
0

你说的“一切跟投工作”,当然,它的工作原理,但它是容易出错的,顺便说一句的意思是什么,你用泛型类型,错误的方式。

当你写:

<T extends Parent> 

这意味着你的类可以接受所有的类型T是母公司的一个子类。使其更清楚,看到这样的代码:由于你的类定义

public class FruitBaskets<T extends Fruit>{ 
T t; 
public addFruit(T t){ 
    this.t=t; 
} 
public T getFruit(T t){ 
    return t;  
    } 
} 

FruitBasket<Apple> myFuitBasket = new FruitBasket(); 

,你说得很清楚,你接受来自水果扩展类型,所以不`吨需要担心约OBJ添加或从中检索你的水果篮(不需要投射),如果有人试图给你的水果篮添加一只狗,他会得到一个编译时异常,你可以捕获并修复它,并防止运行时异常。