简体   繁体   中英

Java Arrays vs Generics

Suppose a SuperClass America and two of its SubClasses SouthAmerica and NorthAmerica

Case 1

For Arrays:

America[] am = new SouthAmerica[10]; //why no compiler error
am[0]= new NorthAmerica();    //ArrayStoreException at RunTime

Case 2

While in Genrics:

ArrayList<America> ame = new ArrayList<SouthAmerica>(); //this does not compile

My question is not why case 2 does not compile but my question is why case 1 compiles.I mean what else can be do this base Array Type and Sub Array Object??

That's because arrays are covariant .

That behavior for arrays is largely considered a mistake:

String[] strings = new String[1];
Object[] objects = strings;
objects[0] = new Integer(1); // RUN-TIME FAILURE

Generic collections - being newer, fixed that mistake.

You can use bounded wildcard notation <? super America> <? super America> :

ArrayList<? super America> = new ArrayList<SouthAmerica>();

This will allow you to add items to the list, but it will avoid the problematic behavior.

See this official tutorial on how to use them.

You are doing something wrong. Based on what you described, suppose we have the following

public class Sample {
    public static void main() {
    America am = new SouthAmerica[10];
    }
}
class America {
    private Integer Size;
}
class NorthAmerica extends America {
    private Integer USA;
}
class SouthAmerica extends America {
    private Integer Chile;
}

I try to compile the above class and it errors out.

javac Sample.java. 
Sample.java:3: incompatible types
found   : SouthAmerica[]
required: America
America am = new SouthAmerica[10];
1 error

Case 1: I assume you meant:

America[] am = new SouthAmerica[10]; //why no compiler error

It's valid for am to hold an array of SouthAmerica as SouthAmerica extends America.

The second line is NOT valid since the array is of SouthAmerica and you're trying to set a NorthAmerica. SouthAmerica is NOT a superclass of NorthAmerica.

The point of the first being valid is that later you can validly say:

am=new NorthAmerica[5];

This is all due to the covariance property of arrays.

Case 2: While SouthAmerica does extend America, that does not work through generics. ArrayList does NOT extend ArrayList as the implication does not hold. Generics(even though in this case it's an ArrayList) does not act in the same way as a full array.

Because arrays are covariant and collections are contravariant . This means that Stirng[] is Object[] , but List<String> is not List<Object> . You should write the following instead:

List<? extends America> list = new ArrayList<SouthAmerica>(); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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