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?