Java ServiceLoader调用报错NoSuchElementException,META-INF/services配置问题求助
问题排查及解决方案
核心原因(最常见):缺少SPI配置文件
Java的ServiceLoader基于SPI(服务提供者接口)机制实现,必须手动创建配置文件声明接口的实现类才能正常加载,配置步骤如下:
- 在项目的
resources目录下新建层级目录META-INF/services - 在该目录下新建文件,文件名必须为接口的全限定名,你当前场景的文件名是
ServiceLoader_.SL.Account - 打开新建的文件,写入实现类的全限定名:
ServiceLoader_.SL.Message,如果有多个实现类每行写一个即可。
其他可能导致报错的问题点
- 接口访问修饰符问题:你当前的
Account接口没有加public修饰符,属于包级私有访问权限,跨包使用或者类加载器隔离场景下会导致加载失败,建议修改为public interface Account - 迭代器使用逻辑错误:你代码中每次调用
ac.iterator()都会生成一个新的迭代器实例,且没有先判断元素存在就直接调用next()方法,很容易触发异常,修改后的主类参考代码如下:
package ServiceLoader_.SL; import java.util.Iterator; import java.util.ServiceLoader; public class main { public static void main(String[] args) { ServiceLoader<Account> ac = ServiceLoader.load(Account.class); Iterator<Account> iterator = ac.iterator(); // 先判断是否存在元素再调用next,避免NoSuchElementException if(iterator.hasNext()){ Account ab = iterator.next(); System.out.println(ab.getMessage()); System.out.println("hay^"); } } }
- 实现类缺少无参构造方法:你当前的
Message类默认生成无参构造符合要求,如果后续自定义了有参构造,需要手动补充无参构造,否则ServiceLoader实例化实现类会失败。
内容的提问来源于stack exchange,提问作者M Nasir Baloch
相关产品推荐
相关产品推荐

