簡體   English   中英

Java中的泛型生產者和消費者

[英]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
Miauw

WAF
WAF

Miauw
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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM