简体   繁体   中英

How did JVM implement array's class?

Can I override any methods of array ?
For example toString() or other methods.

import java.lang.reflect.Method;

public class ArraysClassTest {
    static int[] array = { 1, 2, 3, 1 };

    public static void main(String[] args) {
        Class<? extends int[]> class1 = array.getClass();
        try {
            Method method = class1.getMethod("toString");
        } catch (NoSuchMethodException | SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
} 

You can't change any features of arrays. JLS §10.7 Array Members specifies every member of an array:

The members of an array type are all of the following:

  • The public final field length , which contains the number of components of the array. length may be positive or zero.

  • The public method clone , which overrides the method of the same name in class Object and throws no checked exceptions. The return type of the clone method of an array type T[] is T[] .

    A clone of a multidimensional array is shallow, which is to say that it creates only a single new array. Subarrays are shared.

  • All the members inherited from class Object ; the only method of Object that is not inherited is its clone method.

The specification doesn't allow any way of customizing this implementation. An array's toString() method, for example, is always the basic one inherited from Object .

To create an array object the compiler emits one of three instructions into the compiled Java bytecode : newarray for primitives, anewarray for reference types, or multinewarray for all multidimensional arrays. In implementing those instructions, the virtual machine creates each array class as needed at runtime ( JVMS §5.3.3 Creating Array Classes ). The VM also defines dedicated bytecode instructions for the compiler to use for getting and setting elements of arrays and getting an array's length.

How the arrays are implemented within the VM is not specified whatsoever. It is purely an implementation detail, and even the Java compiler doesn't know, or care. The actual code involved depends on the flavor of virtual machine you're running your program on, the version of that VM, the OS and CPU it's running on, and any relevant runtime options the VM is configured with (eg, whether in interpreted mode or not).

A quick look over the OpenJDK 8 source code turns up some of the relevant machinery for arrays:

As arrays are a core feature of the language and the VM, it's impossible to point to any one source file and say "here, this is the class Array code". Arrays are special, and the machinery that implements them is literally all over the place.


If you want to customize the behavior of an array, the only thing you can do is not use the array directly, but use, subclass, or write, a collection class that internally contains the array. That gives you complete freedom to define the class's behavior and performance characteristics. However, it is impossible to make a custom class be an array in the Java language sense. That means you can't make it implement the [] operator or be passable to a method that expects an array.

In Java, all arrays (including those of primitive types) have java.lang.Object as their base class. (For one thing this is how zero length arrays can be modelled).

Although it's possible to override any method in that base class, Java itself specifies the form of the array. You are not able to interfere with that: in particular you can't extend an array.

To answer your direct question: no, you can't.

Arrays are a "compiler" construct - the compiler knows what String[] means; and it creates the corresponding byte code out of that. You can only create array objects, but not "new array classes". Or beyond that, the JVM knows what to do about "array using" bytecode instructions.

In other words: the source code that defines the behavior of Array-of-something objects is completely out of your control. Arrays just do what arrays do; no way for you to interfere with that.

And to get to your implicit question why things are this way:

Sometimes there isn't much to understand ; but simply to accept . Thing is that the Java language was created almost 20+ years ago; and at some point, some folks made some design choices. Many of them were excellent; some of them might have been handled if we would redo things nowadays.

You will find for example, that Scala has a different way of dealing with arrays. But for java, things are as they are; and especially for things that are "so core" to the language as arrays, there is simply no sense in changing any of that nowadays.

You can create a proxy and use it in place of the original object

final int[] array = { 1, 2, 3, 1 };
Object proxy = Proxy.newProxyInstance(array.getClass().getClassLoader(), array.getClass().getInterfaces(), new InvocationHandler() {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        StringBuilder b=new StringBuilder("the array is");
        for(int i:array)
            b.append(" ").append(i);
        return b.toString();
    }
});
System.out.println(proxy.toString());

the output of the above is " the array is 1 2 3 1 ".

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