当前位置: 首页 > 面试题库 >

在泛型中具有扩展名的超级和晦涩有用的例子吗?

张腾
2023-03-14
问题内容

我知道有关此主题的问题很多,但是很遗憾,这些问题无法帮助我消除歧义。首先,请看下面的例子。我不明白,为什么以下“添加”方法someCage.add(rat1)不起作用并因以下异常而中止:

线程“主”中的异常java.lang.Error:未解决的编译问题:类型为Cage的方法add(capture#2-of?extended
Animal)不适用于参数(Rat)

Cage<Rat>是不是一个相同的原因Cage<Animal>吗?如果是,则在此示例中我不理解它,因此我不确定编译器的功能。这是代码示例:

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("\nRatCage........");
        ratCage.showAnimals();
        System.out.println("\nLionCage........");
        lionCage.showAnimals();
        System.out.println("\nSomeCage........");
        someCage.showAnimals();
    }
}

这是笼类:

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

此外,如果您可以使用此动物笼代码给我一个有意义的“超级”示例,我将感到非常高兴。到目前为止,我还不知道如何使用它。有很多理论示例,我阅读了有关PECS概念的信息,但是无论如何,我还无法在有意义的事情上使用它。在此示例中,拥有“消费者”(具有超级)是什么意思?


问题答案:

超级绑定示例

引入的transferTo()方法接受Cage<? super T>-持有的超类的Cage
T。因为T是一个instanceof它的超类,它的确定,把TCage<? 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);
    }
}

现在让我们看一下<? super T>实际操作:

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

输出:

[Rat, Lion]

另一个重要的概念是:

Lion instanceof Animal // true

不是 真的

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

如果不是这种情况,则此代码将编译:

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>


 类似资料:
  • 问题内容: 当我以为自己终于了解了泛型时,我遇到了以下示例: 它说,如果第1行未注释,则不会编译以下内容: 如果注释了第2行,则不会编译以下内容: 在第二个示例中,允许使用脂肪族及其超类型。那么为什么不允许脂肪族? 在第一个示例中,为什么不允许? 第一个编译器错误: 第二编译器错误: 问题答案: 您的第一个声明 表示 可能 是一个(因为extends ,extends 和extended )。 在

  • 问题内容: 是否可以在没有警告警告的情况下模拟(带有模拟)签名方法?我试过了: 但无论我如何声明,我总是会遇到编译错误。例如当我这样宣布 我收到标准的通用/ mockito编译错误 问题答案: 使用doReturn-when备用存根语法。 被测系统: 和测试用例: 无需错误或警告抑制

  • 问题内容: 我已经看过以前用来表示任何对象的通配符-但最近看到了以下用法: 由于所有对象都扩展了对象,所以这两种用法是同义词吗? 问题答案: 并且是同义的,正如你所期望的。 在某些情况下,泛型实际上并不是多余的。例如,将导致成为下删除,而与它会成为下删除。(如果你要保留与使用的前泛型API的兼容性,这可能很重要。) 来源:http : //download.oracle.com/javase/tu

  • 问题内容: 我正在尝试检测具有扩展名列表的文件。 问题答案: 为此使用元组。 不必每次都转换,只需将其转换为元组一次即可。

  • 问题内容: 有一个简单的程序代码。在构造函数中,没有扩展到超类的调用,我不明白在这种情况下会发生什么? 问题答案: 没有显式扩展另一个类的每个类都隐式扩展。因此,只需调用Object的no-arg构造函数。 请注意,此显式调用是不必要的,因为编译器会为您添加它。当您要使用参数调用超类构造函数时,只需在构造函数中添加调用。

  • 问题内容: 我发现了一个有趣的行为,似乎是一个错误… 基于行为描述了以下文章: https://medium.com/ios-os-x-development/swift-protocol-extension-method- dispatch-6a6bf270ba94 http://nomothetis.svbtle.com/the-ghost-of-swift-bugs- future 当添加时