Konstruktor abbrechen

Hallo Leute

Wie kann ich hier in Konstruktor Abbrechbedienung einbauen. Ich meine wenn ich falsche angaben eingebe, wie kann ich beeinflüssen dass ausgabe() - Methode nichtmehr ausgeführt wird und Programm vorher beendet wird

Vielleicht ist blödeste Frage überhaupt, aber wenn ich statt int Wert Buchstabe eingebe bekomme ich folgende Fehlermeldung und wenn ich Statt String ein Ziffer eingebe ist für Programm kein Problem. Kann man nicht in Konstruktor so behandeln dass ich diese Meldung nichtmehr bekomme? oder wo kann man behandeln?

Exception in thread "main" java.util.InputMismatchException
	at java.util.Scanner.throwFor(Scanner.java:840)
	at java.util.Scanner.next(Scanner.java:1461)
	at java.util.Scanner.nextInt(Scanner.java:2091)
	at java.util.Scanner.nextInt(Scanner.java:2050)
	at artikel.Karte.main(Karte.java:86)

import java.util.*;
import java.text.*;

class KarteAngabe {

	String abfahrtsort;
	String ankunftsort;
	int zonen;
	char hin;
	int person;

	KarteAngabe(String abfahrtsort, String ankunftsort, int zonen, char hin,
			int person) {
		if (abfahrtsort.length() == 0 || ankunftsort.length() == 0 || zonen < 1
				|| person < 1) {
			System.out.println("Falsche Angabe");

		}
		this.abfahrtsort = abfahrtsort;
		this.ankunftsort = ankunftsort;
		this.hin = hin;
		this.person = person;
		this.zonen = zonen;
	}

	{

	}

	double preis() {
		double preis = 0;
		if (hin == 'j') {
			preis = zonen * 2.1 * person;

		} else {
			preis = (zonen * 2.1) * 0.8 * person;

		}
		return preis;

	}

	String datum() {
		GregorianCalendar cal = new GregorianCalendar();

		DateFormat df;

		df = DateFormat.getDateInstance();

		DateFormat tf = DateFormat.getTimeInstance();

		return df.format(cal.getTime()) + " / " + tf.format(cal.getTime());

	}

	void ausgabe() {
		System.out.println("Datum:" + datum());
		System.out.println("Abfahrtsort:" + abfahrtsort);
		System.out.println("Ankunfsort:" + ankunftsort);
		System.out.println("Zonen:" + zonen);
		System.out.println(" hin == 'j'?");
		System.out.println("Personen:" + person);
		System.out.println("Preis:" + preis() + "Euro");
	}

}

public class Karte {

	public static void main(String[] args) {

		Scanner sc = new Scanner(System.in);

		System.out.println("Geben Sie die Zone ein");
		int zone = sc.nextInt();

		System.out.println("Geben sie die Abfahrtsort ein");
		String abfahrt = sc.next();

		System.out.println("Geben sie den Ankunftsort ein");
		String ankunft = sc.next();

		System.out.println("Geben sie den Personenanzahl ein");
		int person = sc.nextInt();

		char hin = 'j';

		KarteAngabe k = new KarteAngabe(abfahrt, ankunft, zone, hin, person);
		k.ausgabe();

	}
}

danke euch allen Anni

Dafür sind Exceptions gedacht. Einfach anstelle der Ausgabe eine [JAPI]IllegalArgumentException[/JAPI] werfen und gut…

bye
TT

Die Schlüsselwörter die dir dabei helfen sollten sind exception handling java sowie try catch. Mit diesen Schlüsselwörtern solltest du zu einer Lösung kommen.

Hier wird es eigentlich ganz gut erklärt Java ist auch eine Insel (da wird quasi dein Problem auch angesprochen)

PS.
[ul]
[li]Die exception die du dann im catch block fangen willst ist InputMismatchException.
[/li][li]Ein Programm beenden geht mit System.exit(0).
[/li][/ul]

Das Thema wird auch auf http://www.javaspecialists.eu/archive/Issue120.html ganz gut zusammengefasst.

Um das Programm zu beenden KANN man in diesem Fall (Erste Schritte, Konsolenprogramm) zwar System.exit(1) verwenden (0 würde bedeuten, dass KEIN Fehler aufgetreten ist). Aber im allgemeinen sollte man das NICHT. Das ist wie wenn man das Licht ausschaltet indem man die Glühbirne zu staub zerstampft :smiley: Das Programm sollte i.a. auch im Fehlerfall auf einigermaßen geregelten Bahnen zum Ende der main-Methode geleitet werden.

Ich würde bei so einem Einlesen und einer Falscheingabe das Programm auch nicht beenden, sondern den Benutzer dann auffordern die Eingabe zu wiederholen mit eventuell einer Angabe, das man nur Zahlen eingeben darf.

So nach der Art

Eingabe A?
test
Eingabe war inkorrekt (bitte eine Zahl eingeben)
Eingabe A?
123
Eingabe B?

Die Anmerkung mit dem System.exit war nur gewesen da die Frage nach wie kann man ein Programm beenden gestellt wurde

Exception ist die letzte Verteildigungslinie für den Konstruktor, der keine Annahmen zu seiner Verwendung treffen kann,
aber im Ablauf lieber vermeiden, sollte kein Normalfall zurück zur Benutzereingabe sein

prüfen, bevor überhaupt ein Objekt erstellt wird!

allgemein ein gewisses Dilemma doppelten Codes, doppelter Prüfung,
aber == 0 und < 1 (gerade für char) usw. ist ja keine Hexenkunst,
das kann man auch auf vorhergehenden Ebenen klären


gerade jetzt erst die main-Methode gesehen, da gibt es freilich nicht viel an Ebenen :wink:

datum() wird übrigens immer ein neues aktuelles Datum liefern,
unterschiedliche Ausgabe je nach vergangener Zeit,
lieber ein festes Datum im Konstruktor ablegen?

Exception ist die letzte Verteildigungslinie für den Konstruktor

Wie ist das bei Java denn genau ?

Ich kenns von C++
Execptions in C++ im CTor sind „verpönt“.
Theoretisch wird der Speicher den ein Constructor allokiert, wieder freigegeben, wenn er ne Exception wirft. aber nur theoretisch.
Praktisch haben compiler in bestimmten konstellationen teilweisse schon schwierigkeiten.
Deshalb sollt nen CTor nur crashen, wenn wirklich was boese im argen ist.
Und abfangen sollt man nur noch, um im log sein Kommentar zu schreiben und dem User zum Abschied zuzuwinken … falls noch möglich :slight_smile:

Also lieber den CTor durchlaufen lassen und den Status der Instanz auf „invalid/unbenutzbar“ setzen.

Gibts da in Java „rules of design“ zu ?

Ciao …

Also bezueglich speicher braucht man sich bei Java keine Gedanken machen.

Da ist eine Exception im Konstruktor sehr viel besser, als eine Invalid-flag das man nach jeder erzeugung wieder abfragen muss.

Wenn du Java programmierst (Und gerade wenn du aus der C-Richtung kommst): Verabschiede dich von allen “Speichergedanken”.

Zudem ist Java eine objektorientierte Sprache. Mit dem Konstruktor erzeugst du ein Objekt. Nach dem Konstruktor-Aufruf sollte das Objekt gültig und einsatzbreit sein. Um dein Problem in Java elegant zu lösen, solltest du einfach eine Exception schmeißen. Java regelt den Rest und du musst dich nur darum kümmern, wo du die Exception fängst und was du dann damit machst.

Im Idealfall prüfst du die Parameter (gerade wenn sie vom Nutzer kommen) aber VORHER auf Richtigkeit. Würde fast soweit gehen und behaupten, es ist Aufgabe der GUI (in deinem Fall die Konsole), der Logic die richtigen Daten zur Verfügung zu stellen. Es einfach durchlaufen zu lassen, nur um zu sehen ob es dann kracht ist meist kein schöner Ansatz. Zumal programmiert es sich viel besser, wenn man (möglichst früh) einen Punkt hat, ab dem man weiß: Ab hier sind alle Daten richtig.

Das ist ein zweischneidiges Schwert. Dadurch kann es passieren, dass die GUI Logik bekommt, die dort nicht hin gehört. Es könnte auch passieren, dass die Logik dupliziert wird und dann irgendwann auseinanderdriftet.
Wenn man das machen möchte, muss man eine zentrale Validierungsschnittstelle definieren.

Das ist in der Tat zweischneidig, denn auch ein Konstruktor sollte nicht viel Logik enthalten. Aber … selbst wenn “man” die Konstruktorparameter vorher prüft, sollte man sich fragen, ob das ausreicht - oder ob der Konstruktor nicht trotzdem (tja: die gleichen) Prüfungen machen sollte, weil er ja nicht wissen kann, von wem er aufgerufen wurde. (Das ganze müßte man noch feiner aufdröseln … ich halte nicht so viel von ‘public’ Konstruktoren … nicht mal von ‘public’ Klassen… aber das würde jetzt wohl zu weit führen).

Ich handhabe es so, dass ich in meinen public Konstruktoren alle Vorbedingungen nochmal prüfe. Ich nutze für die meisten Fälle die Guava Klasse Preconditions, damit lassen sich die Checks jeweils in Einzeilern formulieren.

In Konstruktoren niedrigerer Sichtbarkeit lasse ich die Prüfungen weg.

Also ich persönlich hasse es wenn Konstruktoren Exceptions werfen. Anstatt zum Beispiel dem leidigen

    URL myURL = new URL(...);
} 
catch (MalformedURLException e) {
    // exception handler code here
    // ...
}```

würe ich viel lieber folgendes schreiben:

URL myURL = new URL(…);
if(myURL.isValid())
{
doStuffWith(myURL);
}
else
{
handleErrorOf(myURL);
}

Der Konstruktor sollte ja auch eine unchecked Exception werfen. Wenn jemand versucht das Objekt unter falschen Rahmenbedingungen zu erzeugen, dann liegt etwas im Argen. Das lässt sich dann normalerweise nicht recovern und der Programmablauf bricht ab.

Das wäre im Fall vom TO (falsche Benutzereingabe) aber nicht so. Da würde ich lieber eine extra Validierungsmethode oder gleich einen Validator einsetzen.

Und dennoch stimme ich cmdrudolph zu, dass die geworfene Exception unchecked sein sollte. Checked Exceptions sind ein reines Übel, weil sie immer im aufrufenden Code behandelt werden müssen. Es widerspricht auch der Bean Konvention, in Konstruktoren checked Exceptions zu werfen.

Und als Referenz für mein Plädoyer für unchecked Exceptions: Bspw. die ConstraintValidationException des Java Bean Validation API (aus meiner Sicht ein geeigenter Kandidat für einen Validator) ist aus gutem Grunde unchecked.

Nochmals, Exceptions bei ungültigen Benutzereingaben zu werfen widerspricht dem Prinzip, Exceptions nicht zur Steuerung des Programmflusses zu verwenden sondern Ausnahmen zu behandeln, die in einem normalen Programmdurchlauf nicht auftreten. Dass sich der Benutzer mal vertippt ist mMn keine sehr seltene Ausnahme.

Für mich ist der Versuch, ein ungültiges Objekt zu erzeugen, definitiv eine Ausnahme. Meines Erachtens sollte ein Objekt nach dem Konstruktoraufruf in einem gültigen Zustand sein. Ausnahmen sind für mich nur, wenn die Objekte durch Frameworks (z.B. OR-Mapping) erstellt werden. Dann darf das Objekt auch mal direkt nach dem Konstruktoraufruf kurzzeitig ungültig sein. Es wird aber bevor ich es in meinem Programmablauf sehe gültig, weil die Felder gesetzt werden.

Und nochmals, deinem Objekt ist es egal, ob sein Input von einer Benutzereingabe oder aus einen Netzwerkstream kommt. Im Konstruktor wird validiert ob der Input gültig ist, dass die erstellte Instanz nicht defekt ist. Daher auch unchecked Exceptions, da dies IMHO eine nicht wiederherstellbarer Fehler ist. Der Verwender des Objekts hat natürlich dafür zu sorgen, die Benutzereingaben zu validieren, bevor er eine Instanz erstellen will. Unchecked Exceptions sind keine Steuerung des Programmflusses.

kommt auch immer auf die Möglichkeiten an,
ob eine URL valide ist kann man außerhalb der URL-Klasse kaum prüfen,
da wäre aufwendig zu arbeiten, wahrscheinlich nichtmal vollständig korrekt,
letztlich wohl eine statische Methode der URL-Klasse nötig oder ein Prüf-Objekt

bei URL insofern Zulassen des Konstruktors + isValid()-Methode eher vertretbar als in anderen Fällen,

ob ein Parameter null oder leer oder 0 ist, kann der Aufrufer schon eher vorher abfragen,
da darf es eine komplette Ablehung sein (Exception),
aber Gratwanderung ohne komplettes richtig und falsch