Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I know that there are a lot of questions about this topic, but unfortunately they couldn't help me to eliminate my obscurities. First of all, look at the following example. I don't understand, why the following "add"-method someCage.add(rat1) doesn't work and aborts with the following exception:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: The method add(capture#2-of ? extends Animal) in the type Cage is not applicable for the arguments (Rat)

Is this the same reason why Cage<Rat> is not a Cage<Animal>? If yes, I don't understand it in this example, so I'm not sure what the compiler exactly does. Here is the code example:

package exe;

import cage.Cage;
import animals.Animal;
import animals.Ape;
import animals.Lion;
import animals.Rat;

public class Main {

    public static void main(String[] args) {
        Lion lion1 = new Lion(true, 4, "Lion King", 8);
        Lion lion2 = new Lion(true, 4, "King of Animals", 9);
        Ape ape1 = new Ape(true, 2, "Gimpanse", true);
        Ape ape2 = new Ape(true, 2, "Orang Utan", true);
        Rat rat1 = new Rat(true, 4, "RatBoy", true);
        Rat rat2 = new Rat(true, 4, "RatGirl", true);
        Rat rat3 = new Rat(true, 4, "RatChild", true);

        Cage<Animal> animalCage = new Cage<Animal>();
        animalCage.add(rat2);
        animalCage.add(lion2);

        Cage<Rat> ratCage = new Cage<Rat>();
        ratCage.add(rat3);
        ratCage.add(rat1);
        ratCage.add(rat2);
//      ratCage.add(lion1); //Not Possible. A Lion is no rat

        Cage<Lion> lionCage = new Cage<Lion>();
        lionCage.add(lion2);
        lionCage.add(lion1);

        Cage<? extends Animal> someCage = new Cage<Animal>(); //? = "unknown type that is a subtype of Animal, possibly Animal itself"
        someCage = ratCage; //OK
//      someCage = animalCage; //OK
        someCage.add(rat1);  //Not Possible, but why?

        animalCage.showAnimals();
        System.out.println("
RatCage........");
        ratCage.showAnimals();
        System.out.println("
LionCage........");
        lionCage.showAnimals();
        System.out.println("
SomeCage........");
        someCage.showAnimals();
    }
}

This is the cage class:

package cage;

import java.util.HashSet;
import java.util.Set;

import animals.Animal;

    public class Cage<T extends Animal> {  //A cage for some types of animals
        private Set<T> cage = new HashSet<T>();

        public void add(T animal)  {
            cage.add(animal);
        }

        public void showAnimals()  {
            for (T animal : cage) {
                System.out.println(animal.getName());
            }
        }
    }

Moreover, I would be pleased if you could give me a meaningful "super" example with this animal-cage-code. Until now I haven't understood how to use it. There are a lot of theoretical examples and I read about the PECS concept but anyhow I wasn't able to employ it in a meaningful matter yet. What would it mean to have a "consumer" (with super) in this example?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
324 views
Welcome To Ask or Share your Answers For Others

1 Answer

Example of super bound

The introduced transferTo() method accepts Cage<? super T> - a Cage that holds a superclass of T. Because T is an instanceof its superclass, it's OK to put a T in a Cage<? super T>.

public static class Cage<T extends Animal> { 
    private Set<T> pen = new HashSet<T>();

    public void add(T animal) {
        pen.add(animal);
    }

    /* It's OK to put subclasses into a cage of super class */
    public void transferTo(Cage<? super T> cage) {
        cage.pen.addAll(this.pen);
    }

    public void showAnimals() {
        System.out.println(pen);
    }
}

Now let's see <? super T> in action:

public static class Animal {
    public String toString() {
        return getClass().getSimpleName();
    }
}
public static class Rat extends Animal {}
public static class Lion extends Animal {}
public static class Cage<T extends Animal> { /* above */ }

public static void main(String[] args) {
    Cage<Animal> animals = new Cage<Animal>();
    Cage<Lion> lions = new Cage<Lion>();
    animals.add(new Rat()); // OK to put a Rat into a Cage<Animal> 
    lions.add(new Lion());
    lions.transferTo(animals); // invoke the super generic method
    animals.showAnimals();
}

Output:

[Rat, Lion]



Another important concept is that while it is true that:

Lion instanceof Animal // true

it is not true that

Cage<Lion> instanceof Cage<Animal> // false

It this were not the case, this code would compile:

Cage<Animal> animals;
Cage<Lion> lions;
animals = lions; // This assignment is not allowed
animals.add(rat); // If this executed, we'd have a Rat in a Cage<Lion>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...