The ServiceLoader is a simple and easy to use built-in mechanism for dynamic loading of interface implementations. With the service loader - providing means for instantation (but not the wiring) - a simple dependency injection mechanism can be built in Java SE. With the ServiceLoader interface and implementation separation becomes natural and programs can be conveniently extended. Actually a lot of Java API are implented based on the ServiceLoader

The basic concepts are

Lets start with the interface and put it in a jar, named for example accounting-api.jar

package example;

public interface AccountingService {

  long getBalance();
}

Now we provide an implementation of that service in a jar named accounting-impl.jar, containing an implementation of the service

package example.impl;
import example.AccountingService;

public interface DefaultAccountingService implements AccouningService {

  public long getBalance() {
    return balanceFromDB();
  }

  private long balanceFromDB(){
    ...
  }
}

further, the accounting-impl.jar contains a file declaring that this jar provides an implementation of AccountingService. The file has to have a path starting with META-INF/services/ and must have the same name as the fully-qualified name of the interface:

The content of the file is the fully-qualfified name of the implementation:

example.impl.DefaultAccountingService

Given both jars are in the classpath of the program, that consumes the AccountingService, an instance of the Service can be obtained by using the ServiceLauncher

ServiceLoader<AccountingService> loader = ServiceLoader.load(AccountingService.class)
AccountingService service = loader.next();
long balance = service.getBalance();

As the ServiceLoader is an Iterable, it supports multiple implementation providers, where the program may choose from:

ServiceLoader<AccountingService> loader = ServiceLoader.load(AccountingService.class)
for(AccountingService service : loader) {
   //...
}

Note that when invoking next() a new instance will allways be created. If you want to re-use an instance, you have to use the iterator() method of the ServiceLoader or the for-each loop as shown above.