Welche Java-Tricks gibts noch?

4 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Java ist halt eine tolle Sprache :)

try-with-resources ist kein Trick, sondern eher eine Syntaxvereinfachung, die den Code schmal hält.

Beispiel

Autsch:
public ResultSet getPerson(int id) throws SQLException {
	try (PreparedStatement stmt = getConnection().prepareStatement("SELECT bla bla FROM persons WHERE id = " + id)) {
		return stmt.executeQuery();
	}
}


Besser:
public PersonData getPerson(int id) throws SQLException {
	try (PreparedStatement stmt = getConnection.prepareStatement("SELECT bla bla FROM persons WHERE id = ?")) {
		stmt.putInteger(1, id);
		try (ResultSet set = stmt.executeQuery()) {	
			if (set.next()) {
				return new PersonData(set.getString("name"), set.getInt("age"));
			}
			return null;
		}
	}
}


Das zweite mit normalem try, funktional identisch:
public PersonData getPerson(int id) throws SQLException {
	PreparedStatement stmt;
	try {
		stmt = getConnection.prepareStatement("SELECT bla bla FROM persons WHERE id = ?"
		stmt.putInteger(1, id);
		ResultSet set;
		try {	
			set = stmt.executeQuery();
			if (set.next()) {
				return new PersonData(set.getString("name"), set.getInt("age"));
			}
			return null;
		} finally {
			set.close();
		}
	} finally {
		stmt.close();
	}
}

(Was im Beispiel fehlt: getConnection() ist eine Methode, die prüft, ob die bestehende Verbindung noch gut ist und ggf. erneut öffnet, bevor sie zurückgegeben wird. Ein Pool mit einer Verbindung sozusagen. Diese ist bei Programmende natürlich zu closen. Ich bevorzuge Pooling gegenüber immer öffnen/schließen neuer Verbindungen für jeder Abfrage. Gibt Libraries, die genau diese Funktionalität bereithalten).

Ich treffe immer mal wieder auf diese Autsch-Methode von Kollegen, wo das ResultSet irgendwo außerhalb zerhackfleischt wird. Was oft (aus Unwissenheit) vergessen wird: Auch das ResultSet ist zu closen. Wenn man es nicht macht, tun es die meisten Driver beim closen der Verbindung, aus der es stammt. Da wird ein geclostes ResultSet zurückgegeben.

Wer so programmiert und SQL-Objekte über die Abfrage hinaus verwendet, hat nix von dieser Vereinfachung.

Memory-Leak pur. Beim Testen mit einer manuell gemanagten Connection funktioniert sowas ein paar Mal aber sobald Last draufkommt oder man eine PoolLibrary verwendet, entstehen mit der Zeit die abenteuerlichsten Bugs. Das try-with-resources ist hier vllt. "kontraproduktiv", weil das ResultSet ja noch benötigt wird.

Im zweiten Beispiel mit try-with-resources ist sofort zu sehen, was davon in der Lebensdauer begrent ist.

Die dritte Variante ist funktional identisch mit dem zweiten, jedoch im Verhältnis ein ziemlicher Brocken.

Ach ja, deine Frage:

Java-Features, die ich auch oft und gerne nutze:

  • Collection.stream() - spart diese klobige Schleifen, die irgendwas aus einem Array rausfischen, verarbeiten und in einem neuen Array zurückgeben
  • () -> {} - Abkürzung für Runnable und Callable
  • Interfaces - Hilfreich bei der Strukturierung und Bildung von APIs, wo nur bestimmte Methoden extern sichtbar sein sollen
  • Die Generics <T>, verhindert einiges an Casterei (wie z.B. ArrayList es macht)
  • ExecutorService - Bequemer geht es kaum, an Workerthreads zu kommen.
  • InputStream, OutputStream und ByteBuffer
Woher ich das weiß:Berufserfahrung
AldoradoXYZ  30.07.2023, 15:11

Wobei ich hoffe, dass niemand im beruflichen Umfeld noch selbst mit Connections und Statements rum macht.
Aber da ist vielleicht noch was "Cooles", nimm JPA/Hibernate für ORM.

0

Hey,

AutoCloseable ist schon nice.

Ansonsten lohnt es sich die Features der neuen Java Versionen einfach mal anzusehen.

Generics schon lange dabei (1.5), aber sehr mächtig. Records, besonders für DTOs sehr gut geeignet.
Streams werden inzwischen sehr viel benutzt, wer schreibt schon noch "normale" Schleifen bei denen der Schleifen-Index dann vermutlich falsch ist xD.

Nicht wirklich Java spezifisch, aber immer einen Blick wert sind Desing Patterns:
Singleton, Command-Pattern, Observer-Pattern, Factory-Pattern, Builder-Pattern

Und dann ganz groß natürlich Frameworks wie Spring (Spring-Boot), JPA/Hibernate für DBs, die dir einfach massiv Arbeit abnehmen und häufig eine klare Gliederung und Struktur mitbringen (Stichwort Dependency-Injection).
Man kann natürlich auch ohne Framework, wenn man zum Beispiel privat ein kleineres Projekt baut auf Dependency-Injection setzen - dafür braucht man kein großes Framework.

Für mich ist der "größte Trick" mal Clean Code gelesen zu haben. Da hat man sogar Glück, dass die Code-Beispiele mit Java geschrieben sind. Auch wenn das Buch sicher auch für viele andere Sprachen sinnvoll ist.
Dann weiß man auch etwas über Single Responsibility Principle und erleichtert sich sein Leben ungemein und vorallem auch die Testbarkeit.
Im beruflichen Umfeld habe ich sogar die Erwartung, dass Entwickler zumindest mal einen Blick in das Buch geworfen haben.

Und für Hobby-Entwickler würde ich sagen, "alles mal etwas ansehen", aber muss natürlich nichts davon sein. Privatprojekte sind ja meist eher klein und vorallem auch mit weit weniger Entwicklern entwickelt - da ist sauber  strukturiert Code und eine hohe Testbarkeit (privat: was sind Tests? xD) vielleicht auch nicht so wichtig.

Gruß und viel Spaß

Woher ich das weiß:Berufserfahrung
Ich find das total cool

Du meinst, es ist cool, dass sich der Garbage-Collector selbst darum kümmern soll, welche Ressourcen nicht mehr benötigt werden und diese dann entsorgt?

Warum denn nicht sauber programmieren und es gleich ordentlich machen?
Du weisst doch, welche Variablen wann nicht mehr gebraucht werden, Du weisst doch, wann welche Ressourcen nicht mehr benötigt werden. Dann kannst du sie auch selbst entsorgen anstatt dich darauf zu verlassen, dass dies automatisch erkannt und erledigt wird. Das gehört zu einem ordentlichen und sauberen Programmierstil und belegt dann auch zur Laufzeit weniger Speicher.....

Dein angesprochener "Trick" ist letztlich nur ein schlechter Programmierstil.

Mar3ike 
Fragesteller
 26.07.2023, 10:51

Ach die Connection unterliegt dann im Garbage-Collector? Ich dachte bei dieser Schreibweise greift das try() im shutdown auf das .close() zu und macht das selbst. Damit wäre es kein Unterschied ob man selbst .close() aufruft oder das try()

0
AldoradoXYZ  30.07.2023, 15:08
@Mar3ike

AutoCloseable ist ist Interface und wenn Du möchtest, kannst Du das natürlich auch selbst implementieren.

Das hat nichts damit zutun, dass der GarbageCollector irgendwann die Ressource "schließen" würde. Das macht der GarbageCollector auch gar nicht.

Ich kann natürlich verstehen, wenn jemand denkt "man lässt finally weg, jetzt ist das magic", aber so ist das überhaupt nicht.
Die jeweilige Ressource muss, wie gesagt, das Interface AutoCloseable implementieren und ohne geht es natürlich auch nicht. Heißt, Ressourcen die kein AutoCloseable implementieren müssen noch immer im finally geschlossen werden.
In dem Fall lohnt es sich einfach mal anzusehen wie AutoCloseable implementiert ist und dann wird schnell klar, dass das gar nichts mit magic, oder dem GarbageCollector zutun hat.
Im Grunde ist AutocloseAble auch sauberer, weil die Ressource selbst am "besten weiß" wie sie ordentlich geschlossen wird.

Gruß

1
ZaoDaDong  26.07.2023, 11:03

Am besten dann wegen nem Memory leak dann wieder mit "System.gc()"; im Code kontern.

0
Franky12345678  27.07.2023, 04:38

Du solltest nochmal nachlesen, wie try-with-resources funktioniert.

In seinem Codebeispiel leakt gar nichts.

Das, was hier tatsächlich schlechter Stil ist, ist die Empfehlung, System.gc() aufzurufen (was .close() ohnehin nicht ersetzen würde!)

1
Lamanini  27.07.2023, 16:04
Dann kannst du sie auch selbst entsorgen anstatt dich darauf zu verlassen, dass dies automatisch erkannt und erledigt wird.

Diese Einstellung, das man keinen Fehler bei der manuellen Speicherverwaltung macht, sorgt dafür, dass man nur noch mehr Fehler bei der Speicherbereinigung macht.

Das gehört zu einem ordentlichen und sauberen Programmierstil

Nein, bei Java nicht.

belegt dann auch zur Laufzeit weniger Speicher.....

Mit Memory-Leak ist es dann noch mehr.

0

Tenäre Operationen sind dir ein Begriff?

variable = bedingung ? wert1 : wert2

Statt if Abfrage mit vielen Klammern und so.

Woher ich das weiß:Studium / Ausbildung – studiere gerade Medieninformatik und Visual Computing
AldoradoXYZ  30.07.2023, 15:09

Bei ternären Operatoren muss man sehr aufpassen, dass der Code lesbar bleibt.
Beliebt ist der Fall den Du zeigst, also zur Zuweisung.
Schwierig wird es, wenn ternäre Operatoren mehrfach verschachtelt werden.

1