我如何使方法返回类型通用?

考虑这个例子(典型的OOP书籍):

我有一个Animal课,每个Animal可以有很多朋友。
DogDuckMouse等子类可以添加特定的行为,如bark()quack()等。

这是Animal类:

public class Animal {
    private Map<String,Animal> friends = new HashMap<>();

    public void addFriend(String name, Animal animal){
        friends.put(name,animal);
    }

    public Animal callFriend(String name){
        return friends.get(name);
    }
}

以下是一些包含大量类型转码的代码片段:

Mouse jerry = new Mouse();
jerry.addFriend("spike", new Dog());
jerry.addFriend("quacker", new Duck());

((Dog) jerry.callFriend("spike")).bark();
((Duck) jerry.callFriend("quacker")).quack();

有没有什么办法可以使用泛型来返回类型来摆脱类型转换,这样我就可以说

jerry.callFriend("spike").bark();
jerry.callFriend("quacker").quack();

以下是一些初始代码,将返回类型作为从未使用过的参数传递给方法。

public<T extends Animal> T callFriend(String name, T unusedTypeObj){
    return (T)friends.get(name);        
}

有没有办法找出运行时返回类型没有额外的参数使用instanceof ? 或者至少通过传递一个类的类而不是一个虚拟实例。
我明白泛型是用于编译时类型检查的,但是有没有解决方法?


你可以这样定义callFriend

public <T extends Animal> T callFriend(String name, Class<T> type) {
    return type.cast(friends.get(name));
}

然后这样称呼它:

jerry.callFriend("spike", Dog.class).bark();
jerry.callFriend("quacker", Duck.class).quack();

此代码具有不产生任何编译器警告的好处。 当然,这实际上只是从通用前的日子开始的更新版本,并没有增加任何额外的安全性。


编号不知道什么类型的jerry.callFriend("spike")会返回。 此外,您的实现只是将方法隐藏起来,而不需要任何额外的类型安全。 考虑这个:

jerry.addFriend("quaker", new Duck());
jerry.callFriend("quaker", /* unused */ new Dog()); // dies with illegal cast

在这个特定的情况下,创建一个抽象的talk()方法并在子类中适当地覆盖它会为你提供更好的服务:

Mouse jerry = new Mouse();
jerry.addFriend("spike", new Dog());
jerry.addFriend("quacker", new Duck());

jerry.callFriend("spike").talk();
jerry.callFriend("quacker").talk();

你可以像这样实现它:

@SuppressWarnings("unchecked")
public <T extends Animal> T callFriend(String name) {
    return (T)friends.get(name);
}

(是的,这是合法的代码;请参阅Java泛型:Generic类型仅定义为返回类型。)

返回类型将从调用者推断出来。 不过,请注意@SuppressWarnings注释:它告诉您这段代码不是类型安全的 。 您必须亲自验证它,否则您可能会在运行时遇到ClassCastExceptions

不幸的是,你使用它的方式(没有把返回值赋给一个临时变量),让编译器高兴的唯一方法就是像这样调用它:

jerry.<Dog>callFriend("spike").bark();

虽然这可能比铸造好一点,但正如David Schmitt所说,你最好给Animal课一个抽象的talk()方法。

链接地址: http://www.djcxy.com/p/50195.html

上一篇: How do I make the method return type generic?

下一篇: How to tell a method has a varargs argument using reflection?