Nichts besonderes und nichts großes und auch kein wirklicher Rant, ich hatte heute nur ein wenig Spaß mit static im Java-Code. Es war auch nichts bösartiges und es war eher eine Erkenntnis als “drüber aufregen”.

Ich hab gerade eine Klasse geschrieben gehabt, die verschiedene Konfigurationsoptionen beinhaltet. Damit es ein wenig strukturiert ist, habe ich sie entsprechend gebündelt und in statische Unterklassen gepackt, in etwa so (nur vom Prinzip wegen Originalcode copyrights):

Einfach als Datenklassen nehmen wir das hier noch dabei:

public interface ConfigHolder {
    public static final ConfigHolder configHolder = new ConfigHolderImpl();

    void addOverride(String shop, ConfigOption showAuthor, boolean value);

    boolean getConfig(String shop, ConfigOption option);
}

public class ConfigOption {
    String key;
    boolean value;

    public ConfigOption(String key, boolean value) {
        this.key = key;
        this.value = value;
    }
}

Und die geplante Klasse mit den ganzen Konfigurationen war dann das hier:

public class Config {
    public static class Book {
        public static final ConfigOption SHOW_COVER = new ConfigOption("book:show-cover", true);
        public static final ConfigOption SHOW_AUTHOR = new ConfigOption("book:show-author", true);
    }

    public static class Author {
        public static final ConfigOption SHOW_AGE = new ConfigOption("author:show-age", true);
        public static final ConfigOption SHOW_KIDS = new ConfigOption("author:show-kids", true);
    }

    static {
        ConfigHolder.configHolder.addOverride("bookshopA", Book.SHOW_AUTHOR, false);
        ConfigHolder.configHolder.addOverride("bookshopB", Book.SHOW_COVER, false);
    }
}

Aber die overrides wurden nicht eingetragen. Der static Block wurde nicht ausgeführt, weil ich zwar im Code auf die Konstanten in den Unterklassen zugreife, aber eben nichts in der eigentlichen Klasse mache. Genauso würde der static Block auch bei diesem Code nicht ausgeführt:

public class Constants {
    public static final int PORT = 9000;

    static{
        System.out.println("Default-Port: " + PORT);
    }
}

Dadurch, dass PORT bereits beim compilen eine Konstante ist wird sie dort eingesetzt, wo sie genutzt wird, anstatt die Klasse zu laden (je nachdem, wie weit der Compiler optimiert usw). Anders ist es zum Beispiel bei dem nachfolgenden Code, bei dem erst zur Laufzeit der Wert gesetzt wird:

public class Constants {
    public static final int PORT = (int)(Math.random() * 10000);

    static {
        System.out.println("Default-Port: " + PORT);
    }
}

Ergebnis bei meinem Konfigurationscode für Büchergeschäfte - der im echten Code noch ein wenig anders aussieht und vor allem nichts mit Büchern zu tun hat - ist dann letztendlich dafür zu sorgen, dass in jeder Unterklasse ein static Block eingebaut ist, der die Overrides einträgt:

public class Config {

    public static ConfigHolder configHolder;

    public static class Book {
        public static final ConfigOption SHOW_COVER = new ConfigOption("book:show-cover", true);
        public static final ConfigOption SHOW_AUTHOR = new ConfigOption("book:show-author", true);

        static {
            init();
        }
    }

    public static class Author {
        public static final ConfigOption SHOW_AGE = new ConfigOption("author:show-age", true);
        public static final ConfigOption SHOW_KIDS = new ConfigOption("author:show-kids", true);

        static {
            init();
        }
    }

    private static boolean initialized = false;

    private synchronized static void init() {
        if (initialized) {
            return;
        }
        initialized = true;
        configHolder.addOverride("bookshopA", Book.SHOW_AUTHOR, false);
        configHolder.addOverride("bookshopB", Book.SHOW_COVER, false);
    }
}

In diesem Sinne: Happy Coding :D