2016-07-06 4 views
-1

Могу ли я переопределить любые методы array?
Например, toString() или другими способами.Как JVM реализовал класс массива?

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(); 
     } 
    } 
} 
+0

Рассмотрите [исходный код] (http://hg.openjdk.java.net/) для JDK, чтобы узнать, как реализуются классы. –

+0

Я не могу найти часть, которую я хочу прочитать. Вы можете мне помочь? – Gev

+0

Он распространяется в разных местах файла jvm.cpp: http://hg.openjdk.java.net/jdk8/jdk8/hotspot/file/87ee5ee27509/src/share/vm/prims/jvm.cpp - есть также некоторые бит здесь: http://hg.openjdk.java.net/jdk8/jdk8/hotspot/file/87ee5ee27509/src/share/vm/oops/objArrayKlass.cpp – assylias

ответ

4

Вы не можете изменять какие-либо функции массивов. JLS §10.7 Array Members определяет каждый член массива:

Члены типа массива все из следующих действий:

  • publicfinal поле length, который содержит число компонентов массива. length может быть положительным или нулевым.

  • Метод publicclone, который переопределяет метод с таким же именем в классе Object и не отменяет проверенных исключений. Возвращаемым типом метода clone типа массива T[] является T[].

    Клон многомерного массива неглубокий, то есть он создает только один новый массив. Subarrays разделяются.

  • Все наследуемые от класса Object; единственным методом Object, который не унаследован, является его метод clone.

Спецификация не позволяет какой-либо способ настройки этой реализации. Например, метод массива toString() всегда является основным, унаследованным от Object.

Чтобы создать массив объекта компилятор генерирует один из трех инструкций в скомпилированный Java bytecode: newarray для примитивов, anewarray для ссылочных типов, или multinewarray для всех многомерных массивов. При реализации этих инструкций виртуальная машина создает каждый класс массива по мере необходимости во время выполнения (JVMS §5.3.3 Creating Array Classes). ВМ также определяет специальные инструкции байт-кода для компилятора, которые будут использоваться для получения и установки элементов массивов и получения длины массива.

Как массивы, реализованные внутри виртуальной машины, не указаны вообще. Это чисто детализация реализации, и даже компилятор Java не знает или не заботится. Фактический задействованный код зависит от вкуса виртуальной машины, на которой запущена ваша программа, от версии этой виртуальной машины, ОС и процессора, на котором она работает, и любых соответствующих параметров времени выполнения, с которыми настроена виртуальная машина (например, в режиме интерпретации или нет).

быстрый взгляд поверх исходного кода OpenJDK 8 поворачивает вверх некоторые из соответствующих машин для массивов:

В массивах являются основной особенностью языка и виртуальной машины, что невозможно указать ни одного исходного файла и сказать «вот, это class Array код». Массивы являются специальными, а техника, которая их реализует, буквально повсюду.


Если вы хотите настроить поведение массива, единственное, что вы можете сделать, это не использовать массив напрямую, а использовать, подкласс, или написать, класс коллекции, который внутри содержит массив. Это дает вам полную свободу определять поведение и характеристики класса. Тем не менее, невозможно сделать пользовательский класс be массивом в смысле языка Java. Это означает, что вы не можете заставить его реализовать оператор [] или быть приемлемым для метода, который ожидает массив.

2

В Java все массивы (в том числе примитивных типов) имеют java.lang.Object в качестве своего базового класса. (Во-первых, это то, как можно моделировать массивы нулевой длины).

Хотя в этом базовом классе можно переопределить любой метод, сама Java задает форму массива. Вы не можете вмешиваться в это: в частности вы не можете массива массива extend.

+0

Я думаю, что этот класс создан встроенным методом и у него нет конструктора и других символов класса java. Я хочу найти его источник. – Gev

+2

Я думаю, что вы должны быть более точными: возможно, реализация массива переопределяет определенные методы из Object, но если так, то это «исправлено». Можно было бы прочитать ваш ответ как «возможно, что все переопределяют материал для массивов»; и это, конечно, не так. – GhostCat

+0

Вот пример изменения объекта, чтобы сделать массивы для печати +1 http://vanillajava.blogspot.co.uk/2016/03/printing-arrays-by-hacking-jvm.html –

2

Чтобы ответить на ваш прямой вопрос: нет, вы не можете.

Массивы - это «компилятор» - компилятор знает, что означает String []; и он создает из этого соответствующий байтовый код. Вы можете создавать объекты массива, но не «новые классы массивов». Кроме того, JVM знает, что делать с инструкциями байт-кода, использующими «массив».

Иными словами: исходный код, определяющий поведение объектов Array-of-something, полностью не контролируется. Массивы просто делают то, что делают массивы; вы не можете вмешиваться в это.

И чтобы добраться до подразумеваемого вопрос, почему все это так:

Иногда там не так много, чтобы понять ; но просто до принять. Дело в том, что язык Java был создан почти 20 лет назад; и в какой-то момент некоторые люди сделали некоторые варианты дизайна. Многие из них были превосходны; некоторые из них, возможно, были бы обработаны, если бы мы переделали вещи в наши дни.

Вы найдете, например, что у Scala есть другой способ работы с массивами. Но для джавы все так, как есть; и особенно для вещей, которые «настолько явны» для языка, как массивы, просто нет смысла менять какое-либо из них в наши дни.

+0

Когда я хочу создать новый экземпляр этот класс, он порождает исключение. Я исследовал и знал об этом, но мне нужен любой документ или источники об этом. – Gev

+0

Плюс один, да, это хорошо. – Bathsheba

1

Вы можете создать прокси-сервер и использовать его вместо оригинального объекта

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()); 

выход из выше «массив 1 2 3 1».

+0

Да! спасибо, это интересно. – Gev

+1

В чем смысл этого? Он не позволяет вам обращаться к элементам массива через прокси-объект, поэтому он кажется не лучше, чем нормальный состав объекта. – Boann

+0

Таким образом, все методы вызовут метод, который был переоценен вами. \t System.out.println (proxy.hashCode()); – Gev

Смежные вопросы