2

问题:

我想创建一个通用函数,它将返回我的类型化对象。

功能 :

public <T > T GetPet(AnimalKingdom allAnimals,int id) {
    return (T) allAnimals.getAnimalsManager().findAnimalById(id);

}

上述函数将返回强类型对象或抛出错误。

用法 :

GetPet<Tiger>(thisZoo,tigersId).Roar();

来自 C# 背景。谷歌搜索相同但无法找到解决方案,似乎我需要在函数中传递泛型类型才能使其工作。

上面的场景怎么能用java实现。

4

4 回答 4

6

在 Java 中,您在方法名称之前显式指定泛型方法的类型参数。例如:

class Example {
    public static <T> T getPet(AnimalKingdom allAnimals, int id) {
        return (T)allAnimals.getAnimalsManager().findAnimalById(id);
    }
}

然后调用:

Example.<Tiger>getPet(thisZoo, tigersId).roar();

或者,您可以使用类型推断

Tiger tiger = Example.getPet(thisZoo, tigersId);
tiger.roar();

顺便说一句,您的getPet方法不是很安全,因为没有执行运行时检查以确保返回的对象实际上是Tiger. 事实上,Java 编译器在这一行给出了警告:

return (T)allAnimals.getAnimalsManager().findAnimalById(id);

原因是由于类型擦除(T)而未检查强制转换。

为了加强您的代码,我建议进行以下更改:

class Example {
    public static <T> T getPet(Class<T> clazz, AnimalKingdom allAnimals, int id) {
        return clazz.cast(allAnimals.getAnimalsManager().findAnimalById(id));
    }
}

然后调用:

Example.getPet(Tiger.class, thisZoo, tigersId).roar();

传入类对象 ( Tiger.class) 的好处是:

  1. 它为编译器提供了要使用的类型<T>(再次通过类型推断)。
  2. Class.cast您可以通过调用该方法添加自己的显式运行时类型检查。Java 编译器警告消失,类型安全恢复。例如,如果findAnimalById在您期望 Tiger 时错误地返回了 Bear 的实例,您将得到一个ClassCastException.
于 2012-12-15T05:43:35.923 回答
1

请尝试类似

Tiger tiger = GetPet(thisZoo,tigersId);
tiger.Roar();
于 2012-12-15T05:20:50.800 回答
0

在这里使用泛型只是错误的选择。你应该看看继承、虚函数、抽象类和接口。

于 2012-12-15T07:36:04.810 回答
0

正如 SylvainL 所说,泛型在这里不是正确的选择。对我来说,这看起来像是一个简单的继承/接口问题。

新的 getPet 方法:

public Animal getPet(AnimalKingdom allAnimals, int id)
{
    return allAnimals.getAnimalsManager().findAnimalById(id);
}

使用继承:

class Animal { void Roar() { throw new Exception("This animal cannot roar!"); } };
class Tiger extends Animal { @Override void Roar() { ... }; ... };

用法:

getPet(thisZoo, tigersId).Roar();

或使用接口:(稍微复杂一点,但通常可能更好)

注意:在这种情况下你并不真的需要 Animal,你可以使用 Object

class Animal { ... }; // no Roar method
interface Roarer { void Roar(); };
class Tiger extends Animal implements Roarer { @Override void Roar() { ... }; ... };

注意:您可以将以下任何一种用法粘贴到一个方法中,最终得到类似的结果:

roar(getPet(thisZoo, tigersId));

用法:(您可以删除try {} catch,但这通常不是一个好主意)

try
{
   ((Roarer)getPet(thisZoo, tigersId)).Roar();
}
catch (ClassCastException e) { /* handle error */ };

替代用法:(为了安全避免try {} catch,还没有尝试过,但我认为它可能有效)

Animal animal = getPet(thisZoo, tigersId);
if (Roarer.class.isAssignableFrom(animal.class))
   ((Roarer)animal).Roar();
else
   // handle error
于 2012-12-18T08:37:10.763 回答