Frage von Eurocrafter, 38

Unterschied zwischen "type x = value" & "type x = new Type(value)"?

Da gibt es eine Sache, die ich nicht so ganz verstehe.

Ich habe zum Beispiel in "Klasse1" eine Variable public static int zahl = 5. Von einer anderen Klasse "Klasse2" möchte ich jetzt die Variable auf z.B. 10 setzen.

Also schreibe ich in der anderen Klasse "Klasse1.zahl = 10". Das funzt allerdings nicht. Damit das funktioniert muss ich in Klasse1 statt dem oben Genannten folgendes schreiben: "public static int zahl = new Integer(5)". Erst dann kann ich mit "Klasse1.zahl = 10" die Variable verändern.


Meine Frage ist daher: Was genau ist der Unterschied zwischen den beiden Initialisierungen?

Macht das einen Unterschied im Speicherort?

Soweit ich weiß greifen "x = 5" und "y = 5" auf das selbe Objekt zu. Greifen "x = new Integer(5)" und "y = new Integer(5)" dann auf unterschiedliche Objekte zu?

Und warum kann ich von außen nur auf die Variable zugreifen, wenn ich dafür einen neuen Integer erzeugt habe?

Danke schonmal für Antworten

Hilfreichste Antwort - ausgezeichnet vom Fragesteller
von regex9, 25

Könntest du bitte ein kurzes Codebeispiel posten (nutze die Webseite pastebin/...), bei dem dieses Verhalten reproduzierbar ist?

Grundsätzlich liegt der Unterschied darin, dass du mit dem Aufruf von new und einem Typkonstruktor ein neues Objekt des Typen erstelllst.

int a = new Integer(5);

In diesem Fall wird ein Integer-Objekt erstellt, mit dem Wert 5, und via Auto Unboxing in einen primitiven Datentyp gesteckt.

int a = 5;

Hier dagegen wird nur ein primitiver Datentyp mit einem konkreten Wert initialisiert.

Grundsätzlich kommt bei beiden Fällen das gleiche Ergebnis (eine initialisierte Ganzzahlvariable mit primitiven Datentyp) heraus.

Kommentar von Eurocrafter ,

Heißt das, ich kann von außen nur auf Objekte, nicht aber auf primitive Datentypen, wie int, boolean, char, byte etc zugreifen?


Das erklärt einiges.


Hier nochmal der pastebin link. Eigentlich handelt es sich um boolean, das ist jedoch genau wie int ja auch ein primitiver Datentyp.

http://pastebin.com/HdJ2mjqP


Dem Thread t wird übrigens mit new CheckThread(client) ein Socket übergeben... das ganze ist für einen Server gedacht... 

Kommentar von regex9 ,

Heißt das, ich kann von außen nur auf Objekte, nicht aber auf primitive Datentypen, wie int, boolean, char, byte etc zugreifen?

Nein.

Es ist gut, nun deinen konkreten Fall zu sehen, denn du hast ein sehr wichtiges Detail in deiner Fragestellung vergessen zu erwähnen: Du nutzt Threads. Und wenn du Zustände zwischen Threads teilen möchtest, müssen sie auch untereinander richtig synchronisiert werden.

Zuerst einmal Erklärungen zu dem Problem selbst und der Nutzung von synchronized / volatile:

Und konkrete Lösungsmöglichkeiten werden hier mit Beispielen vorgestellt: http://stackoverflow.com/questions/11839881/how-to-stop-a-thread-by-another-thre...

Kommentar von Eurocrafter ,

Anfangs hatte ich auch die Methode interrupt() genutzt, dachte jedoch, dass genau das eher "schlechter Programmierstil" wäre, da man bei Programmteilen wie Thread.sleep(1000) so gut wie immer eine InterruptedException auslöst, da der Thread die meiste Zeit ja mit warten verbringt.

Zu volatile: Damit sorgt man ja dafür, dass die Threads jedes Mal die Variable aktualisieren, bevor sie diese bearbeiten. In deinem 1. Link wird gefragt, ob statische Variablen unter Threads geteilt werden. Scheint nicht so zu sein, ok.

Wie sieht es mit den Getter-/Setter-Methoden aus? Wenn man in der get-Methode ein return x; stehen hat, dann müsste die Variable die zurückgegeben wird, doch immer aktuell sein, oder?

Kommentar von regex9 ,

Wenn man in der get-Methode ein return x; stehen hat, dann müsste die Variable die zurückgegeben wird, doch immer aktuell sein, oder?

Nein. Die Threads laufen doch parallel. In dem Moment, wo x zurückgegeben wird, kann sich x ändern. Daher muss jeder Zugriff auf Variablen eines anderen Threads synchronisiert ablaufen.

Brian Goetz (Java Language Architect bei Oracle) schreibt in seinem Buch Java Concurrency in Practice dazu übrigens folgendes:

It is a common mistake to assume that synchronization needs to be used only when writing to shared variables; this is simply not true.

For each mutable state variable that may be accessed by more than one thread, all accesses to that variable must be performed with the same lock held. In this case, we say that the variable is guarded by that lock.

In the absence of synchronization, the compiler, processor, and runtime can do some downright weird things to the order in which operations appear to execute. Attempts to reason about the order in which memory actions "must" happen in insufflciently synchronized multithreaded programs will almost certainly be incorrect.

Entweder du nutzt

volatile

für dein Feld oder du nutzt

synchronized

Getter und Setter.

Kommentar von regex9 ,

Keine Ahnung, wieso er das jetzt wieder so formatiert... 😒

Kommentar von Eurocrafter ,

Das erklärt echt vieles.

Danke für deine Hilfe

Antwort
von Rums777, 21

Nein, nein und nochmals Nein.

Ich möchte gar nicht erst wissen, wer dir das Programmieren beigebracht hat, aber so wie du das Ganze angehst, wird das nichts.

Als erstes macht es keinen Sinn, dass du ein Attribut static machst (du weißt vermutlich nicht mal, was das bedeutet, also lass am besten die Finger davon) und zweitens sind Attribute fast IMMER private. 

Auf diese Variablen wird dann per Getter- und Setter-Methoden zugegriffen.

Nun zu deiner Frage:

Bei "x=5" weißt du x einen Integer zu. Bei "x=new Integer(5)" weißt du x ein Objekt vom Typ Integer zu! Standardmäßig ist ein int kein Objekt (im Gegensatz zu String).

Kommentar von regex9 ,

Du kennst doch weder Konzept noch konkrete Implementierung seiner Anwendung. Daraufhin einschätzen zu wollen, ob er wirklich weiß, was static macht und ob es hier sinnvoll ist, würde ich vorerst ihm überlassen. 

Kommentar von Eurocrafter ,

1. ich kann auf die Variable von einer anderen Klasse aus nicht zugreifen, wenn sie private ist. Das kann ich nur wenn sie public oder protected ist.

2. Weiß ich schon, was static bedeutet. Statische Variablen kann es nur "einmal" pro Klasse geben. (z.B. wenn man ne Klasse Dog hat. Dann kann es bei 5 Hunden auch 5 mal die Variable age oder height geben. Die Anzahl, also wieviele Hunde es insgesamt gibt, gibt es allerdings nur einmal, wenn diese als static definiert ist)

3. Wieso macht es "keinen Sinn" static zu benutzen? Ich habe mich dabei hier grob orientiert: http://www.java-forum.org/thema/zugriff-auf-variablen-anderer-klassen.102201/

4. Ja, man kann das über die genannten Getter- bzw. Settermethoden machen... ja kann man, das wird auf der Seite auch erwähnt.

5. Ich habe "das Programmieren" in 2 Büchern (darunter "Java ist auch eine Insel" zum nachschlagen) erlernt und mehrere Tutorials in Form von Text und Video genutzt.

6. Nur weil mein Acc-Name vlt n bisschen nach nem 13 jährigen Jungen klingt (ok, das gebe ich zu), ist das noch lange keine Grund, sich hier so dermaßen aufzuführen und den Fragesteller als Deppen darzustellen.

7. Wieso kann man von außerhalb nur auf Objekte und nicht etwa auf Integer oder Boolean zugreifen?

Danke schonmal

Kommentar von Rums777 ,

1. Richtig (protected allerdings auch nur bei Vererbung), aber es geht um die Sicherheit und Fehleranfälligkeit, weshalb alle Variablen auf private gesetzt werden und nur durch Getter- und Setter-Methoden erreichbar sind.

2. Ja und Nein. Prinzipiell geht es darum, dass static nicht Instant-abhängig ist. So musst du für eine normale Methode ein Objekt erzeugen um diese aufrufen zu können, während du bei einer static lediglich eine Klassenreferenz benötigst.

3. Lasse ich unkommentiert (s. Punkt 1, Abschnitt Schöner Programmierstil)

4. Man kann nicht nur, man sollte auch. (selbiges wie unter 3.)

6. Nein. Nur verstehst du die absoluten Grundlagen von Java nicht, und das war für mich in dem Fall unverständlich.

7. Du kannst von außerhalb nur auf public zugreifen. Private ist nie möglich und protected nur, wenn die Klassen in einer Hirachie stehen.

Kommentar von Eurocrafter ,

Würde eine Getter/Setter Methode so ungefähr aussehen?

http://pastebin.com/dm5GPEgB

Noch eine weitere Frage: Muss ich Klasse2 wirklich um Klasse1 erweitern, wenn ich sie in der selben Klasse habe?

In Eclipse z.B. kann man ja Klasse1 und Klasse2 in eine einzige Klasse schreiben, die man im Projekt-Explorer erstellt hat. Man kann aber dort auch 2 verschiedene Klassen erstellen und darin den Quellcode von Klasse1 bzw. Klasse2 einfügen. Muss man in beiden Fällen Klasse2 um Klasse1 erweitern?

Kommentar von Rums777 ,

Prinzipiell Ja. Allerdings sind allgemein ALLE Methoden, die nicht nur von anderen Methoden direkt, sondern auch per Objekt-/Klassenreferenz aufgerufen werden sollen, public. (Im Gegensatz dazu sind Variablen private).

Der allgemeine Kopf einer Getter-Methode ist: public int getX() {return X;}.

Du musst sie nicht erweitern, Nein. Das wäre nur nötig, wenn du dessen Methoden/ Variablen benutzen (im Sinne von überschreiben (s. @Override)) willst, was aber in einfachen Fällen nie der Fall ist. Hierfür ist besonders die Vererbung und die Polymorphie zu beachten.

Ich benutze Eclipse nicht, aber normalerweise musst du in keinem Fall eine Abhängigkeit erstellen (bei 2in1-Klassen weiß ich es nicht, benutze ich nie).

Kommentar von regex9 ,

1./4.) Die Lösung wurde dir bereits genannt:

Auf diese Variablen wird dann per Getter- und Setter-Methoden zugegriffen.

Es ist das Prinzip der Kapselung (bzw. das Data Hiding-Prinzip), welches dir bekannt sein sollte, bevor du mit objektorientierter Programmierung beginnst.

2./3.) Statische Inhalte machen nur dann Sinn, wenn ihre Werte logisch wirklich von allen Objekten so geteilt werden können. Eine Klasse Obst mit einem statischen Feld farbe würde beispielsweise keinen Sinn machen, sofern man bedenkt, dass sich konkrete Objekte diesen Wert nicht teilen (Äpfel = rot, Bananen = gelb, etc.). Ein statisches Feld nur deswegen zu erstellen, um später einfacher darauf zugreifen zu können, ist ein Missbrauch dieses Schlüsselworts.

Dein Feld isRunning bspw. wäre ebenfalls Missbrauch des static-Schlüsselworts, sobald es mehr als nur einen Client in deinem Programmablauf geben sollte.

7.) Siehe unten.

Keine passende Antwort gefunden?

Fragen Sie die Community