美文网首页
Java数组和类型

Java数组和类型

作者: 风干鸡 | 来源:发表于2016-12-22 15:35 被阅读0次

    ArrayStoreException

    之前一直以为数组的元素类型必须完全相同,不然运行时会报ArrayStoreException,比如这样:

    public class Test {
        public static void main(String[] args){
            Object[] objects = new String[10];
            objects[0] = new Test();
        }
    }
    

    但是看到规范上面的这一句:

    If the type of the value being assigned is not assignment-compatible (§5.2) with the component type, an ArrayStoreException is thrown.

    Chapter 10. Arrays

    他既然这么说,数组的元素应该是可以不同类型。所以尝试了一下,有以下两种种情况:

    1. Array Creation Expressions
    public class Test {
        interface Noface {}
    
        static class A implements Noface {}
    
        static class B implements Noface {}
    
        public static void main(String[] args){
            Noface[] nofaces = new Noface[2];
            nofaces[0] = new A();
            nofaces[1] = new B();
        }
    }
    

    不会有问题。相同的,创建一个父类的数组,用子类对象赋值给数组元素也不会有问题。
    当然这很显然了

    1. Array Initializers
    public class Test {
        interface Noface {}
    
        static class A implements Noface {}
    
        static class B implements Noface {}
    
        public static void main(String[] args){
            Noface[] nofaces = {new A(), new B()};
            System.out.println(nofaces.getClass());
        }
    }
    

    输出:class [Ljava.lang.Object
    这样也是没问题的,而且可以看到数组的类型是左侧的引用类型。反编译一下:

    $ javap -c com.util.Test
    
        Code:
           0: iconst_2
           1: anewarray     #2                  // class com/util/Test$Noface
    

    创建一个大小为2的Noface数组,这两段代码其实是等价的。
    非基础类型数组实质上是一组引用,引用的类型完全相同,数组元素赋值也就是给对应位置的引用赋值,只要赋值的对象与数组元素类型相同或者是他的子类,就是assignment-compatible

    类型

    Java的数组是协变的,也就是说当类A是类B的父类的时候,A[]=new B[size]是允许的,这与功能类似的集合类不一样,ArrayList<A> list = new ArrayList<B>()就会报错。因为A[]是B[]的超类型,而ArrayList<A>不是ArrayList<B>的超类型。

    If S and T are both reference types, then S[] >1 T[] iff S >1 T.

    注:iff是if and only if的意思,并不是笔误。

    而泛型的父子关系就比较复杂了

    Given a generic type declaration C<F1,...,Fn> (n > 0), the direct supertypes of the parameterized type C<T1,...,Tn>, where Ti (1 ≤ i ≤ n) is a type, are all of the following:

    D<U1 θ,...,Uk θ>, where D<U1,...,Uk> is a generic type which is a direct supertype of the generic type C<T1,...,Tn> and θ is the substitution [F1:=T1,...,Fn:=Tn].

    C<S1,...,Sn>, where Si contains Ti (1 ≤ i ≤ n) (§4.5.1).

    The type Object, if C<F1,...,Fn> is a generic interface type with no direct superinterfaces.

    The raw type C.

    4.10. Subtyping

    简单举例解释一下:

    • List<A>ArrayList<A>的超类型,因为ListArrayList的父类,而且参数化类型完全相同
    • ListList<A>的超类型,因为Listraw type
    • List<? extends A>List<A>的超类型,因为? extends A contains A

    contain

    A type argument T1 is said to contain another type argument T2, written T2 <= T1

    ? extends T <= ? extends S if T <: S

    ? extends T <= ?

    ? super T <= ? super S if S <: T

    ? super T <= ?

    ? super T <= ? extends Object

    T <= T

    T <= ? extends T

    T <= ? super T

    在库函数中经常会见到这样的东西 <T extends Comparable<? super T>>, 也是出于这样的原因。

    heap pollution

    • 我发现有些东西起个名字就会显得很高大上*

    相关文章

      网友评论

          本文标题:Java数组和类型

          本文链接:https://www.haomeiwen.com/subject/wcqhvttx.html