【问题标题】:Java method for type safe return generic subclass类型安全返回泛型子类的Java方法
【发布时间】:2013-01-02 05:36:04
【问题描述】:

我正在使用以下代码从抽象类型(动物)列表中获取与给定类(狗、猫)匹配的第一个元素。还有其他类型安全的方法吗?

// get the first matching animal from a list
public <T extends Animal>T get(Class<T> type) {
    // get the animals somehow
    List<Animal> animals = getList();
    for(Animal animal : animals) {
        if(type.isInstance(animal)) {
            // this casting is safe
            return (T)animal;
        }
    }
    // if not found
    return null;
}

// both Cat and Dog extends Animal
public void test() {
    Dog dog = get(Dog.class); // ok
    Cat cat = get(Dog.class); // ok, expected compiler error
}

(猫和狗扩展了动物)

【问题讨论】:

  • job 变量是什么?
  • 你是对的,第二行不应该编译,假设Dog不扩展Cat
  • 刚刚更新了工作,对此感到抱歉
  • @Fallup:哦,来吧,type是一个对象,你不能那样做!
  • 我在尝试您的代码 sn-p 时遇到编译错误:Type mismatch: cannot convert from Dog to Cat

标签: java generics subclass


【解决方案1】:

我的代码出现编译器错误:

public void test() {
    Dog dog = get(Dog.class); // ok
    Cat cat = get(Dog.class); // compiler error
}

而且我只能看到一种可以编译的情况:

class Dog extends Cat {
}

【讨论】:

  • 编译错误,当 Dog 扩展 Cat 时也不应该编译
  • 如果Dog是Cat(扩展Cat),那么它会编译,这是OOP
【解决方案2】:

代码看起来正确。这一行:

Cat cat = get(Dog.class);

Indeed should not compile.

我会确保您没有在代码中的任何地方使用原始类型,因为这通常会“选择退出”看似无关代码的泛型。

【讨论】:

  • 即使提供了原始类型,是否还需要包含其他控件?
  • @OnurGunduru 我不明白你的评论。您应该避免使用原始类型。实际上,您的示例是正确的,并且对 get 的第二次调用编译的前提是错误的。
  • 没关系,我基本上是在寻找是否有其他方法可以做到这一点。我不太喜欢泛型,经过大量阅读后,这就是我想出的。抱歉,如果我的评论不清楚:如果动物是原始类型(可能导致编译器警告),我是否需要在 if 块中包含任何其他控件
  • @OnurGunduru Animal 不能是一个原始类型,除非它声明了任何类型参数,比如class Animal&lt;T&gt;,然后你仍然使用普通的Animal。您的示例中通用的是方法get,它声明了一个类型参数T extends Animal
  • @OnurGunduru 如果我遗漏了什么,您应该更新问题以反映它 - 因为这是一个非常令人困惑的问题,因为声称一些不正确的东西。发布SSCCE
【解决方案3】:

我会在您的代码中更改一件事。而不是

return (T)animal;

我会用

return type.cast(animal);

后者不会产生未经检查的强制转换警告。

【讨论】:

  • 这真的很有帮助,当我有足够的代表时我会投票。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-11
  • 2016-12-24
  • 1970-01-01
  • 2015-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多