Permalänk
Medlem

Java: Arv & initiering

Behöver lite hjälp att tyda lite kod och dess utskrifter. Lite förståelseövningar..

Child.java:

package inherit.init; public class Child extends Parent { private /*static*/ int num = 10; public int lookup() { return num; } }

Parent.java:

package inherit.init; public class Parent { private int val; public Parent() { val = lookup(); } public int value() { return val; } public int lookup() { return 5;// Silly } }

Main.java:

package inherit.init; public class Main { public static void main(String args[]) { Child child = new Child(); System.out.println("child.value() returns " + child.value()); Parent parent = new Child(); System.out.println("parent.value() returns " + parent.value()); Parent parent2 = new Parent(); System.out.println("parent2.value() returns " + parent2.value()); } }

Utskriften första rundan, med bortkommenterad "static" i "Child.java", ger:

child.value() returns 0 parent.value() returns 0 parent2.value() returns 5

Detta förstår jag. "val" är inte tillsatt något värde, och defaultar därmed till 0. Men om man låter där stå "static", så ger det utskriften:

child.value() returns 10 parent.value() returns 10 parent2.value() returns 5

Varför blir det 10/10/5? Tiorna måste ju isåfall komma ur konstruktorn i "Parent"..? Förstår inte kopplingen.
Första raden borde fortfarande bli noll; den anropar ju value() igen, som inte är satt till något?
Vore väldigt snällt om jag kunde få en länk om info, eller om någon bemödar sig förklara varför och vad som sker?

Tack på förhand!

Visa signatur

WS: Asus P8Z77-I Deluxe mITX | Intel 3770K@4.6 | NH-U12P | Asus 780 GTX | Corsair 2x8GB 1600Mhz CL9 | Samsung 840 512GB | Ubuntu 16.04.3 x86_64 | Corsair AX750 | 2x Dell U2412M | Puppe.se | NAS: i7 860, 16GB DDR3, GA-P55M-UD4, FD Define R3, 8x2TB Samsung F4EG, Serveraid M1015, EVGA 750W G2 PSU, FreeBSD x64

Permalänk
Medlem

Det bästa sättet för att se vilka metoder som blir anropade i vilken ordning, är att helt enkelt lägga in en skrivning till standard out i varje metod. Då får du en fin utskrift för att se hur det fungerar. Så ändra dina klasser till följande, så borde du få en bättre överblick och förståelse.

package inherit.init; public class Child extends Parent { private /*static*/ int num = 10; /* När du avkommenterar static ovanför, avkommentera även denna rad: */ //static { System.out.println("Setting static variable num to 10"); } public int lookup() { System.out.println("Calling " + this.getClass().toString() + " method lookup() in Child"); return num; } } package inherit.init; public class Parent { private int val; public Parent() { System.out.println("Calling Parent constructor"); val = lookup(); } public int value() { System.out.println("Calling " + this.getClass().toString() + " method value()"); return val; } public int lookup() { System.out.println("Calling " + this.getClass().toString() + " method lookup() in Parent"); return 5;// Silly } }

Är du ändå osäker, kan du t.ex. numrera dina utskrifter så att du ser vad som händer. Ett litet tips, istället för att ge dig svaret.

Permalänk
Medlem

Re: Java: Arv & initiering

Citat:

Ursprungligen inskrivet av Schrimp
Men om man låter där stå "static", så ger det utskriften:

child.value() returns 10 parent.value() returns 10 parent2.value() returns 5

Varför blir det 10/10/5? Tiorna måste ju isåfall komma ur konstruktorn i "Parent"..? Förstår inte kopplingen.
Första raden borde fortfarande bli noll; den anropar ju value() igen, som inte är satt till något?

* Statiska medlemmar initialiseras alltid först. (De initialiseras i den ordning de står, sett uppifrån och ner i en fil.)
* Du överlagrar inte konstruktorn i Child. Varje instans av Child skapas således genom den implicita, tomma, Child(), som i sin tur gör ett implicit anrop till Parent() det första som sker. Alla konstruktorer i Java anropar en föräldraklass-konstruktor (som anropar en föräldra-konstruktor, som anropar...) innan den egna konstruktorn körs. Om du inte själv specificerar vilken som ska användas (m.h.a. super-nyckelordet) anropas den som inte tar några argument.
* Parent() sätter val till lookup(). Det är dock inte Parent.lookup() som anropas, utan den överlagrade Child.lookup()! Denna sätter ju val till num dvs 10. Eftersom både instanserna "child" och "parent" i är Child-instanser så får du 10.

Permalänk
Medlem

Tack bjornie, det var ett väldigt bra tips (som säkert är "självklart" för den vane javaknackaren, hehe) jag ska ta med mig!

Ditt tips och badbolls eminenta förklaring gav mig nog lösningen. Jag tror jag förstår vad detta gällde nu!

Visa signatur

WS: Asus P8Z77-I Deluxe mITX | Intel 3770K@4.6 | NH-U12P | Asus 780 GTX | Corsair 2x8GB 1600Mhz CL9 | Samsung 840 512GB | Ubuntu 16.04.3 x86_64 | Corsair AX750 | 2x Dell U2412M | Puppe.se | NAS: i7 860, 16GB DDR3, GA-P55M-UD4, FD Define R3, 8x2TB Samsung F4EG, Serveraid M1015, EVGA 750W G2 PSU, FreeBSD x64

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av bjornie

...

Är du ändå osäker, kan du t.ex. numrera dina utskrifter så att du ser vad som händer. Ett litet tips, istället för att ge dig svaret.

Lånar tråd. Nu var det ett tag sen jag programmerade Java så ursäkta om frågan är korkad, men finns det någon fördel med att uttryckligen anropa toString() i samband med getClass()-anropet i debug-strängarna?

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem

Nej, det var enbart för att vara tydlig.