0

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();
        }
    }
} 
7
  • Consider looking at the source code for the JDK to see how classes are implemented Commented Jul 6, 2016 at 12:24
  • I can't find the part which I want to read. Can you help me? Commented Jul 6, 2016 at 12:31
  • It's spread in various places within the jvm.cpp file: hg.openjdk.java.net/jdk8/jdk8/hotspot/file/87ee5ee27509/src/… - there are also some bits here: hg.openjdk.java.net/jdk8/jdk8/hotspot/file/87ee5ee27509/src/… Commented Jul 6, 2016 at 12:38
  • And just for the sake of it: why do you think you have to know about this? What is the point of defining your own "arrays"; when there are plenty of collection classes around? What would be the practical value of building your "own kinds of arrays"? Commented Jul 6, 2016 at 12:39
  • 2
    I want to understand how it created. The array classes are radically different from other java classes. And I want to understand cause. Commented Jul 6, 2016 at 12:45

4 Answers 4

7

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 (e.g., 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.

Sign up to request clarification or add additional context in comments.

Comments

2

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.

3 Comments

I think this class created by native method and it haven't constructor and other java class specific characters. I want to find source of it.
I think you should be more precise: maybe the array implementation is overriding certain methods from Object, but if so, that is "fixed". One could read your answer as "it is possible that everybody overrides stuff for arrays"; and that is of course not true.
Here is an example of changing Object to make arrays printable +1 vanillajava.blogspot.co.uk/2016/03/…
2

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.

2 Comments

When I want to create new instance of this class, it throws an exception.I investigated and knew about it, but I want any document or sources about this.
Plus one, yes, you do put it well.
1

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".

4 Comments

What is the point of this? It doesn't let you access array elements through the proxy object, so it seems no better than normal object composition.
In this way all methods will invoke method which was overriden by you. System.out.println(proxy.hashCode());
I assume the question was more theoretical than practical: in a real world application I'd wrap the array in an object possibly also extending its functions
You can’t use that proxy “in place of the original object” as these places most likely expect the array type, not a type which just implements Serializable and Cloneable. To create an object having a toString() method, you could just create an arbitrary, e.g. anonymous inner class, just like you already did for creating the InvocationHandler, i.e. new Object() { @Override public String toString() { /* your implementation */ }}.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.