56 votes

Java les Énumérations et les Instructions Switch - le cas par défaut?

Pour les personnes suggérant lancer une exception:
Lancer une exception ne me donne pas une erreur de compilation, il me donne une erreur d'exécution. Je sais que je peux lancer une exception, je préfère mourir lors de la compilation que lors de l'exécution.

La première, je suis à l'aide d'eclipse 3.4.

J'ai un modèle de données qui a un mode de propriété qui est un Enum.

enum Mode {on(...), off(...), standby(...); ...}

Je suis actuellement à la rédaction d'une vue de ce modèle et j'ai le code

...
switch(model.getMode()) {
case on:
   return getOnColor();
case off:
   return getOffColor();
case standby:
   return getStandbyColor();
}
...

J'obtiens un message d'erreur "Cette méthode doit retourner un résultat de type java.awt.La couleur" parce que je n'ai pas de cas de défaut et sans retour xxx à la fin de la fonction. Je veux une erreur de compilation dans le cas où quelqu'un ajoute un autre type enum (par exemple shuttingdown) donc je ne veux pas mettre un cas de défaut qui déclenche une AssertionError, ce qui permettra de compiler une modification de la Mode et ne pas être vu comme une erreur jusqu'à ce que l'exécution.

Ma question est la suivante:
Pourquoi ne EclipseBuilder (et javac) de ne pas reconnaître que ce commutateur couvre toutes les possibilités (ou couvre-t-elle?) et arrêter de me prévenir sur d'avoir besoin d'un type de retour. Est il possible que je peux faire ce que je veux sans ajout de méthodes à la Mode?

À défaut, est-il une option d'avertissement/d'erreur sur les instructions switch qui ne couvre pas tous les Enum valeurs possibles?

Edit: Rob: C'est une compilation d'erreur. J'ai juste essayé de le compiler avec javac et je reçois un "manque d'instruction return" erreur de ciblage de la dernière } de la méthode. Eclispe seulement des lieux de l'erreur en haut de la méthode.

71voto

mtpettyp Points 3931

Vous pouvez toujours utiliser l'Enum avec des habitudes des Visiteurs:

enum Mode
{
  on
  {
      public <E> E accept( ModeVisitor<E> visitor )
      {
         return visitor.visitOn();
      }
  },
  off
  {
      public <E> E accept( ModeVisitor<E> visitor )
      {
         return visitor.visitOff();
      }
  },
  standby
  {
      public <E> E accept( ModeVisitor<E> visitor )
      {
         return visitor.visitStandby();
      }
  }

  public abstract <E> E accept( ModeVisitor<E> visitor );

  public interface ModeVisitor<E>
  {
      E visitOn();
      E visitOff();
      E visitStandby();
  }
}

Ensuite, vous mettre en place quelque chose comme ce qui suit:

public final class ModeColorVisitor implements ModeVisitor<Color>
{
    public Color visitOn()
    {
       return getOnColor();
    }

    public Color visitOff()
    {
       return getOffColor();
    }

    public Color visitStandby()
    {
       return getStandbyColor();
    }

}

Vous souhaitez utiliser comme suit:

return model.getMode().accept( new ModeColorVisitor() );

C'est beaucoup plus détaillé, mais vous auriez tout de suite une erreur de compilation si une nouvelle enum a été déclarée.

57voto

egaga Points 5367

Vous devez l'activer dans Eclipse (fenêtre -> préférences), les paramètres "type Enum constante ne sont pas couverts dans switch" avec un niveau d'Erreur.

Lever une exception à la fin de la méthode, mais n'utilisez pas de cas de défaut.

public String method(Foo foo)
  switch(foo) {
  case x: return "x";
  case y: return "y";
  }

  throw new IllegalArgumentException();
}

Maintenant, si quelqu'un ajoute de nouveaux cas plus tard, Eclipse va lui faire savoir qu'il ne manque plus qu'un cas. Donc, ne jamais utiliser la valeur par défaut, sauf si vous avez vraiment de bonnes raisons de le faire.

10voto

amarillion Points 5863

Je ne sais pas pourquoi vous obtenez ce message d'erreur, mais ici, c'est une suggestion, Pourquoi ne pas définir la couleur de l'enum lui-même? Ensuite, vous ne pouvez pas accidentellement oublier de définir une nouvelle couleur.

Par exemple:

import java.awt.Color;

public class Test {

    enum Mode 
    {
    	on (Color.BLACK), 
    	off (Color.RED),
    	standby (Color.GREEN);

    	private final Color color; 
    	Mode (Color aColor) { color = aColor; }
    	Color getColor() { return color; }
    }

    class Model
    {
    	private Mode mode;
    	public Mode getMode () { return mode; }
    }

    private Model model;

    public Color getColor()
    {
    	return model.getMode().getColor();
    }	
}

btw, pour comparaison voici la boite d'origine, avec d'erreur du compilateur.

import java.awt.Color;
public class Test {

    enum Mode {on, off, standby;}

    class Model
    {
    	private Mode mode;
    	public Mode getMode () { return mode; }
    }

    private Model model;

    public Color getColor()
    {
    	switch(model.getMode()) {
    	case on:
    	   return Color.BLACK;
    	case off:
    	   return Color.RED;
    	case standby:
    	   return Color.GREEN;
    	}
    }	
}

6voto

Paul Sonier Points 25528

Je dirais que c'est probablement parce que modèle.GetMode() peut retourner la valeur null.

2voto

mipadi Points 135410

Pourquoi ne EclipseBuilder ne pas reconnaître que ce commutateur couvre toutes les possibilités (ou couvre-t-elle?) et arrêter de me prévenir sur d'avoir besoin d'un type de retour. Est il possible que je peux faire ce que je veux sans ajout de méthodes à la Mode?

Ce n'est pas un problème dans Eclipse, mais plutôt le compilateur, javac. Tous javac voit, c'est que vous n'avez pas de valeur de retour dans le cas où rien n' est adapté (le fait que vous savez que vous êtes correspondant à tous les cas, peu importe). Vous devez retourner quelque chose dans le cas par défaut (ou lever une exception).

Personnellement, je venais de jeter quelque sorte d'exception.

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