package asasaSASA; import java.io.*; class FileInputTest { public static FileInputStream f1(String fileName) { try { FileInputStream fis = new FileInputStream(fileName); System.out.println("f1: File input stream created"); return fis; // I HAVE RETURN fis } catch (FileNotFoundException e) { System.out.println("ìë¬ë"+e); } } public static void main(String args[]) { FileInputStream fis1 = null; String fileName = "foo.bar"; System.out.println("main: Starting " + FileInputTest.class.getName() + " with file name = " + fileName); fis1 = f1(fileName); System.out.println("main: " + FileInputTest.class.getName() + " ended"); } } I want to make this code run but it said This method must return a result of type FileInputStream I can't understand because I made return fis. Why does it say that you have to return? I already returned it!
3 Réponses :
Votre méthode lève une exception vérifiée qui doit être gérée soit à l'intérieur de la méthode, soit à l'extérieur. Les exceptions cochées indiquent qu'un problème peut se produire et que vous devez implémenter quelque chose pour gérer ce scénario. Ici, nous craignons que le fichier n'existe pas.
Vous avez trois choix:
main()
que inputStream n'est pas null, ou retournez Optional <> , qui est une façon JDK8 de gérer de tels scénarios.Exemple:
public static FileInputStream f1(String fileName) throws FileNotFoundException{ FileInputStream fis = new FileInputStream(fileName); System.out.println("f1: File input stream created"); return fis; }
Exemple:
public static FileInputStream f1(String fileName) { try { FileInputStream fis = new FileInputStream(fileName); System.out.println("f1: File input stream created"); return fis; } catch(FileNotFoundException e) { System.out.println("Error "+e); throw new RuntimeException(e); } }
Exemple:
public static FileInputStream f1(String fileName) { try { FileInputStream fis = new FileInputStream(fileName); System.out.println("f1: File input stream created"); return fis; } catch(FileNotFoundException e) { System.out.println("Error "+e); return null; // in case of not existing file } }
Mais si vous déclarez une exception vérifiée dans une méthode à un moment donné, vous devrez l'attraper et la gérer.
L'option 3 est la plus souhaitée.
Je ne dirais pas à un débutant d'utiliser Optional
ou quelque chose du genre - null
est une construction plus basique qui est entièrement légale pour être retournée à partir de la méthode de code de l'OP.
merci beaucoup !! ^ _ ^
les options 1 et 2 sont-elles les plus recherchées? Qu'est-ce que tu racontes. Des exceptions existent pour une raison et il est clair que «le fichier n'est pas là» est un chemin de code possible mais moins attendu. Facultatif est pour l'API de flux, pas quelque chose que vous devriez simplement jeter avec abandon (source: voir oracle lui-même qui met en garde contre une utilisation excessive), le wrapping est idiot ici; la méthode est plus ou moins appelée «ouvrir un fichier», lancer un type d'exception lié au fichier est la bonne décision. l'encapsulation est si «cela ouvre un fichier» est un détail d'implémentation.
créer une RuntimeException personnalisée est un très mauvais conseil ici
Merci d'avoir souligné. Mis à jour ma réponse.
@rzwitserloot J'évite d'utiliser Optional
chaque fois que je peux en faveur de l'utilisation des annotations de nullabilité JSR-305. Pourriez-vous s'il vous plaît fournir un lien vers le document Oracle auquel vous faites référence?
Réponse @fluffy de Brian Goetz sur cette réponse SO: stackoverflow.com/questions/26327957/... Plus précisément: je pense que l'utiliser régulièrement comme valeur de retour pour les getters serait certainement une surutilisation.
@fluffy et je m'excuse d'avoir fait une erreur logique d'Appel à l'Autorité, alors je vais aussi faire un argument juste: 1. (axiomatique) La compatibilité ascendante est bonne. 2. (évident) Optionnel <T> n'est pas rétrocompatible avec Nullable T (une méthode existante 'public V get (K key)' ne peut pas être modifiée en 'public Optional <V>'), donc 3. (conclusion logique de 1 +2) Facultatif ne peut pas remplacer les valeurs nulles dans l'écosystème java. 4. (axiomatique) Les manières mixtes de transmettre un résultat sans résultat sont mauvaises, 5. (conclusion de 3 + 4) Facultatif car un remplacement général par nul est mauvais.
Votre gestion des exceptions est le problème. C'est un style de code courant, mais mauvais: chaque fois que vous attrapez une exception, le bon geste est soit de traiter cette exception, soit de vous assurer que vous (re) lancez une exception.
Enregistrez-le ou imprimez-le? Cela ne gère pas une exception .
Dans ce cas, «fichier non trouvé» n'est pas quelque chose que vous devez gérer; pas à moins que vous développiez ce que f1
est censé faire (astuce: les méthodes devraient être un peu plus descriptives que cela). Ainsi, lancer quelque chose est un jeu juste. De plus, la définition même de f1
(vraisemblablement; ce nom n'est pas particulièrement éclairant et la méthode n'a pas de documentation) suggère que `` ouvrir ce fichier '' en est un aspect fondamental, et par conséquent, lancer une FileNotFoundException
est également juste.
Donc:
public static FileInputStream f1(String fileName) { try { FileInputStream fis = new FileInputStream(fileName); System.out.println("f1: File input stream created"); return fis; } catch (IOException e) { throw new RuntimeException("Unhandled", e); } }
NB: votre psv main peut (et devrait généralement!) Être déclaré pour throws Exception
.
Celui-ci fonctionne dans tous les scénarios où vous ne pouvez pas throws
l'exception, ou si l'ajout de la signature n'a aucun sens car il reflète un détail d'implémentation et non un aspect inhérent de ce que la méthode tente de faire:
public static FileInputStream f1(String fileName) throws IOException { FileInputStream fis = new FileInputStream(fileName); System.out.println("f1: File input stream created"); return fis; } public static void main(String[] args) throws Exception { String fileName = "foo.bar"; System.out.println("main: Starting " + FileInputTest.class.getName() + " with file name = " + fileName); try (InputStream in = f1(fileName)) { // you must close any resources you open using a try-with-resources // construct; you did not do that in your code, I fixed this. } }
Naturellement, cela n'est approprié que pour les situations où vous ne vous attendez vraiment pas à ce que cette exception se produise dans des circonstances normales. Sinon, lancez cette exception ou créez votre propre type d'exception et lancez-la au lieu de RuntimeException
.
Si vous avez juste besoin d'un ¯ \ (ム„) / ¯ Je ne sais pas vraiment ce que cela signifie, je veux juste passer à autre chose et me débarrasser de cette solution d'exceptions: throw new RuntimeException("Uncaught", e);
est correct; e.printStackTrace();
est incorrect. Mettez à jour les modèles de votre IDE.
System.out.println("ìë¬ë"+e);
Votre bloc
catch
doit retourner quelque chose ou lancer unThrowable
pour que toutes les méthodes retournent / lancent des flux capturés.