search

Home  >  Q&A  >  body text

java - A是B的子类,为什么List<A>就不是List<B>的子类?

如题。为什么会是这样呢?

ringa_leeringa_lee2816 days ago967

reply all(7)I'll reply

  • 迷茫

    迷茫2017-04-17 13:08:55

    Pay attention to the objects of comparison
    A is a subclass of B. A and B are comparing
    And List<A> is a subclass of List<B> and is compared with List
    You can use definitions like List<? extend b> to perform limited operations

    reply
    0
  • ringa_lee

    ringa_lee2017-04-17 13:08:55

    Because they are both List classes and there is no inheritance relationship

    reply
    0
  • 怪我咯

    怪我咯2017-04-17 13:08:55

    Object inheritance represents an ‘is-a’ relationship. If two objects A and B can be expressed as ‘B is A’, it means that B can inherit A. The successor can also be understood as the specialization of the inherited, because in addition to the characteristics of the inherited, it also has its own unique personality.

    Parent class and subclass, or base class and derived class, where the subclass inherits all the characteristics of the parent class and also defines new characteristics.

    reply
    0
  • 巴扎黑

    巴扎黑2017-04-17 13:08:55

    A subclass of

    List<A> is
    class XXX extends List<A>

    reply
    0
  • ringa_lee

    ringa_lee2017-04-17 13:08:55

    Generics in Java are implemented through Type erasure

    Generics in Java are basically implemented at the compiler level. The type information in generics is not included in the generated Java bytecode. Type parameters added when using generics will be removed by the compiler during compilation. This process is called type erasure.

    List <A> 和 List <B> 在编译完成以后,实际上指向的是同一份字节码
    并不存在 List <A> 或者 List <B> 这2种类型 ,当然就更谈不上什么子类的问题了.
    

    The following is for reference only. I am not familiar with C++
    Aren’t you confused with C++ templates?
    Generics in C++ are implemented differently

    在C++中 确实会为 List <A> 和 List <B> 生成2个class
    

    reply
    0
  • 巴扎黑

    巴扎黑2017-04-17 13:08:55

    Because List<A>.class is not true.
    Generic

    reply
    0
  • 大家讲道理

    大家讲道理2017-04-17 13:08:55

    A lot of answers don’t get to the point. . Let me add some content. Two concepts are involved here: covariance and contravariance. (Covariance vs. Contravariance)

    In short, if the List<S> composite type is covariant, then if S is a subclass of T, then List<S> is also a subclass of List<T>. If List<S> is contravariant, the result is reversed, and List<T> will become a subclass of List<S>.

    But generics in Java do not implement either of the above two behaviors. . Java's generics are invariant (Invariance).

    Why is it designed like this? Let’s look at an array example first. In Java, arrays are covariant, so Integer[] is a subclass of Number[]. So we can write code like this:

    Integer[] a = new Integer[3];
    Number[] b = a;    // a的类型是Integer[],是Number[]的子类
    b[0] = 3.14;    // 运行时错误
    

    Java’s Type Safety guarantee has been broken. Java will save the type of the array elements (Reification) to ensure that this illegal operation can be detected at runtime.

    Assuming that List is covariant, then the code to put Float into Integer is as follows:

    List<Integer> li = new ArrayList<Integer>(); 
    List<Number> ln = li;    // li的类型是List<Integer>,属于List<Number>的子类
    ln.add(new Float(3.1415));    // 不会有错误
    

    will run. And @dkmeteor also mentioned that Java's generics use type erasure, so there is no guarantee whether a Float will be stuffed into the List, because all the List sees at runtime are Objects. So to prevent this kind of thing from happening, Java's generics are immutable.

    Is there any way to use covariant or contravariant generics in Java? The answer is yes, you need to add wildcard to the statement:

    // 1.协变范例
    List<? extends Number> num = new List<Double>();
    // 2.逆变范例
    List<? super Number> num = new List<Object>();
    

    But in the first case, you cannot call the function with ? in the parameter, for example:

    class Container<E> {
        E data;
        public set(E data) {
            this.data = data;
        }
        public E get(E data) {
            return data;
        }
    }
    
    // 某方法中
    Container<? extends Number> num = new Container<Double>();
    num.set(new Float(3));    // 编译时错误
    

    This is also to ensure Type Safety. Cannot pass Float to Container<Double>.

    Similarly, when inverting, you cannot call a function with a return value of ? unless the variable type that accepts the return value is Object.

    Container<? super Number> num2;
    Number res = num2.get();    // 编译时错误
    

    Part of the source: http://www.ibm.com/developerworks/cn/java/j-jtp01255.html

    reply
    0
  • Cancelreply