9
votes

Pourquoi le bloc de capture donne-t-il une erreur avec une variable non initialisée en Java

Ceci est le code que j'ai écrit.

int num;
try {
    num=100;
    DoSomething();
    System.out.println(num);
} catch(Exception e) {
    DoSomething1();
} finally{
    DoSomething2();
}
System.out.println(num); // Error Line


0 commentaires

7 Réponses :


2
votes

Les variables locales en Java ne sont pas initialisées automatiquement. Donc, vous devez l'initialiser avant de les utiliser.

int num=0;
try
{
  .. 
}
...


7 commentaires

Mais il l'initialise à num = 100; Le chemin d'exécution n'a pas non plus de ramification (no si sinon instruction). Java devrait donc savoir que num est 100 .


@ROSDI - qui est à l'intérieur du bloc d'essai.


Je connais la partie d'initialisation, je suis plus intéressé par la manière dont la suppression du bloc de capture ne conduit à aucune erreur.


Pas nécessairement. Il peut y avoir une exception désagréable avant la fin de l'affectation.


@gizgok - Le bloc de capture sera exécuté lorsqu'une exception levée / lancez-la, étant enfin bloquée toujours exécute lorsque le bloc d'essai sortira.


@Avd - Je veux dire ce qui pourrait conduire à num = 100; ne pas être exécuté? Il n'y a aucune possibilité pour num ne pas être initialisé non?


@ROSDI Il y a. Voir ma réponse. thread.stop (lancé) peut conduire à cet état.



0
votes

Le problème est que ce nombre n'est pas initialisé, int num = -1; Et l'erreur disparaîtra;)


3 commentaires

Mais la mission num = 100 est exécutée avant toute exception pouvant être lancée. Donc, le bloc de capture serait toujours exécuté après la mission.


Comme l'a dit @avd "" variables locales en Java ne sont pas initialisées automatiquement "


Oui, mais la variable sera initialisée avant d'être accessible.



11
votes

S'il y a une exception projetée dans votre ESSAYER Block, la variable num peut en effet pas avoir été initialisée. Si vous incluez le bloc CATTER , l'exécution peut continuer à la ligne d'erreur, peu importe, et donc le compilateur signale l'erreur que vous indiquez.

Si vous supprimez le bloc CATTER , l'exécution n'atteint que la "ligne d'erreur" s'il n'y a pas eu d'exception, et dans ce cas, la variable aura été initialisée dans le essayez .

(Je suppose que vous savez déjà que vous connaissez déjà la nécessité de supporter les variables locales avant de les utiliser et que vous vous êtes concentré sur le comportement que vous avez remarqué avec le bloc block ...)


5 commentaires

Oui, je suis au courant de cela, ce qui a rendu intéressant était le fait que l'élimination du bloc de capture rendait l'erreur disparue.


@gizgok David a répondu à cela lorsqu'il a déclaré: "Si vous supprimez le bloc de capture, l'exécution n'atteint que la" ligne d'erreur "s'il n'y a pas eu d'exception et, dans ce cas, la variable aura été initialisée dans l'essai." +1 btw


@ David-M "S'il y a une exception projetée dans votre bloc , alors la variable num peut en effet n'ayant pas été initialisée." Comment? L'affectation est la première instruction dans le bloc d'essai, de sorte qu'il est impossible pour num ne pas être initialisé. C'est juste le compilateur qui ne sait pas ce fait.


@Dogbane Et si l'initialisation a été faite comme ceci: num = getnumberandthrowruntimeException () ? Le compilateur, vous et moi allons tous être incertains dans ce cas!


@Dogbane utilisant thread.stop (lancé) peut conduire à un état où num est en fait non initialisé lors de l'atteinte du code après traitance - enfin dans l'exemple donné.



3
votes

La manipulation des exceptions peut confondre le compilateur. Dans ce cas, vous savez qu'une exception ne peut pas éventuellement être levée avant que la variable num est définie, mais le compilateur ne le sait pas.

Le compilateur pense qu'une exception peut être lancée avant que num a été définie dans quel cas num n'aurait pas été initialisé lorsque vous essayez de l'imprimer en dehors de l'essai bloc de capture.


1 commentaires

Vous NE PAS SAVOIR que l'affectation ne peut éventuellement pas courir. Voir l'exemple de @ Fabianbarney pour un cas.



3
votes

en Java, vous devez introduire les Vars locaux. Ceci n'est pas garanti lorsque vous avez ces blocs de capture, car une exception peut être levée avant l'init, le Var local en Essayez le bloc et vous n'irez pas le var dans le bloc de capture. Par conséquent, le Var local n'a peut-être pas été initialisé après l'essai-Catch-Enfin - enfin.

Lorsque vous retirez le bloc de capture, le VaR est initialisé après ou une exception est lancé et le code après l'essai ne sera jamais exécuté.

Vous avez suivi des possibilités pour résoudre ce problème: p>

  • init var avant tout try-block li>
  • init var dans les blocs d'essai et les blocs de capture li>
  • init var dans enfin bloquer li>
  • Init Var uniquement dans le bloc d'essai, mais ne pas attraper des exceptions li> ul>

    Le Var local n'est pas garanti d'être initialisé même lorsque Var init est la première chose que vous faites en bloc. Par exemple, le thread exécuté peut être arrêté avec thread.stop (lancé) code> après avoir entré l'essai, mais avant Var init. Lorsque cela se produit, le Var n'est pas initialisé, mais le Catch-enfin est exécuté et le code après l'essai-attraper-enfin aussi. P>

    Voici un exemple pour montrer ce que je veux dire: P>

    catch
    finally
    -1
    after all
    


1 commentaires

Exemple> Explication



2
votes

Vous avez putten num = 100 Intérieur YOUT ESSAYER Block, le compilateur suppose qu'une erreur peut avoir lieu avant num = 100 est atteint. Ainsi, lorsque vous entrez dans le Catch Bloch, pour le compilateur, il ne voit que int num qui vous donne la variable non initialisée erreur. < / p>


1 commentaires

@ROSDI pour le compilateur, toute erreur peut se produire. Plantation JVM, erreur interne générée, ...



1
votes

J'ai eu blogué à propos de cet hier http: // vanillajava.blogspot.com/2012/01/odd-case-of-initialization.html

En bref, le compilateur ne sait pas si la variable a été initialisée à l'intérieur d'un essai / attrape, même dans le cas le plus trivial. Pour cette raison, il se plaint que la variable n'aurait peut-être pas été initialisée.

Fait intéressant, si vous faites la variable finale et essayez de la définir après le bloc TRAIN / CATCH, le compilateur se plaindre aura peut-être été initialisé.


5 commentaires

, très intéressant introduisant l'aspect final de la variable. Pourquoi cela arrive-t-il? Des idées?


Vous ne pouvez pas définir une variable finale si elle a été initialisée et après un bloc d'essai / capteur, il peut être initialisé ou non. Le compilateur n'a aucune idée.


Il y a le mal avec thread.stop (jetable) qui peut conduire à un état où le Var local n'est en fait pas initialisé dans l'exemple donné.


En théorie oui. Toutefois, une fois que le code est optimisé au code natif, je pense qu'il doit atteindre un point de sécurité pour déclencher une telle exception. Imho thread.stop () n'est que "Safe" lorsqu'il est utilisé sur le fil actuel.


Je suis avec toi ici. Je voulais juste montrer que ce n'est pas aussi trivial qu'il ressemble. Et il y a des branches d'exécution pourraient conduire à un état où le compilateur est juste à propos de «peut ne pas avoir été initialisé».