JVM是如何实现数组的类的?

时间:2016-07-06 12:21:30

标签: java jvm

我可以覆盖array的任何方法吗? 例如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();
        }
    }
} 

4 个答案:

答案 0 :(得分:4)

您无法更改数组的任何功能。 JLS §10.7 Array Members指定数组的每个成员:

  

数组类型的成员是以下所有成员:

     
      
  • public final字段length,其中包含数组的组件数。 length可能是正数或零。

  •   
  • public方法clone,它会覆盖类Object中相同名称的方法,并且不会抛出任何已检查的异常。数组类型clone的{​​{1}}方法的返回类型为T[]

         

    多维数组的克隆很浅,也就是说它只创建一个新数组。子阵列是共享的。

  •   
  • 所有成员都继承自班级T[];唯一没有继承的Object方法是Object方法。

  •   

规范不允许任何自定义此实现的方法。例如,数组的clone方法始终是从toString()继承的基本方法。

要创建数组对象,编译器会将三条指令中的一条发送到已编译的Java bytecodeObject表示基元,newarray表示引用类型,或anewarray表示所有多维阵列。在实现这些指令时,虚拟机会在运行时根据需要创建每个数组类(JVMS §5.3.3 Creating Array Classes)。 VM还为编译器定义专用字节码指令,用于获取和设置数组元素以及获取数组的长度。

无法指定

如何在VM中实现数组。它纯粹是一个实现细节,甚至Java编译器也不知道或关心。所涉及的实际代码取决于您运行程序的虚拟机的风格,该VM的版本,运行的操作系统和CPU以及VM配置的任何相关运行时选项(例如,是否处于解释模式或不)。

快速浏览一下OpenJDK 8源代码,可以找到一些相关的数组机制:

由于数组是语言和VM的核心功能,因此无法指向任何一个源文件并说“这里,这是multinewarray代码”。数组是特殊的,实现它们的机器实际上就是一切。

如果要自定义数组的行为,您唯一能做的就是不直接使用数组,而是使用,子类或写入内部包含数组的集合类。这使您可以完全自由地定义类的行为和性能特征。但是,在Java语言意义上,不可能使自定义类成为数组。这意味着你无法使它实现class Array运算符或者可以传递给需要数组的方法。

答案 1 :(得分:2)

在Java中,所有数组(包括原始类型的数组)都以java.lang.Object为基类。 (一方面,这是如何建模零长度数组)。

尽管可以覆盖该基类中的任何方法,但Java本身也指定了数组的形式。你无法干涉:特别是你不能extend数组。

答案 2 :(得分:2)

回答你的直接问题:不,你不能。

数组是一个“编译器”构造 - 编译器知道String []的含义;并从中创建相应的字节代码。您只能创建数组对象,但不能创建“新数组类”。或者除此之外,JVM知道如何处理“使用”字节码指令的数组。

换句话说:定义Array-of-something对象行为的源代码完全不受您的控制。数组只是做数组做的事情;没办法让你干涉。

为了得到你隐含的问题,为什么会这样:

有时理解并不多;但只是接受。事实是Java语言是在大约20多年前创建的;在某些时候,有些人做了一些设计选择。其中许多都很优秀;如果我们现在重做一些东西,其中一些可能已被处理。

例如,您会发现Scala有一种不同的处理数组的方式。但是对于java来说,事情就像它们一样;特别是对于那些像数组这样语言“如此核心”的东西,现在改变任何一种都没有任何意义。

答案 3 :(得分:1)

您可以创建代理并使用它代替原始对象

@GET("yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20**text%3D%22{location}%2C%20be%22)%20and%20u%3D%27c%27&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys")
Call<response> groupList(@Path("location") String location);

上面的输出是&#34; 数组是1 2 3 1 &#34;。