Kleines einfaches Beispiel zur Verwendung des try-with Resource Idioms aus Java 7

Thomas Darimont

Erfahrenes Mitglied
Hallo,

schaut mal hier:
Java:
package de.tutorials.training;

import java.util.concurrent.ThreadLocalRandom;

public class TryWithResourceExample {

	public static void main(String[] args) {
		
		/*
		 * so nicht:
		 * Wenn hier bei der Erzeugung einer Resource ein Fehler passiert und eine
		 * Exception geworfen wird, so ist nicht garantiert, dass der try-with Resource
		 * Mechanismus die close() Methode der bis dahin im try-with-Block erzeugten Objekte aufruft.
		 */
		try (Resource outer = new Resource("outer", new Resource("middle", new Resource("inner")))) {
			System.out.println(outer);
		} catch (Exception ex) {
			System.out.println(ex.getMessage());
		}

		System.out.println("####");
		
		/*
		 * besser so:
		 * Bei dieser Formulierung ist sichergestellt, dass der try-with Resource
		 * Mechanismus die bis dahin erstellten im try-with-Block erzeugtenObjekte
		 * aufruft.  
		 */
		
		try (Resource outer  = new Resource("outer");
			 Resource middle = new Resource("middle", outer);
			 Resource inner  = new Resource("inner" , middle)) {
			System.out.println(inner);
		} catch (Exception ex) {
			System.out.println(ex.getMessage());
		}
	}

	static class Resource implements AutoCloseable {

		private String id;
		
		private Resource nested;
		
		private volatile boolean closed;

		public Resource(String id) {
			this.id = id;
			//mit einer Wahrscheinlichkeit von 15 % Fehler simulieren
			if (ThreadLocalRandom.current().nextDouble() < 0.15) {
				throw new RuntimeException("Could not create: " + id);
			}
		}

		public Resource(String name, Resource nested) {
			this(name);
			this.nested = nested;
		}

		@Override
		public void close() throws Exception {
			
			/*
			 * Die close() Methode von "inneren" (nested) Resourcen aufzurufen ist
			 * in der Regel eine gute Idee - dies führt jedoch bei der Verwendung mit
			 * dem try-with Resource Mechanismus u.U. zu multiplen Aufrufen der close-Methode.
			 * 
			 * Je nach Logik in close() kann das dann auch zu Problemen führen -> hier kann es sich
			 * anbieten ein closed-Flag einzuführen um dann in solchen Fällen nach einem check des Flags
			 * direkt wieder aus der Methode zurückzukehren.    
			 * 
			 */
			
			if(this.closed){
				return;
			}
			
			if(this.nested != null){
				this.nested.close();
				//eine Thread-sichere Implementierung zu diesem Idiom findet man übrigens bei:
				//java.io.BufferedInputStream.close()
			}
			
			System.out.println("Close " + this.id);
			
			this.closed = true;
		}
	}

}

Beispielausgabe:
Code:
Could not create: inner
####
Close outer
Close middle
Could not create: inner

Gruß Tom
 
Zurück