简体   繁体   English

JVM如何实现数组的类?

[英]How did JVM implement array's class?

Can I override any methods of array ? 我可以覆盖任何array方法吗?
For example toString() or other methods. 例如toString()或其他方法。

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: JLS§10.7 数组成员指定数组的每个成员:

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. public final字段length ,其中包含数组的组件数。 length may be positive or zero. length可以是正数或零。

  • The public method clone , which overrides the method of the same name in class Object and throws no checked exceptions. public方法clone ,它将覆盖Object类中的同名方法,并且不引发任何检查异常。 The return type of the clone method of an array type T[] is T[] . 数组类型T[]clone方法的返回类型为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 ; 所有成员都继承自类Object ; the only method of Object that is not inherited is its clone method. 不继承的Object的唯一方法是其clone方法。

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 . 例如,数组的toString()方法始终是从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. 为了创建一个数组对象编译器发出一三指令到编译Java字节码newarray为原语, anewarray对于引用类型,或multinewarray所有多维数组。 In implementing those instructions, the virtual machine creates each array class as needed at runtime ( JVMS §5.3.3 Creating Array Classes ). 在实施这些指令时,虚拟机将在运行时根据需要创建每个数组类( JVMS§5.3.3 创建数组类 )。 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. VM还为编译器定义了专用字节码指令,以供编译器用于获取和设置数组元素以及获取数组的长度。

How the arrays are implemented within the VM is not specified whatsoever. 尚未说明如何在VM中实现阵列。 It is purely an implementation detail, and even the Java compiler doesn't know, or care. 它纯粹是实现细节,甚至Java编译器也不知道或不在乎。 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). 涉及的实际代码取决于您在其上运行程序的虚拟机的风格,该VM的版本,其运行的OS和CPU以及配置了VM的任何相关运行时选项(例如,是否处于解释模式)或不)。

A quick look over the OpenJDK 8 source code turns up some of the relevant machinery for arrays: 快速浏览OpenJDK 8源代码会发现一些与阵列有关的机制:

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". 由于数组是语言和VM的核心功能,因此不可能指向任何一个源文件并说“这里是class Array代码class Array ”。 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. 但是,就Java语言而言,使自定义类成为数组是不可能的。 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. 在Java中,所有数组(包括原始类型的数组)都将java.lang.Object作为其基类。 (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. 尽管可以覆盖该基类中的任何方法,但是Java本身指定数组的形式。 You are not able to interfere with that: in particular you can't extend an array. 您将无法对此进行干预:尤其是您无法extend数组。

To answer your direct question: no, you can't. 要回答您的直接问题:不,您不能。

Arrays are a "compiler" construct - the compiler knows what String[] means; 数组是一个“编译器”构造-编译器知道String []的含义; 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. 或除此之外,JVM知道如何处理“使用”字节码指令的数组。

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; 事实是Java语言是在20年前左右创建的。 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. 例如,您会发现Scala具有不同的数组处理方式。 But for java, things are as they are; 但是对于Java来说,一切都保持不变。 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 ". 上面的输出是“ array is 1 2 3 1 ”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM