Java >> Tutoriel Java >  >> Java

Fonctionnalité d'essai avec des ressources en Java

La prise en charge de try-with-resources, ajoutée dans Java 7, nous permet de déclarer des ressources à utiliser dans un bloc try tout en sachant qu'elles seraient fermées lors de leur exécution. L'instruction try-with-resources en Java est une instruction try avec une ou plusieurs ressources déclarées. La ressource est un objet qui doit être fermé une fois le programme terminé. L'instruction try-with-resources garantit que chaque ressource est fermée à la fin de l'exécution de l'instruction.

Les ressources définies doivent implémenter l'interface AutoCloseable.

Tout objet qui implémente java.lang peut être passé. De plus, tous les objets qui implémentent java.io.Closeable sont pris en compte.

Utilisation de la méthode d'essai avec ressources

En termes simples, une ressource doit être déclarée et initialisée dans la tentative de fermeture automatique :

try (PrintWriter writer = new PrintWriter(new File("test.txt"))) {
    writer.println("Welcome to Codeunderscored");
}

Remplacement de try-catch-finally par try-with-resources

Try-with-resources est une technique qui vous permet d'expérimenter différentes ressources. La nouvelle fonctionnalité try-with-resources remplace l'ancien et verbeux bloc try-catch-finally dans une approche transparente et simple.

Examinons quelques exemples de code.

Le premier est un modèle éprouvé d'essayer-attraper-enfin :

Scanner scan = null;
try {
    scan = new Scanner(new File("code.txt"));
    while (scan .hasNext()) {
        System.out.println(scan .nextLine());
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
} finally {
    if ( scan != null) {
        scan.close();
    }
}

Voici une nouvelle solution très courte basée sur l'essai avec des ressources :

try (Scanner scan = new Scanner(new File("code.txt"))) {
    while (scan .hasNext()) {
        System.out.println(scan .nextLine());
    }
} catch (FileNotFoundException fnfe) {
    fnfe.printStackTrace();
}

essayez avec des ressources avec une variété de ressources

Nous pouvons déclarer plusieurs ressources dans un bloc try-with-resources en utilisant un point-virgule pour les séparer :

try (Scanner scan = new Scanner(new File("readCode.txt"));
    PrintWriter pWriter = new PrintWriter(new File("writeCode.txt"))) {
    while (scan scan ner.hasNext()) {
	pWriter.print(scan .nextLine());
    }
}

Une ressource personnalisée à fermeture automatique

La classe doit implémenter les interfaces Closeable ou AutoCloseable et remplacer la fonction close pour créer une ressource personnalisée qui sera gérée correctement par un bloc try-with-resources :

public class CodeResource implements AutoCloseable {
    @Override
    public void close() throws Exception {
        System.out.println("Code Resource Closed");
    }
}

Fermeture de commande de ressources

Les premières ressources définies/acquises seront fermées en dernier. Prenons l'exemple suivant de ce type de comportement :

1ère ressource :

la classe publique CodeAutoCloseableResourcesInitial implémente AutoCloseable {

public class CodeAutoCloseableResourcesInitial implements AutoCloseable {

    public CodeAutoCloseableResourcesInitial() {
        System.out.println("Constructor -> AutoCloseableResources_Initial");
    }

    public void exploreCode() {
        System.out.println("Something -> AutoCloseableResources_Initial");
    }

    @Override
    public void close() throws Exception {
        System.out.println("Closed AutoCloseableResources_Initial");
    }
}

2ème ressource

public class CodeAutoCloseableResourcesLast implements AutoCloseable {

    public CodeAutoCloseableResourcesLast() {
        System.out.println("Constructor -> AutoCloseableResources_Last");
    }

    public void exploreCode() {
        System.out.println("Explore -> AutoCloseableResources_Last");
    }

    @Override
    public void close() throws Exception {
        System.out.println("Closed AutoCloseableResources_Last");
    }
}

private void CodeOrderOfClosingResources() throws Exception {
    try (CodeAutoCloseableResourcesFirst firstCode = new CodeAutoCloseableResourcesFirst();
        CodeAutoCloseableResourcesSecond lastCode = new CodeAutoCloseableResourcesLast()) {

        firstCode.exploreCode();
        lastCode.exploreCode();
    }
}

Attraper et enfin

Les blocs catch et finally sont toujours utilisés dans un bloc try-with-resources, et ils fonctionneront de la même manière que dans un bloc try standard.

Variables effectivement finales dans Java 9

Nous ne pouvions utiliser de nouvelles variables qu'à l'intérieur d'un bloc try-with-resources avant Java 9 :

try (Scanner scan = new Scanner(new File("readCode.txt"));
    PrintWriter pWriter = new PrintWriter(new File("writeCode.txt"))) {
    // omitted
}

Il était particulièrement verbeux lors de la définition de nombreuses ressources, comme démontré ci-dessus. Nous pouvons désormais utiliser des variables finales ou essentiellement finales dans un bloc try-with-resources à partir de Java 9 et dans le cadre de JEP 213 :

final Scanner scan = new Scanner(new File("readCode.txt"));
PrintWriter pWriter = new PrintWriter(new File("writeCode.txt"))
try (scan;pWriter) {
    // omitted
}

Même si une variable n'est pas explicitement marquée comme finale, elle est essentiellement finale si elle ne change pas après la première affectation.

La variable scan est explicitement déclarée final, comme indiqué ci-dessus, pour l'utiliser avec le bloc try-with-resources. La variable writer ne change pas après la première affectation, même si elle n'est pas explicitement finale. Par conséquent, nous pouvons également utiliser la variable pWriter. Par conséquent, nous n'avons plus besoin d'inclure un bloc finally supplémentaire pour simplement transmettre les déclarations de fermeture des ressources. Les ressources seront fermées dès que le bloc try-catch sera exécuté.

Syntaxe d'essai avec ressources :

try(declare resources here) {
    // use resources
}
catch(FileNotFoundException e) {
    // exception handling
}

ou

try (resource declaration) {
  // use of the resource
} catch (ExceptionType e1) {
  // catch block
}

Comme le montre la syntaxe ci-dessus, l'instruction try-with-resources est déclarée, dans la clause try, en déclarant et en instanciant la ressource. Toutes les exceptions pouvant être levées lors de la fermeture de la ressource sont spécifiées et gérées. Il convient de noter que l'instruction try-with-resources ferme toutes les ressources qui implémentent l'interface AutoCloseable.

Exceptions

Il existe une distinction entre les blocs try-catch-finally et try-with-resources pour les exceptions. La méthode renvoie l'exception levée dans le bloc finally si une exception est levée à la fois dans les blocs try et finally.

Si une exception est levée à la fois dans un bloc try et dans une instruction try-with-resources dans try-with-resources, la méthode renvoie l'exception levée dans le bloc try. Les exceptions try-with-resources sont supprimées. Ainsi, nous pouvons dire que le bloc try-with-resources lève des exceptions supprimées.

Examinons maintenant les deux circonstances alternatives, dont l'une est illustrée ci-dessous à titre d'exemple :

  • Cas 1 :Une seule source d'informations
  • Cas 2 :Une variété de ressources

L'exemple ci-dessous enregistre une chaîne dans un fichier. Il écrit des données dans le fichier à l'aide d'un objet FileOutputStream. La ressource FileOutputStream doit être fermée une fois que le programme a fini de l'utiliser. Par conséquent, dans cet exemple, la fermeture de la ressource est tentée par elle-même.

import java.io.FileOutputStream;   

 
public class CodeTryWithResources {
    
public static void main(String args[]){      
 
// Using try-with-resources  
try(FileOutputStream fileOutputStream =newFileOutputStream("/java7-new-features/src/abc.txt")){      
String msgString = "Welcome to Codeunderscored!";      
byte byteArray[] = msgString.getBytes(); //converting string into byte array      
fileOutputStream.write(byteArray);  
System.out.println("Message is successfuly written to file!");   
   
}catch(Exception exception){  
       System.out.println(exception);  
}      
}      
}  

Exemple d'essai avec ressources :utilisation de plusieurs ressources

  import java.io.DataInputStream;  
    import java.io.FileInputStream;  
    import java.io.FileOutputStream;  
    import java.io.InputStream;    

    public class CodeTryWithResources {    
    public static void main(String args[]){      
    
// Using try-with-resources  
    try(    // Using multiple resources  
            FileOutputStream fileOutputStream =new FileOutputStream("/java7-new-features/src/abc.txt");  
            InputStream input = new FileInputStream("/java7-new-features/src/abc.txt")){  

            // -----------------------------Code to write data into file--------------------------------------------//  
            String msgString = "Welcome to Codeunderscored!";      
            byte byteArray[] = msgString.getBytes();  // Converting string into byte array      
            fileOutputStream.write(byteArray);  // Writing  data into file  
            System.out.println("------------ Writing data to file--------------");  
            System.out.println(msgString);  


            // -----------------------------Code for reading data from file---------------------------------------//  
           
	// Creating input stream instance  
            DataInputStream inputStream = new DataInputStream(input);    
            int data = input.available();    
            // Returns an estimate of the number of bytes that can be read from this input stream.   
            byte[] bArray = new byte[data]; //    
            inputStream.read(bArray);    
            String str = new String(bArray); // passing byte array into String constructor
 
            System.out.println("------------Data after reading from the file--------------");  
            System.out.println(str); // display file data

    }catch(Exception exception){  
           System.out.println(exception);  
    }     
    }      
    }   

Avec une instruction try-with-resources, vous pouvez utiliser les blocs catch et finally de la même manière avec une instruction try normale. Attraper, ou enfin, bloquer les exécutions après la fermeture des ressources indiquées dans une instruction try-with-resources.

Exemple d'essai avec des ressources :utilisation du bloc finally

 import java.io.FileOutputStream;    


    public class CodeTryWithResources {    

    public static void main(String args[]){      
    try(    FileOutputStream outputStream=  
      new FileOutputStream("/home/tuts/code/java7-new-features/src/abc.txt")){  

        // -----------------------------Code for writing data into file--------------------------------------------//  

            String msgString = "Welcome to Codeunderscored!";      
            byte bArray[] = msgString.getBytes();  // Conversion of a string into byte array      
            outputStream.write(bArray);  // process of writing  data into file  
            System.out.println("Data writing completed successfully!");  

    }catch(Exception exception){  
           System.out.println(exception);  
    }  
    finally{  
           System.out.println(" Executes finally after closure of declared resources.");  
    }  
    }      
    }  

Exemple :essayer avec des ressources

import java.io.*;

class Codeunderscored {
  public static void main(String[] args) {
    String line_text;
    try(BufferedReader bReader = new BufferedReader(new FileReader("code.txt"))) {
      while (( line_text = bReader.readLine()) != null) {
        System.out.println("Line =>"+line_text);
      }
    } catch (IOException e) {
      System.out.println("IOException in try block =>" + e.getMessage());
    }
  }
}

Nous utilisons une instance BufferedReader pour lire les données du fichier code.txt dans cet exemple. L'utilisation de l'instruction try-with-resources pour déclarer et instancier le BufferedReader garantit que son instance est fermée, que l'instruction try réussisse ou échoue. Si une exception se produit, les blocs de gestion des exceptions ou le mot-clé throws sont utilisés pour la gérer.

Exceptions qui ont été supprimées

Des exceptions peuvent être levées à partir de l'instruction try-with-resources dans l'exemple ci-dessus lorsque :

  • Le fichier test.txt est introuvable.
  • L'objet BufferedReader est en cours de fermeture.

Étant donné qu'une lecture de fichier peut échouer à tout moment pour diverses raisons, une exception peut être levée à partir du bloc try. Si le bloc try et l'instruction try-with-resources lèvent des exceptions, l'exception du bloc try est levée et l'exception de l'instruction try-with-resources est masquée.

Si un bloc try lève une exception et try-with-resources lève une ou plusieurs exceptions, les exceptions try-with-resources sont réduites au silence. Les exceptions levées par try-with-resources sont des exceptions supprimées, pour le dire autrement.

Récupérer les exceptions qui ont été supprimées

Les exceptions supprimées peuvent être obtenues dans Java 7 et versions ultérieures en appelant la méthode Throwable.getSuppressed(). L'exception du bloc try est transmise au processus.

Cette méthode renvoie un tableau de toutes les exceptions qui ont été supprimées. Dans le bloc catch, on obtient les exceptions supprimées.

catch(IOException e) {
  System.out.println("The Exception Thrown=>" + e.getMessage());
  Throwable[] sExceptions = e.getSuppressed();
  for (int i=0; i<sExceptions.length; i++) {
    System.out.println("Exceptions Suppressed=>" + sExceptions[i]);
  }
}

La fonction getSuppress() de la classe Throwable est utilisée pour obtenir ces exceptions. Java a fourni un nouveau constructeur et deux nouvelles méthodes à la classe Throwable pour gérer les exceptions supprimées.

Constructeur

protected Throwable(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace)

Il crée un nouveau jetable avec le message détaillé fourni, la cause, la suppression, qu'elle soit activée ou désactivée, et une trace de pile inscriptible qui peut être activée ou désactivée.

Méthode

public final void addSuppressed(Throwable exception)/td&gt;

Pour transmettre cette exception, il ajoute l'exception fournie aux exceptions supprimées. L'instruction try-with-resources appelle généralement cette procédure thread-safe (automatiquement et implicitement). Les exceptions suivantes sont levées :
IllegalArgumentException :une exception jetable ne peut pas se supprimer si l'exception est jetable. Si l'exception est nulle, une NullPointerException est levée.

public final Throwable[] getSuppressed()

Il produit un tableau avec toutes les exceptions que la commande try-with-resources a supprimées. Un tableau vide est renvoyé si aucune exception n'est supprimée ou si la suppression est désactivée.

Exemple :programme pour try-with-resources ayant une seule ressource

// Importing all input output classes
import java.io.*;

// Class
class Codeunderscored {

	// Main driver method
	public static void main(String[] args)
	{
		// Try block to check for exceptions
		try (

			// Creating an object of FileOutputStream
			// to write stream or raw data

			// Adding resource
			FileOutputStream fos
			= new FileOutputStream("gfgtextfile.txt")) {

			// Custom string input
			String text
				= "Hello World. This is my java program";

			// Converting string to bytes
			byte arr[] = text.getBytes();

			// Text written in the file
			fos.write(arr);
		}

		// Catch block to handle exceptions
		catch (Exception e) {

			// Display message for the occured exception
			System.out.println(e);
		}

		// Display message for successful execution of
		// program
		System.out.println("Resource are closed and message has been written into the code.txt");
	}
}

La ressource est fermée et un message a été écrit dans le code.txt

Exemple :programme pour essayer avec des ressources ayant plusieurs ressources

// Importing all input output classes
import java.io.*;

// Class
class Codeunderscored {

	// Main driver method
	public static void main(String[] args)
	{
		// Try block to check for exceptions

		// Writing data to a file using FileOutputStream
		// by passing input file as a parameter
		try (FileOutputStream outputStream
			= new FileOutputStream("outputfile.txt");

			// Adding resouce

			// Reading the stream of character from
			BufferedReader br = new BufferedReader(
				new FileReader("code.txt"))) {

			// Declaring a string holding the
			// stream content of the file
			String text;

			// Condition check using readLine() method
			// which holds true till there is content
			// in the input file
			while ((text = br.readLine()) != null) {

				// Reading from input file passed above
				// using getBytes() method
				byte arr[] = text.getBytes();

				// String converted to bytes
				outputStream.write(arr);

				// Copying the content of passed input file
				// 'inputgfgtext' file to code.txt
			}

			// Display message when
			// file is successfully copied
			System.out.println(
				"File content copied to another one.");
		}

		// Catch block to handle generic exceptions
		catch (Exception e) {

			// Display the exception on the
			// console window
			System.out.println(e);
		}

		// Display message for successful execution of the
		// program
		System.out.println("Resource are closed and message has been written into the code.txt");
	}
}

Le contenu d'un fichier est copié dans un autre. De plus, la ressource a été fermée et le message a été enregistré dans le fichier code.txt.

Amélioration de la méthode try-with-resources de Java 9

L'instruction try-with-resources a une limitation dans Java 7. Dans son bloc, vous devez déclarer la ressource localement.

try (Scanner scan= new Scanner(new File("readCode.txt"))) {
  // code
}

En Java 7, déclarer la ressource en dehors du bloc aurait entraîné une notification d'erreur.

Scanner scan = new Scanner(new File("readCode.txt"));
try (scan) {
  // code
}

Java 9 a mis à jour l'instruction try-with-resources pour résoudre ce problème afin de permettre l'utilisation de la référence de la ressource même si la ressource n'est pas spécifiée localement. Sans aucune erreur de compilation, le code ci-dessus va maintenant s'exécuter.

Conclusion

Dans cet article, nous avons examiné comment utiliser try-with-resources et comment remplacer try, catch et enfin par try-with-resources. Nous avons également examiné l'utilisation d'AutoCloseable pour créer des ressources personnalisées et l'ordre dans lequel elles sont fermées.

L'instruction Try-with-resources en Java est une instruction try avec une ou plusieurs ressources déclarées. Une fois que votre programme a fini de l'utiliser, vous devez fermer la ressource. Une ressource File, par exemple, ou une ressource de connexion Socket. L'instruction try-with-resources garantit que chaque ressource est fermée à la fin de l'exécution de l'instruction. Si nous ne fermons pas les ressources, cela pourrait entraîner une fuite de ressources et le programme pourrait épuiser ses ressources.

Tout objet qui implémente java.lang peut être envoyé en tant que ressource. De plus, tous les objets qui implémentent java.io.Closeable sont considérés comme AutoCloseable.


Balise Java