Java Arrays vs Generics

2020-07-23 03:38发布

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??

4条回答
祖国的老花朵
2楼-- · 2020-07-23 04:10

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>:

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.

查看更多
劳资没心,怎么记你
3楼-- · 2020-07-23 04:13

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
查看更多
欢心
4楼-- · 2020-07-23 04:14

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.

查看更多
闹够了就滚
5楼-- · 2020-07-23 04:17

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>(); 
查看更多
登录 后发表回答