是否可以使用泛型方法而不在java中传递参数类型

时间:2012-12-15 04:57:21

标签: java generics

问题:

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

功能:

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

}

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

用法:

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

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

如何在java中实现上述场景。

4 个答案:

答案 0 :(得分: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();

或者,您可以使用type inferencing

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

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

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

原因是由于type erasure而取消选中(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

答案 1 :(得分:1)

请尝试类似

的内容
Tiger tiger = GetPet(thisZoo,tigersId);
tiger.Roar();

答案 2 :(得分:0)

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

答案 3 :(得分: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