43 votes

1/0 est-il une expression légale de Java?

Le suivant compile très bien dans mon Eclipse:

final int j = 1/0;
// compiles fine!!!
// throws ArithmeticException: / by zero at run-time

Java empêche beaucoup de "dumb code" même à partir de la compilation en premier lieu (par exemple, "Five" instanceof Number ne compile pas!), donc, le fait n'en est pas de même de générer autant qu'un avertissement a été très surprenant pour moi. L'intrigue s'intensifie lorsque vous considérez le fait que des expressions constantes sont autorisés à être optimisé au moment de la compilation:

public class Div0 {
    public static void main(String[] args) {
        final int i = 2+3;
        final int j = 1/0;
        final int k = 9/2;
    }
}

Compilé dans Eclipse, l'extrait ci-dessus génère les éléments suivants du code binaire (javap -c Div0)

Compiled from "Div0.java"
public class Div0 extends java.lang.Object{
public Div0();
  Code:
   0:   aload_0
   1:   invokespecial   #8; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   iconst_5
   1:   istore_1      // "i = 5;"
   2:   iconst_1
   3:   iconst_0
   4:   idiv
   5:   istore_2      // "j = 1/0;"
   6:   iconst_4
   7:   istore_3      // "k = 4;"
   8:   return

}

Comme vous pouvez le voir, l' i et k affectations sont optimisés comme des constantes de compilation, mais la division en 0 (qui doit avoir été détectable au moment de la compilation) est tout simplement compilés à l'est.

javac 1.6.0_17 se comporte encore plus étrangement, la compilation en mode silencieux mais d'exciser les affectations à l' i et k complètement hors du bytecode (probablement parce qu'il a déterminé qu'ils ne sont pas utilisés n'importe où) mais en laissant de l' 1/0 intact (depuis la suppression il serait la cause d'un programme totalement différent de la sémantique).

Donc les questions sont:

  • Est - 1/0 la loi l'expression de Java qui devrait compiler n'importe quand n'importe où?
    • Ce n'JLS dire à ce sujet?
  • Si c'est légal, est-il une bonne raison pour cela?
    • À quoi bon, cela pourrait-il servir?

34voto

Stephen C Points 255558

Est - 1/0 la loi l'expression de Java qui devrait compiler n'importe quand n'importe où?

Oui.

Ce n'JLS dire à ce sujet?

Rien de particulier ... à part dire que la division par zéro entraînera une exception d'exécution. Cependant, la JLS reconnaît que la possibilité d'exceptions d'exécution dans la définition suivante:

"Une constante de compilation de l'expression est une expression désignant une valeur de type primitif ou une Chaîne de caractères qui ne se termine pas brutalement et est composé en utilisant uniquement le suivant: ..."

(Italiques ajoutés.) Donc la suite ne serait PAS de la compilation:

switch(i) {
    case 1:
    case 1 + 1: 
    case 1 / 0:  // compilation error.
}

Si c'est légal, est-il une bonne raison pour cela?

Bonne question. Je suppose que c'est une façon de jeter de l' ArithmeticException si ça n'est pas une raison plausible. Plus probablement la raison pour la spécification de Java est d'éviter une complexité inutile dans la JLS et compilateurs pour traiter un cas limite qui est rarement va mordre les gens.

Mais ce n'est que par le par. Le fait est que, 1/0 est valable de code Java, et pas de Java compilateur doit jamais drapeau cela comme une erreur de compilation. (Il serait raisonnable pour un compilateur Java pour émettre un avertissement, à condition qu'il existe un compilateur interrupteur pour l'éteindre.)

20voto

polygenelubricants Points 136838

J'ai fait quelques recherches dans la Base de données de Bogues, et découvert quelques informations intéressantes.

Bug ID 4178182: JLS ne pas spécifier le comportement de 1/0 comme une expression constante

Le code suivant est illégal:

class X { static final int i = 1 / 0; }

La valeur de cette constante à la compilation n'est pas défini, donc ce doit être une erreur de compilation. Guy Steele a confirmé environ 18 mois il y a que c'était en effet l'intention de comportement.

Une constante de compilation doit avoir sa valeur disponible de manière statique (c'est ce qui en fait une constante de compilation ;-) Par exemple, la valeur des autres des constantes dont les valeurs sont déterminées par une constante qui contient une division par zéro ne sont pas définis. Cela affecte la sémantique de l' switchdes déclarations, précise l'affectation et unassignment, etc.

Bug ID 4089107: javac traite division entière par (constante) de zéro, comme une erreur

public class zero {
   public static void main(String[] args) {
      System.out.println(1/0);
   }
}

L'exécution de la ci-dessus, on obtient:

zero.java:3: Arithmetic exception.
     System.out.println(1/0);
                         ^
1 error

Bug ID 4154563: javac accepte la division par zéro des expressions constantes dans le cas des expressions.

Compilateur Java se bloque, tout en essayant de compiler prochain test. Ce test se bloque tous les 1.2beta4 des versions de compilateur, mais un bug est absente dans les 12.beta3. Un exemple de compilateur et de diagnostic suivre:

public class B {
   public static void main(String argv[]) {
      switch(0){
         case 0/0:
      }
  }
}

Évaluation: Le compilateur utilisé dans toutes les tentatives de diviser par la constante de zéro, comme des erreurs de compilation. Ce problème a été corrigé dans beta3 de sorte que le code sera généré pour la division par une constante égale à zéro. Malheureusement, ce bug a été introduit. Le compilateur doit gérer une division par zéro dans le cas de l'expression gracieusement.

Conclusion

Donc, la question de savoir si ou non 1/0 devrait compiler a été attaqué sujet de discussion avec certaines personnes citant Guy Steele en invoquant que ce doit être une erreur de compilation, et d'autres disent qu'il ne devrait pas. Il semble que, finalement, il est décidé que ce n'est ni une erreur de compilation, ni une constante de compilation.

3voto

Corey Points 607

Eh bien, si vous vous regardez dans le Double de la classe, vous verrez ce qui suit:

/**
 * A constant holding the positive infinity of type
 * <code>double</code>. It is equal to the value returned by
 * <code>Double.longBitsToDouble(0x7ff0000000000000L)</code>.
 */
public static final double POSITIVE_INFINITY = 1.0 / 0.0;

Le même calcul est effectué dans la classe integer, à l'exception de chars au lieu de doubles. Fondamentalement, 1/0 retourne un très, très grand nombre, plus que le Double.MAX_VALUE.

Ce code suivant:

public static void main(String[] args) {
    System.out.println(Double.POSITIVE_INFINITY);
    System.out.println(Double.POSITIVE_INFINITY > Double.MAX_VALUE);
}

Sorties:

Infinity
true

Noter le cas particulier de l'impression d' Double.POSITIVE_INFINITY. Il imprime une chaîne de caractères, si c'est considéré comme un double.

Pour répondre à la question, oui c'est légal en Java, mais 1/0 résout à "l'infini", et est traitée différemment de Double standard (ou de flotteurs, ou ainsi de suite et ainsi de suite).

Je tiens à noter que je n'ai pas la moindre idée de comment ou pourquoi il a été mis en œuvre cette manière. Quand je vois au-dessus de la sortie, il semble que tout comme la magie noire pour moi.

2voto

Marcelo Cantos Points 91211

Java exige explicitement que la division entière par zéro déclenche un ArithmeticException . L'affectation à j ne peut pas être éliminée car cela enfreindrait les spécifications.

0voto

Will Hartung Points 57465

C’est légal, car il n’est pas acquis que le compilateur est supposé plier des expressions constantes au moment de la compilation.

Un compilateur "intelligent" pourrait compiler:

 a = 1 + 2
 

comme

 a = 3
 

Mais rien ne dit que le compilateur DOIT le faire. Autre que cela, 1/0 est une expression légale comme:

 int a;
int b;

a = a/b;
 

est une expression légale.

À l'exécution, il lève une exception, mais c'est une erreur d'exécution pour une raison.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X