The reason for the parameter type of the Java Arraylist.toarray (t[] method is T rather than e _java

Source: Internet
Author: User

Two days ago to do the code review to colleagues, feel that the Java generics master not good enough, then take out the "effective Java" 1 this book and then look at the relevant chapters. In the Item 24:eliminate unchecked warnings section, the author takes the public <T> t[] ToArray (t[] a) method in the ArrayList class as an example to illustrate how to use a variable @Suppre sswarnings annotation.

ArrayList is a generic class, which is declared like this:

Javapublic class Arraylist<e> extends abstractlist<e>
implements List<e>, Randomaccess, Cloneable, java.io.Serializable

The ToArray (t[] a) approach to this class is a generic method, which is declared and implemented as follows:

@SuppressWarnings ("unchecked") public
<T> t[] ToArray (t[] a) {
if (A.length < size)
//Make a new arr Ay of a ' s runtime type, but my contents: return
(t[)) arrays.copyof (elementdata, size, A.getclass ());
System.arraycopy (elementdata, 0, a, 0, size);
if (a.length > Size)
a[size] = null;
return A;
}

This method is actually declared in the Collection interface. Because we often use it through ArrayList, here is the example of ArrayList.

1 Why are the different types declared?

My question is: Why does this method use type T instead of using ArrayList type E? In other words, why is this method not declared like this:

Javapublic e[] ToArray (e[] a);

If the type is the same, the parameter's type error can be found during compilation. If the types are different, it is easy to generate run-time errors. For example, the following code:

Create a ArrayList list<string> of type String
strlist = new arraylist<string> ();
Strlist.add ("abc");
Strlist.add ("xyz");
Converts the current strlist into an array of number. Note that the following statement does not have any compilation errors.
number[] Numarray = Strlist.toarray (new number[0));

Running the above code, line 6 throws a Java.lang.ArrayStoreException exception.

If the ToArray method uses type E, Statement 2 generates a compilation error. Compiling errors is more intimate than run-time errors. Also, the main purpose of generics is to eliminate type conversion errors (ClassCastException) during compilation for type safety. This approach is the opposite. Is this a big bug? Java Bugs I have encountered, but this place is a bug I still do not dare to believe.

On the Internet, the problem has been discussed several times 2, 3, 4.

2 can improve flexibility

Such declarations are more flexible and can convert the elements in the current list into an array of more general types. For example, the current list type is Integer, and we can convert its elements into an array of number.

list<integer> intlist = new arraylist<integer> ();
Intlist.add (1);
Intlist.add (2);
number[] Numarray = Intlist.toarray (new number[0));

If this method declares type E, the code above will have a compile error. It seems to be more appropriate to declare this method as follows:

Javapublic <t Super e> t[] ToArray (t[) a);

However, syntax such as <t Super e> does not exist in Java. And even if they do, the array does not work. And it is for this reason that when using this method, even if T is the parent of E, or T is the same as E, it is not entirely possible to avoid java.lang.ArrayStoreException anomalies 5, 6, 7. Take a look at the following two pieces of code. In the first code, T is the parent class of E, and the second code is the same as T and E. Both of these pieces of code will throw an exception.

Code One:

list<integer> intlist = new arraylist<integer> ();
Intlist.add (1);
Intlist.add (2); 
float[] Floatarray = new float[2];
Float is a subclass of number, so float[] is a subclass of number[]
number[] Numarray = Floatarray;
The following statement throws the Arraystoreexception exception
Numarray = Intlist.toarray (Numarray);

Code two:

list<number> intlist = new arraylist<number> ();
The type of List is number. But number is an abstract class and can only save instance
Intlist.add (New Integer ()) of its subclasses;
Intlist.add (New Integer ()); 
float[] Floatarray = new float[];
Float is a subclass of number, so float[] is a subclass of number[]
number[] Numarray = Floatarray;
The following statement throws the Arraystoreexception exception
Numarray = Intlist.toarray (Numarray);

The above exception is caused by this fact: if a is the parent class of B, then a[] is the parent of b[. All classes in Java inherit from object,object[] is the parent class of all arrays.

This post 8 illustrates an example of a arraystoreexception exception that cannot be avoided even if the type of the method is declared as E.

This exception is also mentioned in the documentation for this method:

Arraystoreexception if the runtime type of the specified array is isn't a supertype of the runtime type of every element in This list.

3 can be compatible with previous versions of Java 1.5

This method appeared 9 before Java introduced generics (JDK1.5 introduced generics). At that time it was declared that such:

Javapublic object[] ToArray (object[] a)

After the advent of generics, many classes and methods became generic. This method also follows the same statement as:

Javapublic <T> t[] ToArray (t[] a)

This declaration can be compatible with the version prior to Java 1.5 compatibility 10.

4 more long-winded two sentences

This method requires an array parameter. If the length of this array is greater than or equal to the element in the size,list of the current list, it is stored in the array; If the length of the array is less than the size of the current list, a new array is created and the elements in the current list are saved to the newly created Array. To increase efficiency, if possible, the length of the passed-in array is greater than or equal to the size of the list, to avoid creating a new array for the method.

list<integer> intlist = new arraylist<integer> ();
Intlist.add ();
Intlist.add ();
Pass in an array with a length of 
number[] Numarray = Intlist.toarray (new number[]);//Statement
//pass in an array with a length equal
to the length of the Intlist number[] Numarray = Intlist.toarray (New number[intlist.size ()); Statement

In addition, an array that is a parameter cannot be null, otherwise a NullPointerException exception is thrown.

Footnotes:

1
Effective Java (2nd Edition)
2
Link
3
Link
4
Link
5
Link
6
Link
7
Link
8
Link
9
Link
10
Link
created:2016-04-06 Wed 21:14
Emacs 24.5.1 (ORG mode 8.2.10)
Validate

The above content is small series to introduce the Java Arraylist.toarray (t[]) method of the parameter type is T instead of e reason analysis, hope to help everyone!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.