Klassen InitialisierungsBlöcke

kaoZ

Top Contributor
Aloha , hier mal eine Kleine Frage bezüglich Initialisierungsblöcken

Folgende Situation:

Ich habe eine Klasse 'Name' erstellt, diese möchte ich an mehreren unterschiedlichen stellen einsetzen, z.B später für Klassen die Gegenstände oder Personen darstellen.

um zu vermeiden das bei einer Abfrage an einem Objekt der Klasse 'Name' der wert
Code:
 null
zurückgegeben wird, habe ich einen Initialisierungsblock genutzt, macht man das so ? oder sollte man die Variablen direkt initialisieren anstatt sich auf Lazy Initialisation zu stützen ?

Also entweder so :

Java:
public class Name {
	
	private String name		 = "";
	private String lastName	 = "";
	private String alias	 = "";
...

oder so ?

Java:
public class Name {
	
	private String name		 = "";
	private String lastName	 = "";
	private String alias	 = "";

	
	public Name(String name) {
		tokenizeInput(name);
	}
	
	public Name(String name, String alias){
		tokenizeInput(name);
		this.alias = alias;
	}
	
	private void tokenizeInput(String input){
		if (input.length() <= 0) {
			throw new IllegalArgumentException("'input' length cannot be <= 0 ");
		}
		else{
			if (!input.trim().contains(" ")) {
				this.name = input;
			}
			else{
				String[] token = input.trim().split(" ");
				
				this.name = token[0];
				this.lastName = token[1];
			}
		}
	}
	
	public String getName() 				{return this.name;}
	public String getLastName()				{return this.lastName;}
	public String getAlias()				{return this.alias;}
	public String getFullName()				{return this.name + " " + this.lastName;}
	
	@Override
	public String toString(){
		return String.valueOf(this.name + " " + this.lastName + " " + this.alias);
	}
	
	public static void main(String[] args) {
		Name a = new Name("");
		System.out.println(a.getFullName());
	}
}

Wenn ich jetzt später z.B in einer Klasse Autor welche als Attribut einen Namen hat, über einen getter den alias abfrage , dürfte es doch so nicht passieren das der Wert null geliefert wird , sondern "", also sprich ein leerer String?
 
Zuletzt bearbeitet:

Flown

Administrator
Mitarbeiter
Also den static "Konstruktor" sollte man wirklich nur bei static Klassen/Methoden verwenden.

Aber warum willst du denn nicht, dass man null erhält? Wenn du so weiterverfährst kann es sein, dass 2 leere Objekte gleich sind, wenn dies wer überprüft, obwohl es eigentlich null sein sollte (nur mal so weitergedacht)?
 

kaoZ

Top Contributor
Du hast schon recht, allerdings müsste ich mich dann aber auch wieder überall wo eben nicht null übergeben werden kann / soll um die Behandlung ( prüfung der Eingabeparameter) kümmern um das werfen von NPE zu vermeiden , wenn ich mich nicht irre ?!

Dachte man könnte da so gleich nen Riegel vorschieben ....;)

[EDIT]
Zudem muss ich mich wie ich grade Feststelle auch noch um ausnahmen Situation der Eingabeparameter kümmern , z.B bei Doppelnamen ^^ sonst hat irgendwann mal jemand keinen Nachnamen :lol:
[/EDIT]
 
Zuletzt bearbeitet:

Joose

Top Contributor
Java:
public class Name {
	
	private String name		 = "";
	private String lastName	 = "";
	private String alias	 = "";
...

Wäre möglich, aber du kannst auch einen Standardkonstruktor verwenden (ohne Parameter) und dort diese Initialisierungen machen.

Wie du es machst ist egal, beides klappt und ist richtig. Ich persönlich initialisere gerne alles im Konstruktor. Da habe ich alles auf einen Fleck initialisiert (Ausnahme statische Werte, Konstanten etc)

Java:
public class Name {
	
	private String name;
	private String lastName;
	private String alias;
	
	{
		name	 = "";
		lastName = "";
		alias	 = "";
	}
	....
}

Wenn ich jetzt später z.B in einer Klasse Autor welche als Attribut einen Namen hat, über einen getter den alias abfrage , dürfte es doch so nicht passieren das der Wert null geliefert wird , sondern "", also sprich ein leerer String?

Ja wäre korrekt, aber nicht schön.

Außerdem hat Flown mit seinem Einwand Recht. Wenn es wirklich eine Klasse ist die du an vielen anderen Stellen (und vl auch Projekten verwenden willst) solltest du überlegen ob du wirklich "" brauchst oder ob null reicht.

[EDIT]
Du hast schon recht, allerdings müsste ich mich dann aber auch wieder überall wo eben nicht null übergeben werden kann / soll um die Behandlung ( prüfung der Eingabeparameter) kümmern um das werfen von NPE zu vermeiden , wenn ich mich nicht irre ?!

Dachte man könnte da so gleich nen Riegel vorschieben ....;)

Jein, wenn du einer Methode Parameter übergibst sollte diese Methode
a) die Parameter auf Korrektheit prüfen und notfalls eine Exception werfen
b) die Parameter akzeptieren wie sie übergeben werden, und entweder
b1) die Exception behandeln
b2) die Parameter soweit anzupassen das sie für die Verarbeitung korrekt sind (Achtung bei Objekten als Parameter muss man aufpassen wenn man Änderungen durchführt)
[/EDIT]
 
Zuletzt bearbeitet:

kaoZ

Top Contributor
Nehmen wir doch mal folgenden fall an

Java:
public class Author {
	
	private Name name;
	
	public Author(String name) {
		if (name.length() <= 0) {
			throw new IllegalArgumentException("'name' length cannot be <= 0");
		}
		else{
			this.name = new Name(name);
		}
	}
	
	public String getName() 				{return this.name.getName();}		
	public String getLastName()				{return this.name.getLastName();}
	public String getFullName()				{return this.name.getFullName();}
	public String getAlias()				{return this.name.getAlias();}

	
	public static void main(String[] args) {
		Author a = new Author("Peter Fonda");
		System.out.println(a.getName());
		System.out.println(a.getLastName());
		System.out.println(a.getFullName());
		System.out.println(a.getAlias());
	}
}

Ausgabe:

Peter
Fonda
Peter Fonda
null

Hier nutze ich Beispielsweise ein Attribut vom Typ Name
mit Prüfung des Eingabeparameters und Anpassung der Exception , bzw. der Beschreibung , sonst würde ja die der Klasse Name geworfen werden

hier wird durch den Aufruf des getters folgendes geliefert:

Code:
Peter null

da der Alias des Attributes nicht gesetzt wurde, dies kann doch dann aber an falscher Stelle wiederrum zu einer NPE führen oder ?
Sollte man dann im Konstruktor nicht gleich angeben das eine Nullpointer Exception geworfen werden kann ?

Sonst muss ich halt wirklich dazu übergehen es so zu realisieren
Java:
public Author(Name name){...}

wenn jetzt aber auch noch z.B eine Addresse dazukommen würde wird der Konstruktor zum erstellen eines Autors ziemlich lang oder ?

Java:
new Author(new Name("Max Muster", "MM"), new Address("Musterstrasse", "18", 35585, Musterhausen);

dies wollte ich so eigentlich umgehen :)

Quasi so

Java:
public class Author {
	
	private Name name;
	
	public Author(Name name) {
		this.name = name;
	}
	
	public String getName() 				{return this.name.getName();}		
	public String getLastName()				{return this.name.getLastName();}
	public String getFullName()				{return this.name.getFullName();}
	public String getAlias()				{return this.name.getAlias();}

	
	public static void main(String[] args) {
		Author a = new Author(new Name("Peter"));
		System.out.println(a.getName());
		System.out.println(a.getLastName());
		System.out.println(a.getFullName());
		System.out.println(a.getAlias());
	}
}

Ausgabe wäre dann :

Peter
null
Peter null
null
 
Zuletzt bearbeitet:

Joose

Top Contributor
Du legst fest wie deine Klasse initialisiert werden und was dazu benötigt wird!
Folgende Konstruktoren wären möglich:

Java:
public Author(String name) {
 super(new Name(name));
 ....
}

oder/und

public Author(Name name) {
 ....
}

Ob du nun in der Klasse Name oder Author prüfst ob der Parameter null ist und eine NPE wirfst, musst auch du entscheiden.

Ich würde es logisch finden wenn ich bei beiden Klasse jeweils eine NPE geworfen wird wenn sie mit einem String null initialisiert werden sollen.

wenn jetzt aber auch noch z.B eine Addresse dazukommen würde wird der Konstruktor zum erstellen eines Autors ziemlich lang oder ?

Java:
new Author(new Name("Max Muster", "MM"), new Address("Musterstrasse", "18", 35585, Musterhausen);

Das ist auch keine schöne Programmierung so, um komplexe Objekte zu erstellen kannst du Factorys benutzen bzw. erstelle die Objekte Name und Adress und setze diese dann per setter auf ein Author Objekt.

Das du auf der Konsole "Peter null" siehst hat nur etwas mit der Ausgabe zu tun. Ein null String wird auf der Konsole so "gezeichnet". Du kannst die toString() Methode in der Klasse Name überschreiben. Dann kannst du statt Peter null folgendes Ausgeben lassen Peter [not defined].

Klar kann es dann später zu NPE kommen wenn entsprechende Attribute nicht initalisiert worden sind.
Aber du musst dich fragen: Brauche ich dieses Attribut immer und überall initialisiert? Reicht es, dort wo ich das Attribut über die getter Abfrage es entsprechend zu prüfen?
 
Zuletzt bearbeitet:

kaoZ

Top Contributor
new Author(new Name("Max Muster", "MM"), new Address("Musterstrasse", "18", 35585, Musterhausen);

genau deshalt wollte ich es vermeiden , weil es einfach nicht schön ist, wenn auch syntaktisch korrekt :)

Sicher ist :

Java:
Name name = new Name("Max Muster");
Address address = new Address("Musterstrasse"1 "18", 35569, "Musterhause");

new Author(name, address);

die schönere Lösung ;)

ich hab bereits auch schon eine Lösung gefunden , danke nochmal an dieser Stelle.
 

Joose

Top Contributor
Du musst eben festlegen => Was brauchst du um ein Objekt so weit zu initialisieren um damit arbeiten zu können?

Bezogen auf deine Klasse Name wäre folgendes für mich persönlich logisch:
Java:
public class Name {
    private String name;
    private String lastName;
    private String alias;
    
    public Name(String name) {
        if(name == null) {
            // NPE
        }
        if(name.length() ==0) {
           // IAE
        }
    }  
}

Warum?
Die Klasse Namen hat den Sinn den Vornamen, Nachnamen zu kapseln. Kennst du jemanden der keinen Namen hat bzw. dessen Namen "" ist? Ich glaube nicht. Daher darf nicht null und nicht "" übergeben werden und es sollten auch keine Standardwerte gesetzt werden.

Bezogen auf die Klasse Author wäre folgendes für mich persönlich logisch:
Java:
public class Author {
    private Name name;
   
    public Author(String name) {
        this(new Name(name));
        // oder
        this.name = new Name(name); // sollte name==null sein, wirft die Klasse Name eine NPE (im StackTrace sieht man dann eh wo genau der Fehler passiert)
    }

    public Author(Name name) {
        if(name == null) {
            // NPE
        }
        this.name = name;
    }
}

Warum?
Ein Author braucht einen Namen, ohne diesem könnte er nicht existieren. Daher kann man entweder einen String übergeben oder direkt ein Objekt des Types Name.
Wenn du einen String übergibst -> dieser wird nur weitergeleitet an den Konstrukor von Name! Daher musst du nicht extra prüfen weil in Name geprüft wird.
Wenn du ein Objekt vom Type Name übergibst -> natürlich musst du hier überprüfen ob diese Objekt == null ist.
 

turtle

Top Contributor
Die Klasse Name hat den Sinn den Vornamen, Nachnamen zu kapseln. Kennst du jemanden der keinen Namen hat bzw. dessen Namen "" ist? Ich glaube nicht. Daher darf nicht null und nicht "" übergeben werden und es sollten auch keine Standardwerte gesetzt werden.
Diesen Gedankengang von Joose finde ich sehr gut und logisch.:applaus:

Hinzufügen möchte ich, das es Sinn macht, sich das Leben mit externen Libs einfacher zu machen.
Es gibt beispielsweise die Guava-Library, in der es die Klasse Optional gibt. Damit kann einfach unterschieden werden, das ein Wert abwesend, also null, sein KANN aber nicht muss.

Im Beispiel:
Java:
	public Name(Optional<String> optional) {
		if (optional.isPresent()) tokenizeInput(optional.get());
		else throw new IllegalArgumentException("name darf nicht null sein");
	}
wenn der name abwesend, also null ist, werfen wir hier eine IllegalArgumentException (siehe Kommentar Joose ) . Sonst wird wie bisher der Vorname, Nachname extrahiert.
 

kaoZ

Top Contributor
Ich hab es nun letztendlich so gemacht :

Java:
public class Name {
	
	private String name;
	private String lastName;
	private String nickName;
	
	public Name(String name, String lastName){
		this.name		 = checkInput(name);
		this.lastName	 = checkInput(lastName);
	}
	
	public Name(String name, String lastName, String nickName){
		this.name		 = checkInput(name);
		this.lastName	 = checkInput(lastName);
		this.nickName	 = checkInput(nickName);
	}
	
	private String checkInput(String input){
		
		final String trimmedInput = input.trim();
		
		if (trimmedInput == null) {
			throw new NullPointerException("The parameters can not be null !");
		}
		if (trimmedInput.length() <= 1) {
			throw new IllegalArgumentException("The parameters lenght can not be < 1 !");
		}
		else{
			return trimmedInput;
		}
	}
	
	public String getName() 				{return this.name;}
	public String getLastName() 			{return this.lastName;}
	public String getNickName() 			{return this.nickName;}
	public String getFullName()				{return this.name + " " + this.lastName;}

}

ich hatte erst vor den String nach Vorname und Nachname zu splitten so das man den Namen in einem String eingeben kann, allerdings gibt es da einiges an Sonderfällen die extra behandelt werden müssten, z.B 2 Vor oder Nachnahmen, bindestriche usw....

das hier tuts auch :)

ggf. biete ich auch noch ein Konstruktor an der nur einen String akzeptiert, für den Fall das ein Author nur einen Künstlernamen besitzen sollte der aus einem Wort besteht.
 
Zuletzt bearbeitet:

Ähnliche Java Themen

Neue Themen


Oben