The uses keyword in Java is part of the Java Platform Module System (JPMS) introduced in Java 9. It is used within a module declaration to specify that the module depends on a service interface. This keyword indicates that the module will use a service provider that implements the specified service interface.
Table of Contents
- Introduction
usesKeyword Syntax- Understanding
uses - Examples
- Declaring a Module that Uses a Service
- Providing a Service
- Using the Service
- Real-World Use Case
- Conclusion
Introduction
In Java’s module system, services and service providers can be declared and consumed using the uses and provides keywords. The uses keyword declares a dependency on a service, allowing the module to discover and use implementations of the service interface at runtime.
uses Keyword Syntax
The syntax for using the uses keyword in a module-info.java file is as follows:
module moduleName {
uses fully.qualified.ServiceInterfaceName;
}
Example:
module com.example.myapp {
uses com.example.myapp.api.MyService;
}
Understanding uses
Key Points:
- Service Interface: The
useskeyword specifies that the module depends on a service interface. - Service Loader: At runtime, the
ServiceLoaderclass can be used to locate and load implementations of the service. - Decoupling: This mechanism helps decouple the service provider and the consumer, promoting modular design.
Examples
Declaring a Module that Uses a Service
A module that uses a service interface.
Example
// File: src/com.example.myapp/module-info.java
module com.example.myapp {
uses com.example.myapp.api.MyService;
}
Providing a Service
A module that provides an implementation for the service interface.
Example
// File: src/com.example.provider/module-info.java
module com.example.provider {
requires com.example.myapp;
provides com.example.myapp.api.MyService with com.example.provider.MyServiceImpl;
}
// File: src/com.example.myapp/api/MyService.java
package com.example.myapp.api;
public interface MyService {
void performService();
}
// File: src/com.example.provider/MyServiceImpl.java
package com.example.provider;
import com.example.myapp.api.MyService;
public class MyServiceImpl implements MyService {
@Override
public void performService() {
System.out.println("Service performed by MyServiceImpl");
}
}
Using the Service
Using the ServiceLoader to load and use the service implementation.
Example
// File: src/com.example.myapp/Main.java
package com.example.myapp;
import com.example.myapp.api.MyService;
import java.util.ServiceLoader;
public class Main {
public static void main(String[] args) {
ServiceLoader<MyService> serviceLoader = ServiceLoader.load(MyService.class);
for (MyService service : serviceLoader) {
service.performService();
}
}
}
Output:
Service performed by MyServiceImpl
Real-World Use Case
Plugin System
In real-world applications, the uses and provides keywords can be used to create a plugin system where the main application can discover and use plugins (service providers) at runtime without knowing the implementation details.
Example
// Main application module definition (src/com.example.app/module-info.java)
module com.example.app {
uses com.example.plugin.api.Plugin;
}
// Plugin API module definition (src/com.example.plugin/module-info.java)
module com.example.plugin {
exports com.example.plugin.api;
}
// Plugin provider module definition (src/com.example.plugin.impl/module-info.java)
module com.example.plugin.impl {
requires com.example.plugin;
provides com.example.plugin.api.Plugin with com.example.plugin.impl.PluginImpl;
}
// Plugin interface (src/com.example.plugin/api/Plugin.java)
package com.example.plugin.api;
public interface Plugin {
void execute();
}
// Plugin implementation (src/com.example.plugin.impl/PluginImpl.java)
package com.example.plugin.impl;
import com.example.plugin.api.Plugin;
public class PluginImpl implements Plugin {
@Override
public void execute() {
System.out.println("Plugin executed by PluginImpl");
}
}
// Main application (src/com.example.app/Main.java)
package com.example.app;
import com.example.plugin.api.Plugin;
import java.util.ServiceLoader;
public class Main {
public static void main(String[] args) {
ServiceLoader<Plugin> serviceLoader = ServiceLoader.load(Plugin.class);
for (Plugin plugin : serviceLoader) {
plugin.execute();
}
}
}
Output:
Plugin executed by PluginImpl
Conclusion
The uses keyword in Java’s module system is used for specifying service dependencies in a decoupled and modular way. By declaring a dependency on a service interface, modules can dynamically discover and use service implementations at runtime, promoting a flexible and extensible architecture. Understanding and using the uses keyword effectively is essential for developing modular and maintainable Java applications.