4

特定のクラスのインスタンスであるオブジェクトを取得するこのメソッドがあります。

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);

それは良いことですが、次の 2 つの方法でメソッドを呼び出せるようにしたいと考えています。

Collection<Animal> dogs = UtilitiesClass.get(animals, Dog.class);

また

Collection<Dog> dogsTyped = UtilitiesClass.get(animals, Dog.class);

つまり、メソッドの結果を Dog コレクションまたは Animal コレクションに格納できるようにしたいということですDog.classAnimal.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);
4

3 に答える 3

6

はい、メソッドをジェネリックにする必要があります。また、型パラメーターを宣言するときに境界を指定する必要があります。

public static final <T extends Animal> Collection<T> get(
                   Collection<Animal> animals, Class<T> clazz) {
}

ただし、animalfromanimalsコレクションを newCollection<T>に追加するときは、型にキャストし直す必要がありますclazz。メソッドが必要Class#isInstance(Object)であり、メソッドも必要Class#cast(Object)です。

于 2014-02-26T16:53:12.540 に答える
3

これは 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();
    }
}

出力:

ワフ
ミアウ
ワフ
ミアウ

ワフワフ
_

ミアウ
ミアウ

それがすることは、getBySubTyperespgetBySubTypeSafeです:

  • 入力として取得しますCollection<T_IN>
  • instanceof述語に基づいてすべてをフィルタリングします。
  • あるバージョンでは にキャストしますがT_OUT、私たちのバージョンでは a を使用しFunction<T_IN, T_OUT>て明示的に安全にキャストします。
  • を返しますCollection<T_OUT>
于 2014-02-27T09:41:06.497 に答える