2014-11-08 2 views
7

Ну мои сомнения это одна:Наследуется от примитивного массива, невозможного с точки зрения JVM?

В Java, это запрещено наследовать из массива, то есть, один не может делать такие вещи, как:

class FloatVec extends float[] 
{ 
    // Vector methods. 
} 

FloatVec somevec = new FloatVec()[] { 1, 2, 3 }; // With array initializer. 

Или еще лучше:

class FloatVec3 extends float[3] 
{ 
    // Regular accessor. 
    public float getX() { 
     return this[0]; 
    } 
    // Or say, make it the 'this' implicit like with other fields: 
    public void setVec(float x, float y, float z) { 
     [0] = x; 
     [1] = y; 
     [2] = z; 
    } 
    // And specific vec3 methods like: 
    public float dotProduct() { 
     float x = this[0]; 
     float y = this[1]; 
     float z = this[2]; 
     return x * x + y * y + z * z; 
    } 
} 

Но массивы фактически реализуют определенный интерфейс и считаются объектами. т.е. ожидается, что экземпляры массива будут одинаковыми методами, открытыми объектом, плюс поле определенного массива, поле конечной длины.

Так что мой вопрос есть, даже если язык Java не позволяет это использование:

  • Может быть реализованы в JVM, не слишком много изменений?

  • Подходит ли JVM к массивам, как к любому объекту с классом, который может быть унаследован?

  • Поддерживает ли JVM массивы, такие как перечисления, т. Е. Делает объекты массива наследуемыми автоматически из определенного класса массива?

  • Определен ли класс массива где-то таким образом, чтобы его можно было унаследовать?

+1

Учитывая, что другие языки могут быть реализованы поверх JVM, и что все, что вам нужно в этом случае, это своего рода «стирание типа» (когда вы хотите передать эти массивы API-интерфейсам, ожидающим «регулярные» массивы) и бокс (когда вы получаете результаты), я не понимаю, почему это не может быть сделано ... С точки зрения компилятора, конечно, это намного сложнее ... (отказ от ответственности: я не парень Java) –

+0

Вот что получилось я думаю. Скажем, что VM делает предположения о макете макетов в памяти, так как они исправлены. Например, поле «длина» имеет смещение по 12 байт в объект, данные начинаются с 16-байтового смещения, заканчивается на «длину» * байтов на элемент после этого. Эти допущения могут работать с регулярными массивами. Если он не делает предположений о том, что лежит за пределами данных массива, после этого вы можете добавить все поля своего унаследованного класса и называть его днем. Опять же, устранение местоположения этих дополнительных полей * может * отличаться от того, как разрешены обычные поля объекта. – TheStack

ответ

9

Может ли оно быть реализовано в JVM без особых изменений?

Нет. Изменения были бы массовыми. Они повлияли бы на всю цепочку инструментов Java, а также на огромное количество сторонних кодов, работающих на уровне абстракции JLS/JVM или ниже.

Нет ничего, что помешало бы вам загрузить исходный код (OpenJDK) и попытаться сделать это самостоятельно в качестве эксперимента. Но шансы на это происходят в real Java (IMO) исчезающе мало.

Я перечислил только некоторые из технических проблем внизу. Я уверен, что есть другие.

Подходит ли JVM к массивам, как к любому объекту с классом, который может быть унаследован?

No.

типы массивов в Java обеспечивают небольшое количество методов. (Эти методы getClass, hashCode, toString, clone, wait, notify и notifyAll ... согласно Object API.)

Насколько я знаю, фактические реализации этих методов обеспечиваются собственными методами определены от java.lang.Object. Но поскольку JLS не разрешает вам писать код, который наследуется от массива, спецификация JVM не должна обеспечить способ реализации такого кода. И на практике это не так.

Содержит ли JVM массивы типа перечислений, т. Е. Делает объекты массива наследуемыми автоматически из определенного класса массива?

№ Тип массива неявно наследуется от java.lang.Object.

Определен ли класс массива где-то таким образом, чтобы он мог быть унаследован?

Нет такого класса. Типы массивов неявно наследуются от Object.


На уровне спецификации JVM, есть несколько основных препятствий для создания массивов более «класса, как»:

  • «Тип строки» представление типа массива ("[ elem-type ") упоминает только элемент. Фактический тип массива не имеет имени, и если это так, то «Lname»; Представление говорит, что это обычный класс, а не тип массива.

  • Массивы создаются специальными инструкциями JVM, которые предоставляют тип элемента в качестве операнда, а не тип массива.

И, кроме того, реализация JVM будет предполагать, что массивы работают, чтобы эффективно их реализовать. Несмотря на то, что (согласно JLS) теоретически возможно использовать команду invoke для вызова нестандартного метода в массиве, интерпретатор JVM или компилятор JIT не будут знать, что из этого сделать ... даже если вы как-то удалось прокрасть invoke мимо загрузчика классов и верификатора.

Как только вы пройдете мимо этого, возникает проблема, заключающаяся в том, что если бы массивы могли быть объявлены с помощью пользовательских суперклассов, то эти суперклассы (предположительно) могли бы иметь переменные экземпляра. Но это означает, что JVM спецификации необходимо изменить таким образом, чтобы:

  • кучи узлов для массивов может содержать переменные экземпляра, а также самого массива,

  • инструкции регулярные поля загрузки и сохранения работы на объектов массива, а также объектов рекуперации,

  • и так далее.

Как вы можете видеть, это «небольшое расширение» распутывает множество других проектных решений в JVM.

+2

Пожалуйста, объясните нижний план. –

+0

Не я. Я с тобой сказал.:) – asteri

6

относится ли JVM массивы, как и любой объект с классом, который может быть унаследованной от?

Каждый тип примитивного массива действительно имеет класс. Например, int[] фактически является экземпляром int[].class, а float[] является экземпляром float[].class. (JLS 10.8) Вы можете увидеть в своем собственном примере кода, что эти классы не могут быть унаследованы.

Содержит ли JVM массивы типа перечислений, т. Е. Делает объекты массива наследуемыми автоматически из определенного класса массива?

Да, если у вас есть два int[] массивов, скажем a и b, то a.getClass() == b.getClass().

Определен ли класс массива где-то таким образом, чтобы он мог быть унаследован?

Как вы можете видеть в своем собственном примере кода, эти классы не могут быть унаследованы. Они не имеют исходного кода и создаются самим JVM, как указано in this other answer along with a code example.

Может ли оно быть реализовано в JVM без особых изменений?

Этот вопрос выходит за рамки переполнения стека и очень субъективен.

+1

Это отличный ответ, но он больше ориентирован на спецификацию языка. В вопросе конкретно спрашивается о виртуальных машинах. – Radiodef

+1

@Radiodef Хорошая точка. Я старался максимально объективно ответить на этот вопрос, и, читая его, я чувствовал, что вопросы «не могут ли JVM делать XYZ» не были такими, как JVM, поскольку JVM может свободно использовать любую функциональность из JLS во всех как ему нравится. Это также находит отражение в предположении автора того, что существует только одна реализация JVM. – asteri

+0

Полагаю, для меня было бы более подходящим для голосования, а не пытаться ответить на вопрос. – asteri

1

Ближайшим что вы могли бы получить на это в Java является проект Гил Тен в ObjectLayout - http://objectlayout.org/ - это еще долгий путь от превращения ее в Java, но это только возможно, что это сделает его как часть Java 9

+0

Я думаю, что самый простой способ адаптировать JVM для расширенных массивных вещей - это иметь тип, который представляет собой конкатенацию массива ссылок и массив примитивов. Такой тип мог бы, с поддержкой компилятора, использоваться для представления конкатенации заголовка плюс произвольное количество элементов, причем заголовок и элементы каждый содержат произвольный набор «полей». Вещи такого типа не подходят для использования в большинстве общедоступных интерфейсов, но могут сократить вдвое количество передач, необходимых для доступа ко многим видам данных. – supercat

+0

Supercat: Я бы пошел и обсудил его с людьми ObjectLayout - они дружелюбны, и я уверен, что они хотели бы услышать о вашем случае использования. – kittylyst

+0

Я не видел, где там было предложено обсуждение; возможно, я что-то пропустил? В противном случае одна из вещей, которые я хотел бы видеть в качестве дополнения к «внутренней» концепции, заключалась бы в том, чтобы Oracle добавила несколько «незапущенных» полей в «Thread», чтобы можно было использовать «intrinsics» без слишком большого количества полей как возвращаемые значения метода [например, метод может возвращать тип 'Point2d', состоящий из' int x; int y; ', например. сохраняя 'x' в' CurrentThread.tempI0' и возвращая 'y'], вместо того, чтобы создавать новый экземпляр объекта« Point »и надеемся, что JVM оптимизирует его.] – supercat

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