Java数组和类型

2016-12-22  本文已影响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

简单举例解释一下:

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

上一篇 下一篇

猜你喜欢

热点阅读