[英]Producer and Consumer with Generics in Java
我有这个方法来检索作为给定类的实例的对象:
public class UtilitiesClass {
public static final Collection<Animal> get(Collection<Animal> animals, Class<? extends Animal> clazz) {
// returns the Animals which are an instanceof clazz in animals
}
...
}
要调用该方法,我可以这样做:
Collection<Animal> dogs = UtilitiesClass.get(animals, Dog.class);
这很好,但我也希望能够通过以下两种方式调用该方法:
Collection<Animal> dogs = UtilitiesClass.get(animals, Dog.class);
要么
Collection<Dog> dogsTyped = UtilitiesClass.get(animals, Dog.class);
我的意思是我希望能够将方法的结果存储在Dog Collection或Animal中,因为Dog.class
扩展了Animal.class
我在考虑这样的事情:
public static final <T> Collection<T> get(Class<T extends Animal> clazz) {
// returns the Animals which are an instanceof clazz
}
但它不起作用。 任何提示?
编辑:最后,使用@Rohit Jain答案,这是调用UtilitiesClass方法时的解决方案:
Collection<? extends Animal> dogsAnimals = UtilitiesClass.get(animals, Dog.class);
Collection<Dog> dogs = UtilitiesClass.get(animals, Dog.class);
是的,你必须使方法通用。 并且在声明类型参数时应该给出界限:
public static final <T extends Animal> Collection<T> get(
Collection<Animal> animals, Class<T> clazz) {
}
但是,在将animals
集合中的animal
添加到新的Collection<T>
,您必须将其转换为clazz
类型。 您将需要Class#isInstance(Object)
方法,以及Class#cast(Object)
方法。
这可以在Java 8中使用而不使用Class<T>
,但是仍然可能涉及类型转换。 一个不涉及类型转换的版本也是可能的,但有点冗长:
public interface Animal {
public void makeSound();
}
public class Dog implements Animal {
@Override
public void makeSound() {
System.out.println("Waf");
}
}
public class Cat implements Animal {
@Override
public void makeSound() {
System.out.println("Miauw");
}
}
public abstract class Utils {
@SuppressWarnings("unchecked")
public static <T_IN, T_OUT> Collection<T_OUT> getBySubType(Collection<T_IN> input, Predicate<T_IN> predicate) {
return input.stream()
.filter(predicate)
.map(element -> (T_OUT)element)
.collect(Collectors.toList());
}
public static <T_IN, T_OUT> Collection<T_OUT> getBySubTypeSafe(Collection<T_IN> input, Predicate<T_IN> predicate, Function<T_IN, T_OUT> function) {
return input.stream()
.filter(predicate)
.map(function)
.collect(Collectors.toList());
}
}
public class TestProject3 {
private void init() {
List<Animal> animals = new ArrayList<>();
animals.add(new Dog());
animals.add(new Cat());
animals.add(new Dog());
animals.add(new Cat());
animals.forEach(Animal::makeSound);
System.out.println();
Collection<Dog> dogs = Utils.getBySubType(animals, animal -> (animal instanceof Dog));
dogs.forEach(Animal::makeSound);
System.out.println();
Collection<Cat> cats = Utils.getBySubTypeSafe(animals, animal -> (animal instanceof Cat), animal -> (Cat)animal);
cats.forEach(Animal::makeSound);
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
new TestProject3().init();
}
}
输出:
WAF
Miauw
WAF
MiauwWAF
WAFMiauw
Miauw
它的作用是,在getBySubType
resp中getBySubTypeSafe
:
Collection<T_IN>
。 instanceof
过滤所有内容。 T_OUT
其转换为T_OUT
,在我们的版本中使用Function<T_IN, T_OUT>
来明确地安全地转换它。 Collection<T_OUT>
。 参数类型应该是通用通配符,以接受Animal的任何子类的输入集合。
public static final <T extends Animal> Collection<T> get(
Collection<? extends Animal> animals, Class<T> clazz ) {
Collection<T> filteredAnimals = new ArrayList<T>();
for ( Animal animal : animals ) {
if ( clazz.isInstance( animal ) ) {
filteredAnimals.add( clazz.cast( animal ) );
}
}
return filteredAnimals;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.