Java array transformation and Model

Source: Internet
Author: User

Today, I encountered a strange problem when writing code. The code structure is as follows:

Arraylist <string> List = new arraylist <string> (); <br/> string strings [] = (string []) List. toarray ();In this way, I personally think there should be no problem in writing code, and there is no problem in compiling. However, an exception is reported during running as follows:

Exception in thread "Main" Java. Lang. classcastexception: [ljava. Lang. object;

But if you write it like this, there will be no problem:

Arraylist <string> List = new arraylist <string> (); <br/> int Len = List. size (); <br/> string strings [] = new string [Len]; <br/> for (INT I = 0, j = List. size (); I <j; I ++) {<br/> strings [I] = List. get (I); <br/>}


How can this problem be solved?

Java allows upward and downward transformations, but whether the transformation is successful depends on the type of the object in the Java Virtual Machine. The Java virtual machine saves the type of each object, and the array is also an object.

The array type is [ljava. lang. object, put the [ljava. lang. convert an object to [ljava. lang. string is obviously impossible, because this is a downward transformation, and the virtual machine only saves this is an array of objects, and the elements in the array cannot be guaranteed to be string, so this transformation cannot be successful. The elements in the array are only element references, not specific storage elements. Therefore, the element types in the array are stored in the Java Virtual Machine.

According to the above explanation, we can summarize this problem into the following model.

Object objs [] = new object [10];

String STRs [] = (string []) objs;

This is the same as the above compilation error. If we modify this Code, as follows:

String STRs [] = new string [10];

Object objs [] = STRs;

In this way, compilation can be passed, so this problem can be attributed to a problem of Java transformation rules.

 

Question about fan type support for Java Arrays:

JDK 5 already hasGenericTo ensure the security of the data types in the collection and map, but the toarray method of list returns object [], which makes me very confused. I personally feel that the corresponding T [] can be directly returned based on the model. After carefully reading the JDK source code, we found that there are two ways to convert list to array:

Public object [] toarray ();

This method returns all elements in the list to an array of the same size. All elements in the array are of the object type.

Public <t> T [] toarray (T [] );

This method returns all elements in the list to an array of the same size. All elements in the array are of the T type.

The list is designed because the Java compiler does not allow us to define an array of the new model. That is to say, you cannot define an array as follows:

T arr = new T [size];

However, you can use t [] to represent arrays and forcibly convert arrays to T. For example, the Public <t> T [] toarray (T [] A) in the list is implemented as follows:

Public <t> T [] toarray (T [] A) {<br/> If (. length <size) <br/> A = (T []) Java. lang. reflect. array. newinstance (. getclass (). getcomponenttype (), size); <br/> system. arraycopy (elementdata, 0, A, 0, size); <br/> If (. length> size) <br/> A [size] = NULL; <br/> return a; <br/>}

From the code above, you mustReflectionTo create this array, because you do not know the type of this array. The A. getclass (). getcomponenttype () method is used to obtain the type of an array element.

 


JavaWhy?Cannot create a fan array?

I think the answer to this question is: this will undermine type security. The core problem is that there is a fundamental difference between Java and C:

The Java model stays at the compilation layer. At runtime, the information of these models is actually erased, while the C # model implements the msil (Microsoft intermediate language, microsoft intermediate language.

The Java practice does not need to modify the JVM, which reduces the potential for significant changes and the risks that come with it. It may also reflect the inherent limitations of the Java bytecode specification at the beginning of its design;

C # It's a big deal to change together with CLR (Common Language Runtime, common language runtime) to support more thorough paradigm. In other words, in terms of paradigm, C # is more like C ++.

 

In Java, the object [] array can be the parent class of any array, or any array can be transformed up to an array of the parent class of the specified Element type during definition, at this time, if we put it in a different way than the original data type, but it satisfies the parent class type used later, the compilation will not be a problem, however, the runtime checks the type of the object to be added to the array, so arraystoreexception is thrown:

String [] strarray = new string [20];

Object [] objarray = strarray;

Objarray [0] = new INTEGER (1); // throws arraystoreexception at runtime

Because the Java model will erase the type information after compilation, if Java allows us to use something similar:

Map <integer, string> [] maparray = New Map <integer, string> [20];

For such a statement, we can convert it to object [] in the subsequent code, and then put the map <double, string> instance in it.

In this way, not only can the compiler not find a type error, but the Array Storage check in the runtime cannot do anything about it. What it can see is the object we put in the map, which we define <integer, string> it has been erased at this time, so for it, as long as it is map, it is legal. Think about it. We define an array containing Map <integer, string>, but we can put any map (such as Map <double, string>) in the result ), next, if some code tries to take the value according to the original definition, what is the consequence.

Therefore, the Java compiler does not allow us to use new arrays.



Toarray ()

Public object [] toarray () {<br/> object [] A = C. toarray (); <br/> for (INT I = 0; I <. length; I ++) <br/> A [I] = new unmodifiableentry <> (map. entry <K, V>) A [I]); <br/> return; <br/>}</P> <p> Public <t> T [] toarray (T []) {<br/> // We don't pass A to C. toarray, to avoid window of <br/> // vulnerability wherein an unscrupulous multithreaded client <br/> // cocould get his hands on raw (unwrapped) Entries F Rom C. <br/> object [] arr = C. toarray (A. Length = 0? A: arrays. copyof (A, 0); </P> <p> for (INT I = 0; I <arr. length; I ++) <br/> arr [I] = new unmodifiableentry <> (map. entry <K, V>) Arr [I]); </P> <p> If (ARR. length>. length) <br/> return (T []) Arr; </P> <p> system. arraycopy (ARR, 0, A, 0, arr. length); <br/> If (. length> arr. length) <br/> A [arr. length] = NULL; <br/> return a; <br/>}Toarray () source code, see the sdk I uploaded in Google code source code: src-jdk1.7.0_02

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.