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

发布于 2021-02-02 23:00:32

考虑以下示例(OOP书籍中的典型示例):

我有一Animal堂课,每个人Animal可以有很多朋友。
和子类喜欢Dog,Duck,Mouse等里面加如特定行为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?或者至少通过传递类型的类而不是虚拟实例。
我了解泛型用于编译时类型检查,但是是否有解决方法?

关注者
0
被浏览
104
1 个回答
  • 面试哥
    面试哥 2021-02-02
    为面试而生,有面试问题,就找面试哥。

    你可以这样定义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();
    

    此代码的好处是不会生成任何编译器警告。当然,这实际上只是前代产品的更新版本,不会增加任何额外的安全性。



  • 面试哥
    面试哥 2021-02-02
    为面试而生,有面试问题,就找面试哥。


    不会。编译器不知道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();`


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看