enum und switch (neu): falschen Wert mit IllegalArgumentException oder mit EnumConstantNotPresentException abfangen ?

volcanos

Bekanntes Mitglied
Wenn ein falscher Wert eingegeben wird, soll das Programm nicht den printStackTrace ausgeben, sondern zB: "Farbe nicht gefunden".

Funktioniert so nicht !

Java:
public class EnumSwitchExample
{   
    private enum Farbe { ROT, GRUEN, BLAU, GELB, rot, gruen, blau, gelb }
    
    public static void main(String... args)
    {       
        // String input = args[0];
        
        // oder:
        
        String input = "";
        
        try
        { input = javax.swing.JOptionPane.showInputDialog("Farbe eigeben: "); }
        catch (EnumConstantNotPresentException e) { System.out.println("Der Wert kann nicht verifiziert werden"); }
        
        Farbe farbe = Farbe.valueOf(input);               
        
        switch (farbe)
        {
            case ROT, rot -> System.out.println("Farbe ist rot");
        
            case GRUEN, gruen -> System.out.println("Farbe ist grün");
            
            case BLAU, blau -> System.out.println("Farbe ist blau");
        
            case GELB, gelb -> System.out.println("Farbe ist gelb");           
            
            // default ->  throw new IllegalArgumentException("Farbe nicht gefunden !!!");
            // default -> throw new EnumConstantNotPresentException(???);
            default ->  colorNotFound();
        }
        
        
    }   
    
    public static void colorNotFound()
    {
        try { javax.swing.JOptionPane.showConfirmDialog(null, null, "Farbe nicht gefunden !!!", 2); }
        catch (IllegalArgumentException e) { System.out.println("Error !!!"); }   
        // catch (EnumConstantNotPresentException e) { System.out.println("Error !!!"); }       
    }   
}
 
Y

yfons123

Gast
warum sollte überhaupt eine exception kommen?

du garantierst doch mit default dass alles funktionieren wird ( zumindest dein enum teil.. ka was input da für exceptions haben kann
 

KonradN

Super-Moderator
Mitarbeiter
das ist ja das Problem. mit diesen obigen default's passiert gar nix !

Der "default -> ..." ist falsch !
Dein Problem ist, dass Du noch nicht verstanden hast, wenn welche Exception kommen kann.

Du hast ein try / catch bei showInputDialog, aber da kann keine Exception kommen.

Du hast kein try/catch um den valueOf Aufruf. Da kann aber eine Exception kommen.
 

volcanos

Bekanntes Mitglied
Das habe ich schon probiert:

try { Farbe farbe = Farbe.valueOf(input); }
catch (IllegalArgumentException e ) {System.out.println("falsche farbe");}

dann kommt bei
switch(farbe)
farbe cannot be resolved to a variable
 

httpdigest

Top Contributor
Ja, jetzt deklarierst du die lokale Variable farbe innerhalb des try-catch. Mache die Deklaration außerhalb und die Zuweisung innerhalb.
Java:
Farbe farbe = null;
try {
  farbe = Farbe.valueOf(input);
} catch (IllegalArgumentException e ) {
  System.out.println("falsche farbe");
}
 

volcanos

Bekanntes Mitglied
Ja, danke. Jetzt funktioniert es :)

Java:
public class EnumSwitchExample
{   
    private enum Farbe { ROT, GRUEN, BLAU, GELB, rot, gruen, blau, gelb }
    
    public static void main(String... args)
    {       
        // String input = args[0];
        
        // oder:
        
        String input = "";
        
        input = javax.swing.JOptionPane.showInputDialog("Farbe eigeben: "); 
        
        Farbe farbe = null;
        try
        { farbe = Farbe.valueOf(input); }
        catch (IllegalArgumentException e) { colorNotFound(); }
        
        
        switch (farbe)
        {
            case ROT, rot -> System.out.println("Farbe ist rot");
        
            case GRUEN, gruen -> System.out.println("Farbe ist grün");
            
            case BLAU, blau -> System.out.println("Farbe ist blau");
        
            case GELB, gelb -> System.out.println("Farbe ist gelb");           
            
            default ->  colorNotFound();
        }   
    }
    
    
    public static void colorNotFound()
    { javax.swing.JOptionPane.showConfirmDialog(null, null, "Farbe nicht gefunden !!!", 2); }   
}
 

volcanos

Bekanntes Mitglied
Habs jetzt nochmals etwas verändern müssen, da wieder in der Eclipse-Console ein lästiger Error ausgegeben wurde:

Java:
import javax.swing.JOptionPane;

public class EnumSwitchExample
{   
    private enum Farbe { ROT, GRUEN, BLAU, GELB, rot, gruen, blau, gelb, NIX }
    
    public static void main(String... args)
    {       
        // String input = args[0];       
        // oder:       
        String input = "";
        
        // Eingabe-Fenster:
        input = JOptionPane.showInputDialog("Farbe eigeben:"); 
        
        Farbe farbe = Farbe.NIX;
        try
        { farbe = Farbe.valueOf(input); }
        catch (IllegalArgumentException e) { colorNotFound(); }   
        // catch (NullPointerException e) { System.out.println("Farbe nicht gefunden !!!"); }
        
        switch (farbe)
        {
            case ROT, rot -> System.out.println("Farbe ist rot.");       
            case GRUEN, gruen -> System.out.println("Farbe ist grün.");           
            case BLAU, blau -> System.out.println("Farbe ist blau.");       
            case GELB, gelb -> System.out.println("Farbe ist gelb.");           
            // case NIX -> System.out.println("Farbe nicht gefunden !!!");           
            
            // default ->  colorNotFound();
        }   
    }
    
    
    // Ausgabe-Fenster:
    public static void colorNotFound()
    { JOptionPane.showConfirmDialog(null, null, "Farbe nicht gefunden !!!", 2); }   
}
 

Neumi5694

Top Contributor
Glücklich wirst du damit immer noch nicht werden.
Im Falle der IllegalArgumentException ist "farbe" danach null.
So lange du die language preview Funktionen noch nicht aktiviert hast, wird switch danach eine NullpointerException werfen.
Ich würde den Parser samt Exception auslagern ohne Meldungsfenster, schon allein um Logik und Ausgabe zu trennen

Java:
private Optional<Farbe> getFarbe(String s) {
    try {
        return Optional.of(Farbe.valueOf(s));
    } catch (IllegalArumentException e) {
        return Optional.empty();
    }
}

public void main(String... args) {
    [...]
    var oFarbe = getFarbe(input);
    if (oFarbe.isPresent()) {
        switch (farbe)
        {
            case ROT, rot -> System.out.println("Farbe ist rot.");      
            case GRUEN, gruen -> System.out.println("Farbe ist grün.");          
            case BLAU, blau -> System.out.println("Farbe ist blau.");      
            case GELB, gelb -> System.out.println("Farbe ist gelb.");          
             default ->  colorNotFound();
        }  
        //Hier kann man auch den Namen bestimmen lassen anstatt direkt was auszugeben, so etwa:
        var farbName = switch(oFarbe.get()) {
            case ROT, rot -> "rot";
            case GRUEN, gruen -> "grün";
            case BLAU, blau -> "blau";
            case GELB, gelb -> "gelb";
            case NIX -> "unbestimmt";
        };
        System.out.printf("Farbe ist %s.%n", farbName);
    } else {
      colorNotFound();
    }
}


Was mir am Enum grundsätzlich nicht gefällt: Bei dir unterscheidet sich aber ROT von rot, obwohl beide das Selbe bedeuten.
Besser: Schreib eine eigene parse-Funktion, die case-Insensitive ist, dazu auch gleich einen Unit-Test, der prüft, ob jede Farbe richtig erkannt wird.
Code:
private enum Farbe { ROT, GRUEN, BLAU, GELB, NIX ;
  //In diesem Fall mit Optional, geht natürlich auch direkt.
  private Optional<Farbe> getItem(String name) {
    for (var f : Farbe.values()) {
      if (f.name().equalsIgnoreCase(name)) {
        return Optional.of(f);
      }
    }
    return Optional.empty(); //hier wäre natürlich auch die Rückgabe eines Default-Werts wie NIX möglich.
  }
}

//UnitTest
for (var f : Farbe.values()) {
  Assert.assertSame(f, Farbe.getItem(f.name()).get());
}
 

MarvinsDepression

Bekanntes Mitglied
Das sollte auch funktionieren:
Java:
public class EnumSwitchExample {  
   
    private enum Farbe { ROT, GRUEN, BLAU, GELB }
   
    public static void main(String... args) {      
        Farbe selection = null;
       
        while (selection == null) {
            String input = javax.swing.JOptionPane.showInputDialog("Farbe eigeben: ");
           
            try {
                selection = Farbe.valueOf(input.trim().toUpperCase());  
            } catch (Exception e) { System.out.println("Der Wert kann nicht verifiziert werden"); }
        }
       
        switch (selection) {
            case ROT -> System.out.println("Farbe ist rot");
            case GRUEN -> System.out.println("Farbe ist grün");
            case BLAU -> System.out.println("Farbe ist blau");
            case GELB -> System.out.println("Farbe ist gelb");          
        }
    }
}
 
Y

yfons123

Gast
ich weis nicht wie man es in java macht aber in c# kannst du zb
Farbe farb = (Farbe)1000;
was nicht im spektrum der reichweite liegt dachte dass es sowas auch in java gibt und da kommst halt dann ohne default case in probleme
 

MarvinsDepression

Bekanntes Mitglied
Mit Farbe.valueOf() bekommst du eh nur einen gültigen Wert oder halt null (oder Exception?). Beides wird aber in der while-Schleife behalten.
Ein Default ist nicht nötig wenn alle Items des Enum aufgezählt werden.
 

KonradN

Super-Moderator
Mitarbeiter
Wobei man hier durchaus einen Punkt bedenken muss:

Wir haben eine recht schwierige Abhängigkeit zwischen Enum und dem Code dieses Switch Anweisung. Was ist, wenn das Enum erweitert wird? Es kommen weitere Elemente hinzu? Das wird erst einmal nicht auffallen. Wenn wir also ein "DUNKELROT" hinzufügen, dann kann man das Eingeben und es kommt einfach keine Ausgabe. Das kann aber natürlich in anderer Form viel kritischer sein.

Hier kann man auf einen Default kommen um dies zu lösen. Dann erreicht man, dass in so einem Fall die Ausführung nicht unbemerkt weiter läuft sondern z.B. eine Exception geworfen wird. Aber habe ich dadurch viel gewonnen? Ich kriege eine Exception und das, was ich machen will, läuft dennoch nicht.

Was sind die möglichen Lösungsideen:

1) Auf den Switch verzichten. Dann bekommt der Enum ein Attribut und dann wird das zu etwas wie:
System.out.println("Die Farbe ist " + selection.getDescription());
Damit liegt die Verantwortung direkt beim Enum und wir haben nicht den Fall, dass eine Änderung am Enum an anderer Stelle etwas kaputt macht.

2) manchmal gehört etwas nicht an diese Stelle. Dies ist ein gutes Beispiel: Das Enum ist nur ein bestimmter (Business) Wert. Wie dieser Ausgegeben wird gehört einfach nicht in Entität. Also gibt es eine Ausgabelogik. Das kann dann z.B. sowas sein:

Java:
public Interface ColorPrinter {
    void print(Farbe color);
}

Java:
public class GermanColorPrinter implements ColorPrinter {
    public void print(Farbe color) {
        switch (color) {
                // ...
        }
    }
}
Jetzt haben wir natürlich wieder diese Problematik. Das kommt aber dann z.B. in einem UnitTest um eben diesen Fall mit zu bekommen:

Java:
public class GermanColorPrinterTests {
    /**
     * Tests that the number of entries inside Farbe enum wasn't changed.
     * <p>
     * Do not change this test without changing the number of Elements inside the switch statement!
     * </p>
     */
    public void testNumberOfEntriesInsideFarbeEnum() {
        int numberOfSwitchEntries = 4;
        assertEquals(Farbe.values().length, numberOfSwitchEntries);
    }
}
Damit hätte man einen Unit-Test der fehlschlägt, wenn ein neues Element hinzu kommt. Wenn ein Element umbenannt wird, dann wird der Code ja nicht mehr übersetzen.

Das wäre da so meine Sicht auf diese Problematik.
 

MarvinsDepression

Bekanntes Mitglied
Oh Gott, ich dachte halt: "wenns Enum verändert wird, meckert die IDE schon" 😬
Da bist Du mir halt Dekaden voraus. Gut erklärt!
Bin immer wieder überrascht, wie weit die Kluft zwischen 'für den Hausgebrauch' und 'bis zum Ende gedacht' offen steht.
 

MarvinsDepression

Bekanntes Mitglied
Hab ich ja und hab mich drauf verlassen. Aber eine Garantie gibt dir niemand und wenn zur Kompelierzeit keinen Fehler auftritt, dann knallt es halt zur Laufzeit...
Also doch lieber mit default.
 

Neumi5694

Top Contributor
Mit Farbe.valueOf() bekommst du eh nur einen gültigen Wert oder halt null (oder Exception?). Beides wird aber in der while-Schleife behalten.
Ein Default ist nicht nötig wenn alle Items des Enum aufgezählt werden.
Den hab ich nur erwähnt, weil er noch den Wert NIX hat, der der wohl so viel wie "keine gültige Eingabe" bedeutet.
Wenn null ok ist, dann kann man NIX natürlich auch einfach weglassen.
 

volcanos

Bekanntes Mitglied
Wenn enum verändert wird, merkt man das sofort, wenn nix rauskommt.
Dann braucht man nur mehr den switch entsprechend verändern.

Ja, und das mit
default -> colorNotFound();
ist aber trotzdem sicher eine gute Idee.

Zur Zeit sieht der Code so aus :

Java:
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import javax.swing.Icon;
import javax.swing.JOptionPane;
import javax.swing.text.html.StyleSheet;


public class EnumSwitchExample
{  
    private enum Farbe { RED, GREEN, BLUE, YELLOW, ORANGE, BLACK, GRAY }
    static String input = "";
   
    // String in Color umwandeln:
    static StyleSheet color = new StyleSheet();
    static Color col = null;
   
    static Icon icon = new Icon()
    {      
        @Override public void paintIcon( Component c, Graphics g, int x, int y )
        {
            col = color.stringToColor(input);
            g.setColor(col);
            g.fillOval(x, y, getIconWidth(), getIconHeight());
        }
       
        @Override public int getIconWidth()
        { return 30; }
       
        @Override public int getIconHeight()
        { return 30; }
    };  
   
   
    // Main:
    public static void main(String... args)
    {          
        // String input = args[0];     // -> für Aufruf in der command_line mit 'java EnumSwitchExample ROT'  
       
        Farbe selection = null;
       
        // Eingabe-Fenster:  
        while (selection == null)
        {
               input = JOptionPane.showInputDialog("Farbe des Tages eigeben:");
               
            try { selection = Farbe.valueOf(input.trim().toUpperCase()); }  
            catch (Exception e) { colorNotFound(); }
        }  
       
        switch (selection)
        {
            case RED -> colorFound();      
            case GREEN -> colorFound();          
            case BLUE -> colorFound();      
            case YELLOW -> colorFound();          
            case ORANGE -> colorFound();
            case BLACK -> colorFound();
            case GRAY -> colorFound();

            // case MAGENTA ...  PINK ... CYAN -> colorFound();                          // kommt immer schwarz ???
           
            default ->  colorNotFound();
        }      
    }  
   
   
    // Ausgabe-Fenster 'colorFound':
    public static void colorFound()
    { JOptionPane.showConfirmDialog(null, "ist die Farbe des Tages.", "Ausgabe-Fenster",  2, 2, icon); }
   
   
    // Ausgabe-Fenster 'colorNotFound':
    public static void colorNotFound()
    { JOptionPane.showConfirmDialog(null, "Farbe nicht gefunden !!!", "Ausgabe-Fenster", 2); }  
}
 
Zuletzt bearbeitet:

KonradN

Super-Moderator
Mitarbeiter
Wenn enum verändert wird, merkt man das sofort, wenn nix rauskommt.
Dann braucht man nur mehr den switch entsprechend verändern.
Wer merkt es wann? Das ist ja das Thema. Du merkst es nicht automatisch. Und damit ist die Gefahr gegeben, dass es ein Problem wird, das an den Kunden raus gegeben wird.

Dazu macht man ja die automatisierten Tests. Der Entwickler soll etwas mitbekommen.
 
Y

yfons123

Gast
dein code tut auch nichts mit magenta... ist auskommentiert also wäre es nur blindes raten was du probiert hast
 

volcanos

Bekanntes Mitglied
Un noch ein Problem gibt es beim obigen Code. Das 'Abrechen' funktioniert nicht.
Wenn man nicht weiß, was man 'richtig' eingeben muss, kommt man von der while-Schleife nie mehr raus !
 

volcanos

Bekanntes Mitglied
private enum Farbe { RED, GREEN, BLUE, YELLOW, ORANGE, BLACK, GRAY, MAGENTA }

case MAGENTA -> colorFound(); // kommt immer schwarz ???
case PINK dito
case CYAN dito
 

KonradN

Super-Moderator
Mitarbeiter
kein raten ! Der Code ist fast perfekt ! -> bis auf die Endlos-Schleife ...
Sorry, diese Sicht teile ich nicht.

a) Bezeichner teilweise seltsam. Ein Stylesheet ist in der variable color? Ja, wenn ich die Variable color sehe, dann würde ich da auch ein Stylesheet erwarten.
b) Du hast Variablen wild überall genutzt. Du erweiterst Icon in Deiner Klasse und nutzt da z.B. direkt input. Also absolut keine Kapselung. Sowas macht Code schwer nachvollziehbar, weil es eben nicht intuitiv ist, was da genau abläuft. Hier würde ich das eher besser Kapseln und das in einer eigenen Klasse machen. Und dann würde ich im Code deutlich machen, dass da dann etwas genutzt wird und intern etwas passiert. Was man da z.B. machen könnte, wäre ein new ColorIcon(selectedColor) zu nutzen. ColorIcon wäre halt die eigenständige Klasse und das andere wäre ein Parameter, der in der Methode colorFound übergeben würde.

Aber kommen wir zu dem eigentlichen Problem:
Du verwendest hier wild Dinge ohne zu prüfen, ob es überhaupt das macht, was es machen soll. In diesem Fall setzt du voraus, dass Stylesheet.stringToColor für alle Elemente etwas sinnvolles liefert und das kann man ja schnell testen:

Java:
package de.kneitzel;

import org.junit.jupiter.api.Test;

import javax.swing.text.html.StyleSheet;

import static org.junit.jupiter.api.Assertions.*;

public class StylesheetTests {

    enum Farbe { RED, GREEN, BLUE, YELLOW, ORANGE, BLACK, GRAY, MAGENTA }

    /**
     * Java Forum Thread: https://www.java-forum.org/thema/enum-und-switch-neu-falschen-wert-mit-illegalargumentexception-oder-mit-enumconstantnotpresentexception-abfangen.198406/#post-1317717
     */
    @Test
    public void testStringToColor() {
        StyleSheet styleSheet = new StyleSheet();
        for (Farbe color : Farbe.values()) {
            assertNotNull(styleSheet.stringToColor(color.toString()));
        }
    }
}

Siehe da - dem ist nicht der Fall :)
 

volcanos

Bekanntes Mitglied
Schlau werde ich von dem JUNIT-Test trotzdem nicht.
Wenn man nämlich MAGENTA weglässt, dann ist alles grün:
Java:
import static org.junit.jupiter.api.Assertions.assertNotNull;

import javax.swing.text.html.StyleSheet;

import org.junit.jupiter.api.Test;

class StyleSheetTest
{
    enum Farbe { RED, GREEN, BLUE, YELLOW, ORANGE, BLACK, GRAY }


    @Test
    void test()
    {
        StyleSheet styleSheet = new StyleSheet();
        for (Farbe color : Farbe.values())
        {
            assertNotNull(styleSheet.stringToColor(color.toString()));
        }
    }
}

Gibt man aber MAGENTA dazu:
enum Farbe { RED, GREEN, BLUE, YELLOW, ORANGE, BLACK, GRAY, MAGENTA }
dann wird es rot und es kommt:
"org.opentest4j.AssertionFailedError: expected: not <null>..."
...
...
 

KonradN

Super-Moderator
Mitarbeiter
Das liegt dann schlicht daran, dass Stylesheet.stringToColor beim Parameter "MAGENTA" eben null zurück gibt. Und damit gibst Du bei g.setColor als Parameter mit dem null halt nicht wirklich eine Farbe. (Ich finde das Verhalten nicht ok, ich hätte da eine NPE geworfen, wenn ich das setColor entwickelt hätte. )
 

volcanos

Bekanntes Mitglied
Das mit dem StyleSheet war sowieso nicht meine Idee. Ich wollte das mit
static Color col = Color.getColor(input);
und
g.setColor(col);
lösen.

Hat nicht funktioniert:

System.out.println(input); -> blue
System.out.println(col); -> null
 
Zuletzt bearbeitet:

KonradN

Super-Moderator
Mitarbeiter
Wieso baust Du das nicht direkt mit in die Enum ein?
Oder man macht eine Map. Du hast ja in erster Linie nur Color Werte und dazu dann Namen. Also typische Map.

Diese Lösungsideen könnten so aussehen:

Enum Idee:
Java:
package de.kneitzel.implementationideas;

import java.awt.*;

/**
 * Example of an enum with properties.
 * https://www.java-forum.org/thema/enum-und-switch-neu-falschen-wert-mit-illegalargumentexception-oder-mit-enumconstantnotpresentexception-abfangen.198406/#post-1317747
 */
public enum CustomColorEnum {
    BLACK(Color.BLACK),
    CYAN(Color.CYAN),
    SPECIAL_BLUE(new Color(50, 50, 100));

    private Color color;

    CustomColorEnum(Color color) {
        this.color = color;
    }

    public Color getColor() {
        return color;
    }
}

Map Idee:
Java:
package de.kneitzel.implementationideas;

import java.awt.*;
import java.util.HashMap;
import java.util.Map;

/**
 * Example of a Map with hard values.
 * https://www.java-forum.org/thema/enum-und-switch-neu-falschen-wert-mit-illegalargumentexception-oder-mit-enumconstantnotpresentexception-abfangen.198406/#post-1317747
 */
public class CustomColorMap {
    private Map<String, Color> colors = new HashMap<>();

    public CustomColorMap() {
        colors.put("black", Color.BLACK);
        colors.put("cyan", Color.CYAN);
        colors.put("special_black", new Color(50, 50, 100));
    }

    public Color getColor(String name) {
        return colors.get(name.toLowerCase());
    }
}
 

Neumi5694

Top Contributor
Wieso baust Du das nicht direkt mit in die Enum ein?
Oder man macht eine Map. Du hast ja in erster Linie nur Color Werte und dazu dann Namen. Also typische Map.

Diese Lösungsideen könnten so aussehen:

Enum Idee:
Java:
package de.kneitzel.implementationideas;

import java.awt.*;

/**
 * Example of an enum with properties.
 * https://www.java-forum.org/thema/enum-und-switch-neu-falschen-wert-mit-illegalargumentexception-oder-mit-enumconstantnotpresentexception-abfangen.198406/#post-1317747
 */
public enum CustomColorEnum {
    BLACK(Color.BLACK),
    CYAN(Color.CYAN),
    SPECIAL_BLUE(new Color(50, 50, 100));

    private Color color;

    CustomColorEnum(Color color) {
        this.color = color;
    }

    public Color getColor() {
        return color;
    }
}

Map Idee:
Java:
package de.kneitzel.implementationideas;

import java.awt.*;
import java.util.HashMap;
import java.util.Map;

/**
 * Example of a Map with hard values.
 * https://www.java-forum.org/thema/enum-und-switch-neu-falschen-wert-mit-illegalargumentexception-oder-mit-enumconstantnotpresentexception-abfangen.198406/#post-1317747
 */
public class CustomColorMap {
    private Map<String, Color> colors = new HashMap<>();

    public CustomColorMap() {
        colors.put("black", Color.BLACK);
        colors.put("cyan", Color.CYAN);
        colors.put("special_black", new Color(50, 50, 100));
    }

    public Color getColor(String name) {
        return colors.get(name.toLowerCase());
    }
}
Persönlich favorisiere ich bei so was einfeachem die direkte Eigenschaft zu verwenden. Map ist für alles, was nicht direkt eine Eigenschaft des Wertes ist, das ist aber Geschmackssache.

Ergänzend: Wir haben für Enums bessere Map als die HashMap, nämlich die EnumMap. EnumMap und EnumSet sind optimiert, arbeiten intern mit einer BitMaske und für den Zugriff auf die Map mit einem Array, Indizes sind ja für jeden Wert bekannt (ordinal).

EnumSet hat ein paar verdammt praktische statisch Supplier (of, noneOf, copyOf, allOf, complementOf), EnumMap erzeugt bei clone() im Gegensatz zut Hashmap direkt wieder eine EnumMap, die nicht gecastet werden muss. Braucht man jetzt nicht wirklich oft, aber ich erwähn's mal :).

Ein weiterer Vorteil der EnumMap- und Sets- ist, dass sie sortiert sind, die Reihenfolge entspricht immer der Reihenfolge, in der die Werte im Set stehen, sortieren per ordinal() entfällt bei weiterer Verwendung z.B. in einer Liste.
 

KonradN

Super-Moderator
Mitarbeiter
Ergänzend: Wir haben für Enums bessere Map als die HashMap, nämlich die EnumMap. EnumMap und EnumSet sind optimiert, arbeiten intern mit einer BitMaske und für den Zugriff auf die Map mit einem Array, Indizes sind ja für jeden Wert bekannt (ordinal).
Das setzt aber eine Enum Voraus. In der Map Variante gibt es aber keine Enum. Daher kommt auch keine EnumMap in Frage.

Wenn Du die Keys wieder in einem Enum hast, dann hast Du wieder das gleiche Problem, das wir schon angeschnitten haben: Eine Anpassung der Enum bedarf immer einer externen Anpassung und wenn diese nicht gemacht wird, bekommt man es nicht wirklich mit. (Dabei ist es ja egal, ob es in einer switch fehlt oder beim füllen der Map)
 

Neumi5694

Top Contributor
Das setzt aber eine Enum Voraus. In der Map Variante gibt es aber keine Enum. Daher kommt auch keine EnumMap in Frage.

Wenn Du die Keys wieder in einem Enum hast, dann hast Du wieder das gleiche Problem, das wir schon angeschnitten haben: Eine Anpassung der Enum bedarf immer einer externen Anpassung und wenn diese nicht gemacht wird, bekommt man es nicht wirklich mit. (Dabei ist es ja egal, ob es in einer switch fehlt oder beim füllen der Map)
ah ... my bad. Hatte mich verlesen :)
Hatte beim Lesen des Beispiels noch den vorigen Codeteil im Kopf.
 
Zuletzt bearbeitet:

volcanos

Bekanntes Mitglied
Bei der enum-Variante :
beim Icon geht anscheinend CustomColorEnum (Color) nicht.

The method setColor(Color) in the type Graphics is not applicable for the arguments (EnumSwitchExample.CustomColorEnum)

Java:
static CustomColorEnum color3 = CustomColorEnum.CYAN;
       
    static Icon icon = new Icon()
    {      
        @Override public void paintIcon(Component c, Graphics g, int x, int y)
        {
            //col = color2.stringToColor(input);
            //g.setColor(CustomColorEnum.input);
            g.setColor(color3);
           
           
            g.fillOval(x, y, getIconWidth(), getIconHeight());
        }
       
        @Override public int getIconWidth()
        { return 30; }
       
        @Override public int getIconHeight()
        { return 30; }
    };
 

Neumi5694

Top Contributor
Bei der enum-Variante :
beim Icon geht anscheinend CustomColorEnum (Color) nicht.

The method setColor(Color) in the type Graphics is not applicable for the arguments (EnumSwitchExample.CustomColorEnum)

Java:
static CustomColorEnum color3 = CustomColorEnum.CYAN;
      
    static Icon icon = new Icon()
    {     
        @Override public void paintIcon(Component c, Graphics g, int x, int y)
        {
            //col = color2.stringToColor(input);
            //g.setColor(CustomColorEnum.input);
            g.setColor(color3);
          
          
            g.fillOval(x, y, getIconWidth(), getIconHeight());
        }
      
        @Override public int getIconWidth()
        { return 30; }
      
        @Override public int getIconHeight()
        { return 30; }
    };
Die Fehlermeldung sagt doch schon alles. Du versuchst, ienen Enum-Wert dort zu übergeben, wo eine Farbe erwartet wird.
Der Farbwert ist eine Eigenschaft des Enums, frag ihn also beim Methodenaufruf ab.
 

volcanos

Bekanntes Mitglied
Wusste nicht dass man das so
Color pink = CustomColorEnum.PINK.getRGB();
schreibt.

Java:
static Icon icon = new Icon()
    {      
        Color color = CustomColorEnum.PINK.getRGB();
       
        @Override public void paintIcon(Component c, Graphics g, int x, int y)
        {
            // farbN = farbe.stringToColor(input);
            // g.setColor(farbN);
           
            g.setColor(color);                                  
            g.fillOval(x, y, getIconWidth(), getIconHeight());
        }
       
        @Override public int getIconWidth()
        { return 30; }
       
        @Override public int getIconHeight()
        { return 30; }
    };

Trotzdem kommt logischerweise jetzt nur mehr pink heraus.
Color color = CustomColorEnum.color.getRGB();
Color color = CustomColorEnum.input.getRGB();
Color color = CustomColorEnum.selection.getRGB();
 

KonradN

Super-Moderator
Mitarbeiter
??? Was machst Du da?

Das CustomColor(Enum) ist nur ein reines enum. Da sollte also nichts mit color, input oder selection drin sein sondern nur die Enum wie ich diese gezeigt hatte. (Das Enum am Ende kann eigentlich weg. Das ist nur benutzt worden, da es auch noch ein CutomColorMap geben sollte.)

Und das Enum, das ich gezeigt habe, hat eine Methode: getColor(). Und mit dieser hast du die Color bekommen.

Und das mit dem dem Icon wäre dann eine Klasse, die so aufgebaut sein könnte:
Java:
public class ColorIcon extends Icon {
    static Icon icon = new Icon()
    {     
        Color color;
        
        public ColorIcon(CustomColorEnum customColor) {
            this.color = customColor.getColor();
        }
      
        @Override public void paintIcon(Component c, Graphics g, int x, int y)
        {
            // farbN = farbe.stringToColor(input);
            // g.setColor(farbN);
          
            g.setColor(color);                                 
            g.fillOval(x, y, getIconWidth(), getIconHeight());
        }
      
        @Override public int getIconWidth()
        { return 30; }

        @Override public int getIconHeight()
        { return 30; }
}

Und dann hätte man etwas wie:
Java:
    public static void main(String... args) {         
      
        CustomColorEnum selection = null;
      
        while (selection == null)
        {
               input = JOptionPane.showInputDialog("Farbe des Tages eigeben:");
              
            try {
                selection = CustomColorEnum.valueOf(input.trim().toUpperCase());
            }  catch (Exception e) {
                colorNotFound();
            }
        } 
      
        if (selection != null) {
            colorFound(selection);
        } else {
            colorNotFound();
        }
    } 
  
  
    public static void colorFound(CustomColorEnum color) {
        JOptionPane.showConfirmDialog(null, "ist die Farbe des Tages.", "Ausgabe-Fenster",  2, 2, new ColorIcon(color));
    }
  
  
    public static void colorNotFound() {
        JOptionPane.showConfirmDialog(null, "Farbe nicht gefunden !!!", "Ausgabe-Fenster", 2);
    }

Damit hat man auch kein Switch mehr. Die Variable selection sollte man noch umbennen in selectedColor oder so. Aber der Code ist komplett im Forum geschrieben worden und daher ohne Refactoring Möglichkeiten und auch ohne Syntax Prüfung. Es sollte aber klar werden, wie man sowas aufbauen könnte.
 

volcanos

Bekanntes Mitglied
Die SuperKlasse Icon scheint es bei mir nicht zu geben

public class ColorIcon extends Icon

The type Icon cannot be the superclass of ColorIcon; a superclass must be a class

Und bei
public ColorIcon(CustomColorEnum customColor) {
this.color = customColor.getColor();
}
wird ein Return-Type gewünscht.
Normalerweise sollte customColor oder color funktionieren. Geht aber nicht.
 

volcanos

Bekanntes Mitglied
Ich habe dein Programm trotzdem etwas umschreiben müssen:

1) public class ColorIcon extends Icon -> gibt es bei mir (eclipse) nicht

was es aber bei mir (eclipse) gibt ist:

public class ColorIcon implements Icon

2) wenn ich es mit einer eigenen Methode in der ColorIcon-Klasse mit
static Icon icon = new Icon() { ... ... ... };
-> jetzt /* */
mache ...
dann funktioniert das ganze Programm nicht.
Ich muss es in der Klasse selbst machen (ohne interne icon-Methode).

3) Den Konstruktor hat innerhalb der Methode icon nicht funktioniert -> wollte einen return-Wert ???
Der ist jetzt direkt in der Klasse. (Prinzipiell hat der Konstruktor bereits einen Rückgabewert -> ein Objekt der Klasse)

4) ist eher unwesentlich: vorher hatte ich nur die main-Klasse. Jetzt ->
ColorIcon.java -> eigene Class
Main.java -> eigene Class

Aber trotzdem muss man sagen. Den Hauptanteil für MAGENTA, PINK und CYAN
hast Du (Konrad) gemacht.

Danke nochmals.
 

volcanos

Bekanntes Mitglied
So sieht es jetzt aus:

ColorIcon.java

Java:
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import javax.swing.Icon;

public class ColorIcon implements Icon
{
    static Color color;
    
    public ColorIcon(CustomColorEnum customColor)
    { this.color = customColor.getRGB(); }   
    
    public enum CustomColorEnum
    {
        RED(Color.RED),
        GREEN(Color.GREEN),
        SPECIAL_BLUE(new Color(50, 50, 150)),
        YELLOW(Color.YELLOW),
        ORANGE(Color.ORANGE),       
        BLACK(Color.BLACK),
        GRAY(Color.GRAY),
        CYAN(Color.CYAN),
        PINK(Color.PINK),
        MAGENTA(Color.MAGENTA);

        private Color color;

        CustomColorEnum(Color color)
        { this.color = color; }

        public Color getRGB()
        { return color; }
    }   
    
    /*
    static Icon icon = new Icon()
    {       
        @Override
        public void paintIcon(Component c, Graphics g, int x, int y)
        {
            // farbN = farbe.stringToColor(input);
            // g.setColor(farbN);
          
            g.setColor(color);                                 
            g.fillOval(x, y, getIconWidth(), getIconHeight());
        }
      
        @Override
        public int getIconWidth()
        { return 30; }

        @Override
        public int getIconHeight()
        { return 30; }
    };
    */

    @Override
    public void paintIcon(Component c, Graphics g, int x, int y)
    {
        g.setColor(color);                                 
        g.fillOval(x, y, getIconWidth(), getIconHeight());       
    }

    @Override
    public int getIconWidth()
    { return 30; }
    
    @Override
    public int getIconHeight()
    { return 30; }       
}


Main.Java

Code:
import javax.swing.JOptionPane;

public class Main
{
    static String input = "";
    static ColorIcon.CustomColorEnum selection = null;
    
    public static void main(String[] args)
    {         
        while (selection == null)
        {
           input = JOptionPane.showInputDialog("Farbe des Tages eigeben:");
              
            try { selection = ColorIcon.CustomColorEnum.valueOf(input.trim().toUpperCase()); } 
            catch (Exception e) { colorNotFound(); }
        }
      
        if (selection != null)
        { colorFound(selection); }
        else
        { colorNotFound(); }
    }
 
 
    public static void colorFound(ColorIcon.CustomColorEnum color)
    { JOptionPane.showConfirmDialog(null, "ist die Farbe des Tages.", "Ausgabe-Fenster",  2, 2,
                                    new ColorIcon(color));
    }
 
 
    public static void colorNotFound()
    { JOptionPane.showConfirmDialog(null, "Farbe nicht gefunden !!!", "Ausgabe-Fenster", 2); }

}
 

KonradN

Super-Moderator
Mitarbeiter
Ja, Icon ist ein Interface und keine Klasse. Das ist halt, wenn man so Dinge schnell im Forum schreibt.

Aber wieso packst Du die enum in eine Klasse? Denn sie ist ja ganz offensichtlich auch außerhalb interessant und ist nicht intern für das ColorIcon. Beim zweiten Blick ist es sogar so, dass ColorIcon gar keine Abhängig zu der CustomColorEnum braucht (Und man einfach im Konstruktor direkt die Color übergibt. Das dies aus dem speziellen Enum kommt ist eine Business Logik, die für dieses Element uninteressant ist).

Und das getRGB leuchtet mir nicht ein. Es wird ein Color zurück gegeben und das enthält mehr als nur die RGB Werte (Den Alpha Wert). Daher verstehe ich dieses Rename nicht.

Aber das ist alles erst einmal egal - ich denke, ich konnte Mittel und Wege deutlich machen, mit denen man hier bei gewissen Problemen agieren kann um diese zu entschärfen.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
X Enum Abfrage ohne if, for, while oder switch Java Basics - Anfänger-Themen 21
U Warum kann ich die Methode in der ENUM Klasse nicht aufrufen? Und warum geht die Switch nicht? Java Basics - Anfänger-Themen 8
J enum switch Java Basics - Anfänger-Themen 5
P Enum oder normale Klasse? Java Basics - Anfänger-Themen 10
D Frage bzgl. Enum-Handhabung Java Basics - Anfänger-Themen 16
S Java Enum Java Basics - Anfänger-Themen 2
I Validation, ob String ein Wert aus einem Enum enthält Java Basics - Anfänger-Themen 3
V Enum Java Basics - Anfänger-Themen 1
C Farben als Enum Java Basics - Anfänger-Themen 3
N enum Attribut von Objekten einer Hashmap ausgeben Java Basics - Anfänger-Themen 6
I JAXB und Enum Java Basics - Anfänger-Themen 7
M Enum-Variable HashMap zuweisen Java Basics - Anfänger-Themen 5
B Enum innerhalb einer Klasse / anderes Konzept Java Basics - Anfänger-Themen 8
N Enum Typen, was passiert intern mit ihnen? Java Basics - Anfänger-Themen 2
A enum Java Basics - Anfänger-Themen 6
O Enum Array Rekursiv abarbeiten Java Basics - Anfänger-Themen 44
B ENUM to List<String> konvertieren Java Basics - Anfänger-Themen 2
N Java Enum converter Methode Java Basics - Anfänger-Themen 5
F Enum von Ländern Java Basics - Anfänger-Themen 8
J Klassen Enum als Informationsträger Java Basics - Anfänger-Themen 10
T Datentypen enum static Chaos (blutiger anfänger) Java Basics - Anfänger-Themen 5
R Enum ist das gleiche wie? Java Basics - Anfänger-Themen 15
P Klassen Richtige Anwendung einer Enum-Klasse Java Basics - Anfänger-Themen 11
E Datentypen Problem beim Speichern von enum. Java Basics - Anfänger-Themen 10
J Compiler-Fehler class interface or enum expected Java Basics - Anfänger-Themen 1
E Objektvergleich Enum Java Basics - Anfänger-Themen 7
kilopack15 Euromünzen in enum als Liste ausgeben Java Basics - Anfänger-Themen 11
N Enum als generischer Typ Java Basics - Anfänger-Themen 4
H Datentypen Fehler bei Verwendung von enum Java Basics - Anfänger-Themen 9
lBlKha0s Fehlermeldung : class interface or enum expected Java Basics - Anfänger-Themen 9
T error: class, interface, or enum expected Java Basics - Anfänger-Themen 5
S Menüauswahl per Enum Java Basics - Anfänger-Themen 12
F Enum via String definieren Java Basics - Anfänger-Themen 2
L Compiler-Fehler error: class, interface or enum expected Java Basics - Anfänger-Themen 2
M java.lang.Enum.valueOf(Unknown Source) Java Basics - Anfänger-Themen 2
M Enum-Variabel-Abfrage funktioniert nicht? Java Basics - Anfänger-Themen 2
P Fallunterscheidung mit Überprüfung (enum) Java Basics - Anfänger-Themen 11
H enum Type Java Basics - Anfänger-Themen 6
F Operatoren Enum aus Textdabei laden Java Basics - Anfänger-Themen 3
P enum: cannot be resolved to a type Java Basics - Anfänger-Themen 2
kaoZ Variablen Konstantensammlung vs. Enum Java Basics - Anfänger-Themen 9
H Enum außerhalb einer Klasse? Java Basics - Anfänger-Themen 2
K OOP Aufzählungstypen! enum Currency!!! Java Basics - Anfänger-Themen 5
F ENUM als Variable Java Basics - Anfänger-Themen 4
M Enum: Zugriff auf Konstanten Java Basics - Anfänger-Themen 7
W Enum Konstruktor Type Java Basics - Anfänger-Themen 2
A Erste Schritte ENUM - Werte zurückgeben Java Basics - Anfänger-Themen 5
D Enum als Parameter Java Basics - Anfänger-Themen 6
B Variablen Instanz von Enum zur Laufzeit erstellen und zuweisen Java Basics - Anfänger-Themen 2
B Datentypen Enum vererben/gruppieren? Java Basics - Anfänger-Themen 6
F Datentypen enum Java Basics - Anfänger-Themen 5
J Enum zählen Java Basics - Anfänger-Themen 8
D Einlesen eines Enum-Wertes per console Java Basics - Anfänger-Themen 3
K String mit ENUM vergleichen? Java Basics - Anfänger-Themen 6
N enum vergleiche Klammern? Java Basics - Anfänger-Themen 5
J public enum? in Java Java Basics - Anfänger-Themen 9
D Erste Schritte Enum - das unbekannte Wesen Java Basics - Anfänger-Themen 3
Y ENUM auslesen (Name des ENUM als Variable) Java Basics - Anfänger-Themen 4
P Compiler-Fehler "class, interface, or enum expected" Java Basics - Anfänger-Themen 5
K class, interface or enum expected Java Basics - Anfänger-Themen 14
pg1337 enum-Aufgabe Java Basics - Anfänger-Themen 5
N was sagt enum aus? Java Basics - Anfänger-Themen 3
S Methoden Enum Parameter in Methode Java Basics - Anfänger-Themen 7
G Datentypen enum Frage Java Basics - Anfänger-Themen 3
R Probleme mit Enum Java Basics - Anfänger-Themen 10
B Enum: Instanzen Java Basics - Anfänger-Themen 10
B Generic? Enum - So lösbar? Java Basics - Anfänger-Themen 8
T class, interface, or enum expected Java Basics - Anfänger-Themen 2
M Vererbung Enum Vererbung/Polymorphie Java Basics - Anfänger-Themen 2
P Enum Attribut in Konstruktoren Java Basics - Anfänger-Themen 10
4 Enum Problem Java Basics - Anfänger-Themen 2
turmaline Bindestrich in enum? Java Basics - Anfänger-Themen 5
T Enum - Key als Value ermitteln Java Basics - Anfänger-Themen 7
X enum Fehlermeldung "The public type Day must be defined in its own file" Java Basics - Anfänger-Themen 8
T ist enum.ordinal keine Konstante? Java Basics - Anfänger-Themen 7
R State machine mit enum Java Basics - Anfänger-Themen 9
L enum aus Integer umwandeln Java Basics - Anfänger-Themen 3
C Klasseninstanzierung mit enum-Parameter erzwingen Java Basics - Anfänger-Themen 2
I Enum in String Java Basics - Anfänger-Themen 4
N enum richtig verwenden Java Basics - Anfänger-Themen 5
M for(Enum..., ButtonGroup.getElements()... Java Basics - Anfänger-Themen 3
StrikeTom Fragen zu enum Java Basics - Anfänger-Themen 4
A Was ist performanter für Konstanten, enum oder static variablen Java Basics - Anfänger-Themen 5
L String zu Enum parsen Java Basics - Anfänger-Themen 8
J Datentypen Array in enum, ?? Wozu ?? Java Basics - Anfänger-Themen 3
S OOP Durch ein Enum iterieren... Java Basics - Anfänger-Themen 47
K Datentypen enum und liste Java Basics - Anfänger-Themen 7
S String - Enum Java Basics - Anfänger-Themen 3
H Eine enum switchen? Java Basics - Anfänger-Themen 7
G enum für Typsicherheit Java Basics - Anfänger-Themen 9
J class, interface, or enum expected - finde Fehler nicht. Java Basics - Anfänger-Themen 4
J OOP enum Java Basics - Anfänger-Themen 2
O Problem (Enum) Java Basics - Anfänger-Themen 14
S Enum als Index Java Basics - Anfänger-Themen 5
H Enum --> int ?? Java Basics - Anfänger-Themen 3
tanja enum in java Java Basics - Anfänger-Themen 3
D class, interface or enum expected Java Basics - Anfänger-Themen 2
A OOP Übergabe eines Wertes an den enum Konstruktor Java Basics - Anfänger-Themen 12
T Simple Enum Fragen Java Basics - Anfänger-Themen 6
J class, interface, or enum expected Java Basics - Anfänger-Themen 4

Ähnliche Java Themen

Neue Themen


Oben