Diamo le due versioni differenti nomi per renderli un po 'più facile parlare di:
object Foo1 {
class Bar1
}
object Foo2 {
object Bar2 {
class Baz2
}
}
Ora, se si guardano i file di classe, vedrete che il compilatore Scala ha creato una classe Foo1
. Quando si esegue javap -v
su Foo1$Bar1
, vedrai che questa classe è elencato come classe contenitrice:
InnerClasses:
public statiC#14= #2 of #13; //Bar1=class Foo1$Bar1 of class Foo1
Questo è esattamente ciò che accadrebbe con una classe innestata statica in Java, in modo che il compilatore Java è perfettamente felice di compilare new Foo1.Bar1()
per te.
Ora guardate la javap -v
output per Foo2$Bar2$Baz2
:
InnerClasses:
public statiC#16= #13 of #15; //Bar2$=class Foo2$Bar2$ of class Foo2
public statiC#17= #2 of #13; //Baz2=class Foo2$Bar2$Baz2 of class Foo2$Bar2$
Ora classe contenitrice è Foo2$Bar2$
, non Foo2$Bar2
(in realtà il compilatore Scala non ha nemmeno genera un Foo2$Bar2
a meno che non si aggiunge una classe compagno per object Bar2
). Il compilatore Java si aspetta che una classe interna statica Baz2
di una classe che include Foo2$Bar2$
sia denominata Foo2$Bar2$$Baz2
, con due segni di dollaro. Questo non corrisponde a quello che è effettivamente ottenuto (Foo2$Bar2$Baz2
), quindi dice no a new Foo2.Bar2.Baz2()
.
Java è perfettamente felice di accettare i segni del dollaro nei nomi delle classi, e in questo caso poiché non può capire come interpretare Foo2$Bar2$Baz2
come una classe interna di qualche tipo, ti consente di creare un'istanza con new Foo2$Bar2$Baz2()
. Quindi questa è una soluzione, ma non molto carina.
Perché il compilatore Scala trattare Foo1
e Bar2
modo diverso (nel senso che Bar2
non ottiene una classe Bar2
), e perché la classe racchiude elencati l'attributo InnerClasses
per Baz2
avere un simbolo del dollaro alla fine, mentre quello per Bar1
no? Non ne ho davvero idea. Ma questa è la differenza: basta un po 'più di verbosità per vederlo con javap
.
fonte
2015-06-12 19:03:34