Morning,

After having updated to JDK 26, I have some feedback regarding JEP 526: 
specifically the removal of the "low[er]-level methods".

My particular use case is creating mods for a popular block game, which has 
quite a few competing mod loaders. These mod loaders generally require you to 
specify a class that extend or implement some kind of interface to handle 
lifecycle events and so on.

Mod developers who wish to support multiple mod loaders typically have a 
"common" project, which defines the mod's behaviour, and then one or more 
platform-implementation projects which bridge the gap between common's APIs and 
the platform's (such as how to implement the registration of key bindings).

What mod developers typically do is define an abstract singleton which the 
platform-impl projects implement and set. Which can look something like the 
following:

    public abstract class AbstractExampleMod {
        protected static AbstractExampleMod instance;
        public static AbstractExampleMod getInstance() {
            return instance;
        }

        protected void handleEnable() {
            this.registerKeyBinding(new KeyBinding(Key.R));
        }

        // Example platform-specific method
        protected abstract void registerKeyBinding(KeyBinding keyBinding);
    }

With a platform-impl class resembling the following:

    public class PlatformExampleMod extends AbstractExampleMod implements 
IPlatformMod {
        public PlatformExampleMod() {
            if (instance != null) throw new IllegalStateException("instance is 
already set!");
            instance = this;
        }

        @Override // from IPlatformMod
        public void onModEnable() {
            this.handleEnable();
        }

        @Override // from AbstractExampleMod
        protected void registerKeyBinding(KeyBinding keyBinding) {
            Platform.registerKeyBinding(keyBinding);
        }
    }

Unfortunately, most of the mod loaders do not let you control how or under what 
circumstances your mod class is constructed: setting the instance occurs once 
you already have the instance. This was not a problem as StableValue had 
setOrThrow/trySet, which let you define a placeholder StableValue to set later. 
This allowed me to update my mods to take advantage of StableValue while only 
making minor code changes, eg:

    public abstract class AbstractExampleMod {
        public static final StableValue<AbstractExampleMod> instance = 
StableValue.of();
        // etc
    }

    public class PlatformExampleMod extends AbstractExampleMod implements 
IPlatformMod {
        public PlatformExampleMod() {
            instance.setOrThrow(this);
        }
        // etc
    }

While this may seem like a niche use case, this could also apply to values set 
within a main method, such as setting a particular implementation of an 
interface to a static constant based on a command-line argument. However, with 
JEP 526 and the removal of the these methods, there seems to be no other option 
but to return to the non-final field strategy (or otherwise remaining on JDK 25 
preview), which while not the end of the world, is nonetheless rather 
unfortunate in my opinion. Would it be at all possible to reinstate these 
methods?

Reply via email to