2014-11-08 8 views
7

Beh il mio dubbio è questo:Sta ereditando da una matrice primitiva impossibile dalla prospettiva della JVM?

In Java, è annullato a ereditare da una matrice, vale a dire, non si può fare cose come:

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

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

O ancora meglio:

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; 
    } 
} 

Ma gli array implementano effettivamente un'interfaccia specifica e sono considerati oggetti. cioè, ci si aspetta che le istanze dell'array siano gli stessi metodi esposti da Object, più un campo array specifico, il campo 'lunghezza' finale.

Quindi la mia domanda sono, anche se il linguaggio Java non consente questo utilizzo:

  • Potrebbe essere implementato nella JVM senza troppi cambiamenti?

  • La JVM tratta gli array come qualsiasi oggetto con una classe da cui si può ereditare?

  • La JVM tratta gli array come enumerazioni, ovvero rendendo gli oggetti array ereditari automaticamente da una classe di array definita?

  • La classe dell'array è definita da qualche parte in modo da poter essere ereditata?

+1

Considerando che altri linguaggi possono essere implementati sulla JVM, e che tutto ciò che serve in questo caso è una sorta di "cancellazione del tipo" (quando si desidera passare questi array alle API che si aspettano array "regolari") e al boxing (quando ricevi risultati), non riesco a capire perché non si possa fare ... Dal punto di vista del compilatore, ovviamente, questo è molto più complicato ... (disclaimer: I'm not a Java guy) –

+0

Ecco cosa ha ottenuto io penso. Supponi che la VM faccia supposizioni sul layout degli array in memoria poiché sono corretti. Ad esempio, il campo "lunghezza" è a 12 byte sfalsati nell'oggetto, i dati iniziano con 16 byte sfalsati, terminano con "lunghezza" * byte per elemento dopo quello. Le normali operazioni dell'array potrebbero funzionare su questi presupposti. Se non fa ipotesi su cosa si trova oltre i dati dell'array, puoi aggiungere tutti i campi della tua classe ereditata e chiamarla un giorno. Quindi, di nuovo, la risoluzione della posizione di questi campi aggiuntivi * potrebbe * differire da come vengono risolti i normali campi oggetto. – TheStack

risposta

9

Potrebbe essere implementato nella JVM senza troppe modifiche?

No. Le modifiche sarebbero enormi. Avrebbero impatto sull'intera catena di strumenti Java e anche su un enorme corpo di codice di terze parti che funziona al livello di astrazione JLS/JVM o al di sotto.

Non c'è nulla che ti impedisca di scaricare il codice sorgente (OpenJDK) e provare a farlo da solo come esperimento. Ma le probabilità che ciò accada nel reale Java sono (IMO) estremamente piccole.

Ho elencato solo alcuni dei problemi tecnici nella parte inferiore. Sono sicuro che ce ne sono altri.

La JVM tratta gli array come qualsiasi oggetto con una classe da cui si può ereditare?

No.

tipi Array in Java forniscono un piccolo numero di metodi. (I metodi sono getClass, hashCode, toString, clone, wait, notify e notifyAll ... come da Object API.)

quanto ne so, le implementazioni attuali di questi metodi sono forniti dai metodi nativi definiti di java.lang.Object. Ma poiché il JLS non ti permette di scrivere codice che eredita da un array, la specifica JVM non è necessario a fornire un modo per implementare tale codice. E, in pratica, non è così.

La JVM considera gli array come enumerazioni, ovvero rendendo gli oggetti array ereditari automaticamente da una classe di array definita?

No. I tipi di array implicitamente ereditano da java.lang.Object.

La classe dell'array è definita da qualche parte in modo da poter essere ereditata?

Non esiste tale classe. I tipi di matrice ereditano implicitamente da Object.


A livello spec JVM, ci sono un paio di principali ostacoli per rendere array più "classe-like":

  • La rappresentazione "tipo stringa" di un tipo di matrice ("[ elem-type ") menziona solo l'elemento. Il vero tipo di array non ha nome e se lo ha fatto allora "Lname;" la rappresentazione è che dice che questa è una classe regolare, non un tipo di matrice.

  • Le matrici vengono create da speciali istruzioni JVM che forniscono il tipo di elemento come un operando non il tipo di matrice.

E oltre a questo, un'implementazione JVM assumerà le cose su come funzionano gli array al fine di implementarli in modo efficiente. Anche se (secondo il JLS) sembra teoricamente possibile utilizzare un'istruzione invoke per chiamare un metodo non standard su un array, un interprete JVM o un compilatore JIT non saprebbero cosa farne ... anche se si in qualche modo riuscito a intrufolare il invoke oltre il caricatore di classe e verificatore.

Una volta superato questo, il problema è che se gli array possono essere dichiarati con superclassi definite dall'utente, allora tali superclassi potrebbero (presumibilmente) essere in grado di avere variabili di istanza. Ma ciò implica che le specifiche JVM deve cambiare in modo che:

  • i nodi mucchio per le matrici possono contenere variabili di istanza così come la matrice stessa,

  • le istruzioni di caricamento campo e store regolari lavorare su oggetti array e oggetti reculari,

  • e così via.

Come si può vedere, questa "piccola estensione" svela un sacco di altre decisioni di progettazione nella JVM.

+2

Per favore spiega il downvote. –

+0

Non ero io. Ho fatto +1 su di voi.:) – asteri

6

Condivide la JVM per trattamento di array come un qualsiasi oggetto con una classe che può essere ereditato da?

Ogni tipo di matrice primitiva ha effettivamente una classe. Ad esempio, un int[] è in realtà un'istanza di int[].class e un float[] è un'istanza di float[].class. (JLS 10.8) Puoi vedere nel tuo esempio di codice che queste classi non possono essere ereditate da.

La JVM considera gli array come enumerazioni, ovvero rendendo gli oggetti array ereditari automaticamente da una classe di array definita?

Sì, se si hanno due int[] array, dire a e b, quindi a.getClass() == b.getClass().

La classe dell'array è definita da qualche parte in modo da poter essere ereditata?

Come si può vedere nel proprio esempio di codice, queste classi non possono essere ereditate da. Non hanno codice sorgente e sono creati dalla JVM stessa, come detto in this other answer along with a code example.

Potrebbe essere implementato nella JVM senza troppe modifiche?

Questa domanda non rientra nell'ambito di Stack Overflow ed è molto soggettiva.

+1

Questa è un'ottima risposta, ma è più orientata verso le specifiche della lingua. La domanda si rivolge specificamente alle macchine virtuali. – Radiodef

+1

@Radiodef Buon punto. Stavo cercando di rispondere alla domanda nel modo più obiettivo possibile e, leggendolo, ho sentito che le domande "do/could the JVM do XYZ" non rispondevano in questo modo, dal momento che una JVM è libera di implementare qualsiasi funzionalità dal JLS in qualunque come piace a lui. Ciò si riflette ulteriormente nell'ipotesi del richiedente che esiste una sola implementazione JVM. – asteri

+0

Suppongo che sarebbe stato più appropriato per me votare per chiudere piuttosto che tentare di rispondere alla domanda. – asteri

1

Il più vicino che si potrebbe arrivare a questo in Java è il progetto ObjectLayout di Gil Tene - http://objectlayout.org/ - questo è ancora una lunga strada da fare in Java, ma è possibile che questo renderà più come parte di Java 9

+0

Penso che il modo più semplice per adattare la JVM alle cose di tipo array avanzato sarebbe di avere un tipo che rappresenti la concatenazione di una matrice di riferimenti e una matrice di primitivi. Un tal tipo potrebbe, con il supporto del compilatore, essere usato per rappresentare la concatenazione di un'intestazione più un numero arbitrario di elementi, con l'intestazione e gli elementi contenenti ciascuno una raccolta arbitraria di "campi". Cose di quel tipo non sarebbero adatte all'uso nella maggior parte delle interfacce pubbliche, ma potrebbero ridurre la metà del numero di riferimenti indiretti richiesti per accedere a molti tipi di dati. – supercat

+0

Supercat: vorrei andare a discuterne con la gente di ObjectLayout - sono molto amichevoli e sono sicuro che vorrebbero sentir parlare del tuo caso d'uso. – kittylyst

+0

Non ho visto dove la discussione è stata sollecitata laggiù; forse mi sono perso qualcosa? Altrimenti, una delle cose che mi piacerebbe vedere in aggiunta al concetto "intrinseco" sarebbe che Oracle aggiungesse alcuni campi "non vincolati" a 'Thread', in modo che" intrinseco "senza troppi campi potesse essere usato come metodo restituisce valori [ad es un metodo potrebbe restituire un tipo 'Point2d' che consiste di' int x; int y; 'ad es. memorizzando 'x' in' CurrentThread.tempI0' e restituendo 'y'], piuttosto che dover creare una nuova istanza di un oggetto' Point' e sperare che la JVM la ottimizzi.] – supercat