Temat pojawił się na warsztatach : Czy jeśli klasa rozszerza AnyVal i się wywali w Runtimime to co dokładnie będzie widać w stacktrace?
Czy będzie informacja o tym, ze to była klasa czy też będzie tam widniał typ prymitywny?
Odpowiedź na tak postawione pytanie brzmi "Tak, masz rację, teraz mnie zostaw w spokoju"
Labolatorium
Na początek przygotujmy aparaturę badawczą
class Domenowa(val s:String) extends AnyVal
Ćwiczenie pierwsze - zrobić aby coś się wywaliło. Wrzućmy granat w środek :
val d=new Domenowa(null)
"Exception in thread "main" java.lang.NullPointerException
at com.wlodar.nauka.oop.Domenowa$.hashCode$extension"
Zaraz zajrzymy pod mikroskop ale najpierw jeszcze jedna wypierdółka :
class Domenowa(val s:String) extends AnyVal{
null.toString
}
I tu się tego nie spodziewałem :
Error:(18, 10) this statement is not allowed in value class
null.toString
^
Wygląda na to, ze ValueClasses w ogóle nie mogą mieć konstruktorów.
To jeszcze inaczej :
class Domenowa(val s:String) extends AnyVal{
def logic=null.toString
}
I się wywaliło :
Exception in thread "main" java.lang.NullPointerException
at com.wlodar.nauka.oop.Domenowa$.logic$extension
Pod oscyloskop go
Po kompilacji mamy tka naprawdę dwie klasy. Ta
Domenowa$ nie pojawia się gdy nie rozszerzamy AnyVal
-rw-rw-r-- 1 pawel pawel 1875 kwi 12 21:22 Domenowa.class
-rw-rw-r-- 1 pawel pawel 1170 kwi 12 21:22 Domenowa$.class
javap Domenowa
public final class com.wlodar.nauka.oop.Domenowa {
public static boolean equals$extension(java.lang.String, java.lang.Object);
public static int hashCode$extension(java.lang.String);
public static java.lang.String logic$extension(java.lang.String);
public java.lang.String s();
public java.lang.String logic();
public int hashCode();
public boolean equals(java.lang.Object);
public com.wlodar.nauka.oop.Domenowa(java.lang.String);
}
javap Domenowa$
public final class com.wlodar.nauka.oop.Domenowa$ {
public static final com.wlodar.nauka.oop.Domenowa$ MODULE$;
public static {};
public final java.lang.String logic$extension(java.lang.String);
public final int hashCode$extension(java.lang.String);
public final boolean equals$extension(java.lang.String, java.lang.Object);
}
Strzelam, że kiedy wywoływana jest metoda
logic na klasie Domenowej to gdzieś tam pod spodem ten string ze środka jest przekazywany
do tego
logic$extension(java.lang.String). Jest jedna instancja Domenowa$, ValueClasses nie maja pól to nei ma stanu i to wszystko tak działa (chyba).
Postanowiłem zdekompilowac kod z opcja -c by zobaczyć bytecoda
public final java.lang.String logic$extension(java.lang.String);
Code:
0: aconst_null
1: invokevirtual #18 // Method java/lang/Object.toString:()Ljava/lang/String;
4: areturn
Po czym się zastanowiłem po co właściwie chce go zobaczyć jak i tak się na tym nie znam?
To może jednak prościej
Potwórzmy kilka identycznych klas.
class Domenowa(val s:String) extends AnyVal{
def logic=this.toString()
}
println(new Domenowa("abc"))
println(new Domenowa("abc"))
println(new Domenowa("abc"))
println(new Domenowa("abc"))
println(new Domenowa("abc2"))
println(new Domenowa("abc2"))
println(new Domenowa("abc").logic)
println(new Domenowa("abc").logic)
com.wlodar.nauka.oop.Domenowa@17862
com.wlodar.nauka.oop.Domenowa@17862
com.wlodar.nauka.oop.Domenowa@17862
com.wlodar.nauka.oop.Domenowa@17862
com.wlodar.nauka.oop.Domenowa@2d9410
com.wlodar.nauka.oop.Domenowa@2d9410
com.wlodar.nauka.oop.Domenowa@17862
com.wlodar.nauka.oop.Domenowa@17862
I cuda. Jak jest ten sam string to i jest ta sama referencja.
Jeśli dla eksperymentu usuniemy
extends AnyVal to już to nie działa.
Czyli tu nie działa przez co udowadniamy , że ogólnie mechanizm jak taki działa.
class Domenowa(val s:String){
def logic=this.toString()
}
com.wlodar.nauka.oop.Domenowa@48140564
com.wlodar.nauka.oop.Domenowa@58ceff1
com.wlodar.nauka.oop.Domenowa@7c30a502
com.wlodar.nauka.oop.Domenowa@49e4cb85
com.wlodar.nauka.oop.Domenowa@2133c8f8
com.wlodar.nauka.oop.Domenowa@43a25848
com.wlodar.nauka.oop.Domenowa@3ac3fd8b
com.wlodar.nauka.oop.Domenowa@5594a1b5
wracamy do
class Domenowa(val s:String) extends AnyVal{
def logic=this.toString()
}
Znowu zdekompiluje bytecod Domenowa$ (sam nie wiem po co).
public final java.lang.String logic$extension(java.lang.String);
Code:
0: new #16 // class com/wlodar/nauka/oop/Domenowa
3: dup
4: aload_1
5: invokespecial #19 // Method com/wlodar/nauka/oop/Domenowa."":(Ljava/lang/String;)V
8: invokevirtual #23 // Method java/lang/Object.toString:()Ljava/lang/String;
11: areturn
i niby tutaj jest instrukcja
new, która tworzy klasę domenową. Według dokumentacji to alokuje nową instancję a jednak sprawdzaliśmy, że tak się nie dzieje.
Co umacnia mnie w przekonaniu, ze na bytecodzie Javy się nie znam.
http://docs.scala-lang.org/overviews/core/value-classes.html
Najbliższe spotkania i warsztaty ze Scalacheck
W Maju/Czerwcu przyjedzie Damian Warszawski z Touka z warsztatem o Javie8 :
"
żeby się nie zastanawiać za długo to moja propozycja warsztatu:
Intro to java8 workshop:
agenda:
Lambda Expressions
Stream API
DateTime package
W ciągu tygodnia przygotuje repo na githubie i przygotuje krótki opis warsztatu.
"
I jeszcze jakoś na początku maja Cezary Draus który też pracuje w Touku (oraz pociągu relacji Łódź-Warszawa) zrobi warsztaty z intellij.
W tym wszystkim jedyny rozsądny termin w jaki mogę się wcisnąć z warsztatami to 20 kwietnia :
Scalacheck i Property Based Testing - Warsztaty
Będą trzy iventy w tygodniu ale damy radę.
Scalar
W końcu laptop wygląda jak laptop do programowania :
Muszę sobie załatwić drugi zestaw na komputer w pracy zanim mi ktoś nie przylepi naklejek : "Sharepoint,Excel,Outlook,Ms Project,UML "
Konferencja była fajna i dłuższej relacji pisać nie będę bo ludzie później nie kumają dowcipów i rzucają kamieniami w okna :D Było fajnie i tyle.