petek, 10. september 2010

Java in String switch

Končno mi je uspelo usposobiti tudi barvanje kode tukaj na blogu tako, da bom lahko lepše objavljal izrezke kode. Pa poskusimo.
Kot je znano Java 6 ne omogoča uporabe nizov (Stringov) v switch stavkih. Omogoča samo primerjavo Integer-jev, char-ov in enum-ov. S slednjimi pa si lahko pomagamo pri implementaciji želenega switch stavka za String-e. JDK7 sicer obljublja to že nekaj časa ampak bomo po vsej verjetnosti zadevo ogledali šele nekje v sredini leta 2011 (plan B). Ta JDK izdaja pa bo vsebovala samo del predvidenih specifikacij za JDK7. Kompleten paket je predviden za izdajo nekje ob koncu leta 2012 kot JDK8 (plan A).
No pa se vrnimo k namešmu problemu. Recimo, da hočemo implementirati switch stavek, ki nam bo vračal vrednosti za poljubne lastnosti grafičnih komponent. Zaradi lepše implementacije bomo te vrednosti vračali kar kot String-e.
Kot rečeno si bomo pomagali z naštevnimi tipi (enumi). Naštejmo imena komponent (velike črke) s katerimi bomo kasneje preverjali za kateri tip komponente gre. Najlažje s kratkimi imeni. Dodajmo pa še nek tip, ki nam bo predstavljal vse ostalo kar ne bo možno kasneje pretvorit.
/*
     * Enum with our simple class names
     */
    private enum ClassesEnum {
        TEXTFIELD, JCOMBOBOX, JTEXTAREA, JLABEL, JLIST, OTHER
    };
Zdaj pa definirajmo še našo metodo, ki bo vračala vrednost glede na tip komponente. Kratko ime razreda našega argumenta (komponente) pretvorimo v ustrezen naštevni tip, ki smo ga prej definirali. Seveda moramo ta imena v naštevnem tipu natančno definirati, mi smo jih z velikimi črkami.
/*
     * Returns value of given component
     */
    private static String getValue(Component component) {
        //get simple class name
        String className = component.getClass().getSimpleName().toUpperCase();
        //try to convert into enum
        try {
            ClassesEnum.valueOf(className);
        } catch (IllegalArgumentException e) {
            className = ClassesEnum.OTHER.name();
        }
        //convert to enum an get related property
        switch (ClassesEnum.valueOf(className)) {
            case JTextArea:
                return ((JTextArea) component).getText();
            case TextField:
                return ((TextField) component).getText();
            case JComboBox:
                return ((JComboBox) component).getSelectedItem().toString();
            case JLabel:
                return ((JLabel) component).getText();
            case JList:
                return ((JList) component).getSelectedValue().toString();
            default:
                return "Component is not defined!";
        }
    }
No zdaj pa še preverimo našo metodo z različnimi argumenti.
//Our test method
public static void main(String[] args) {
         // Test data
        JLabel label = new JLabel("This is label!");
        TextField textField = new TextField("This is text field!");
        JTextArea textArea = new JTextArea("This is text area!");
        JComboBox jComboBox = new JComboBox(
                    new Object[]{"This is selected item in JComboBox!"});
        jComboBox.setSelectedIndex(0);
        JList list = new JList(new Object[]{"This is selected item in JList!"});
        list.setSelectedIndex(0);
        Button button = new Button("Not defined!");

        /*
         * Test output
         */
        System.out.println(getValue(label));
        System.out.println(getValue(textField));
        System.out.println(getValue(textArea));
        System.out.println(getValue(jComboBox));
        System.out.println(getValue(list));
        System.out.println(getValue(button));
    }
To je trenutno najboljša rešitev, če ne želimo čakat na JDK7. Omenimo pa lahko še eno rešititev.
HashMap<String, Integer> map = new HashMap<String, Integer>() {
            {
                put("JTEXTAREA", 0);
                put("TEXTFIELD", 1);
                //...
            }
        };
        String testString = textArea.getClass().getSimpleName().toUpperCase();
        switch ((Integer) map.get(testString)) {
            case 0:
                System.out.println("This is text area!");
        }
Pa še končni rezultat.

Ni komentarjev:

Objavite komentar