简体   繁体   English

Java中的通用类型和通配符

[英]Generic types and wildcards in Java

I have the following class created with generics in Java and I have several doubts about this: 我在Java中使用泛型创建了以下类,对此有一些疑问:

 public class Averias<T, E> {

    private ArrayList<T> averias;
    private E prueba;
    private ArrayList<? extends T> animal;

    public Averias(ArrayList<T> averias, E prueba, ArrayList<? extends T> animal) {
        this.averias = averias;
        this.prueba = prueba;
        this.animal = animal;
    }

    public ArrayList<T> getAverias() {
        return averias;
    }

    public void setAverias(ArrayList<T> averias) {
        this.averias = averias;
    }

    public E getPrueba() {
        return prueba;
    }

    public void setPrueba(E prueba) {
        this.prueba = prueba;
    }

    public ArrayList<? extends T> getAnimal() {
        return animal;
    }

    public void setAnimal(ArrayList<? extends T> animal) {
        this.animal = animal;
    }
}

This is my class, and now the first doubt I have is: when I want to use this class, do I have to infer all types or can I use just one? 这是我的课程,现在我的第一个疑问是:当我想使用此类时,我是否必须推断所有类型,还是只能使用一个?

private Averias<Integer, String> averias;

If I infer all types works, but I think a lot of code that every time I want to use it, I have to infer the type, then I don't know if there is some simpler way that I don't know. 如果我推断所有类型都行得通,但我认为每次我想使用它时都需要推断大量类型的代码,那么我不知道是否有一些我不知道的简单方法。

In the class I have an ArrayList with a wildcard: private ArrayList animal;. 在该类中,我有一个带有通配符的ArrayList:private ArrayList animal;。 I still don't have very clear how wildcards work, I know that it can be put alone, with extensions or with super, and depending on how it works, but I don't know when it would be useful to use them. 我仍然不清楚通配符如何工作,我知道可以将其与扩展名或super一起使用,并取决于其工作方式,但是我不知道何时使用通配符会很有用。

Inference can work, but if you go with inference, it's all or nothing. 推论是可行的,但是如果您推论推论,那么它就是全部或什么都没有。 You can't specify half of the generics parameters and leave the other half inferred. 您不能指定一半的泛型参数,而将另一半推断出来。 To use inference, you need the diamond operator. 要使用推论,您需要菱形运算符。 For example, given: 例如,给定:

void foo(Averias<String, Integer> a);

you can write: 你可以写:

thingie.foo(new Averias<>());

and it'll infer the <String, Integer> bit. 并推断<String, Integer>位。 For static methods with type args, you get inference without any additional syntax, so no need for <> there. 对于类型为args的静态方法,无需任何其他语法即可进行推理,因此无需在其中使用<>

For fields, inference cannot be used; 对于字段,不能使用推断。 in private Averias<Integer, String> averias it cannot be avoided. private Averias<Integer, String> averias它是不可避免的。

For wildcards: 对于通配符:

With generics the inheritance rules are more strict. 使用泛型时,继承规则更加严格。 For example, this: 例如,这:

Number x = new Integer(5);

is legal java. 是合法的Java。 But if we genericsify this: 但是,如果我们将其通用化:

List<Number> x = new ArrayList<Integer>();

it is NOT LEGAL – generics are 'invariant', meaning only if the same thing is on both the left and right side, it'd work. 不是合法的 –泛型是“不变的”,意味着只有在左右两侧都相同的情况下,它才会起作用。 Only List<Number> x = new ArrayList<Integer>() works. List<Number> x = new ArrayList<Integer>()有效。 That may strike you as weird, but it is correct: The thing is, with lists, you can also write to them. 也许您会觉得很奇怪,但这是正确的:事实是,有了列表,您也可以写信给他们。 And, you can write a double into a List<Number> (after all, a double is a number), but.. a double isn't an integer. 并且,您可以将Double写入List<Number> (毕竟,double是数字),但是.. double不是整数。 Hence why it works like this. 因此,为什么它如此工作。

If you NEED covariance, you can still do that, that's where wildcards come in. This IS legal: 如果需要协方差,您仍然可以这样做,这就是通配符出现的地方。这是合法的:

List<? extends Number> x = new ArrayList<Integer>();

So what happens with the 'add a double' problem? 那么“加倍”问题会怎样? Easy: You cannot add anything to a List<? extends whatever> 容易:您无法将任何内容添加List<? extends whatever> List<? extends whatever> . List<? extends whatever> (Well, except null which is always okay). (好吧,除了null总是可以的)。

super is for contravariance. super是为了求逆。 The effective notion of Integer x = new Number . Integer x = new Number的有效概念。 With contravariance you can add things to a list, but if you get from it, you'll always get a type of Object out: 有了矛盾性,您可以将内容添加到列表中,但是如果从列表中get ,则总是可以得到一种Object

List<? super Integer> x = new ArrayList<Number>(); // legal
x.add(new Integer(10)); // Okay
x.add(someNumber); // illegal
Object z = x.get(0); // that works; anything other than Object would not

super is by far the most rare. super是迄今为止最罕见的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM