If you have an interface or abstract class defined in some jar
package whatever.project;
public interface DoesThing {
void doThing();
}
And in another jar you have one or more implementations of that interface which has a zero argument constructor
package something.other;
public final class DoesThingImpl implements DoesThing {
@Override
public void doThing() {
System.out.println("I implemented this in a certain way");
}
}
as well as a file in that jar with the interface name under META-INF/services
META-INF/services/whatever.project,DoesThing
which has a line that has the name of the implementing class
something.other.DoesThingImpl
Then you can obtain an implementation of that interface via the service loader mechanism
= ServiceLoader.load(DoesThing.class);
var loader for (var thingDoer : loader) {
.doThing();
thingDoer}
This is some really core magic and is how most of the projects that want you to just add dependencies to get functionality - like slf4j, jdbc, twelvemonkeys, etc - use to do their thing