调用com.google.common.collect.Lists.cartesianProduct()报NoSuchMethodError的排查
我尝试调用com.google.common.collect.Lists.cartesianProduct(...),但一直报NoSuchMethodError。不管是接受List of Lists作为参数的版本,还是接受List数组作为参数的版本,只要能正常运行就行。请问我哪里操作错了?
尝试1:
import java.util.List; import com.google.common.collect.Lists; ... List<List<MyClass>> candidates = new ArrayList<>(); ... //填充List of Lists List<List<MyClass>> product = Lists.cartesianProduct(candidates);
结果:java.lang.NoSuchMethodError: 'java.util.List com.google.common.collect.Lists.cartesianProduct(java.util.List)'
调试器评估结果:Type does not implement selector cartesianProduct and signature (Ljava/util/List;)Ljava/util/List;
尝试2:
List<List<MyClass>> candidates = new ArrayList<>(); ... //填充List of Lists List<MyClass>[] candidatesArray = candidates.toArray(new List[0]); List<List<MyClass>> product = Lists.cartesianProduct(candidates);
结果:java.lang.NoSuchMethodError: 'java.util.List com.google.common.collect.Lists.cartesianProduct(java.util.List[])'
调试器评估结果:Type does not implement selector cartesianProduct and signature ([Ljava/util/List;)Ljava/util/List;
尝试3:
List<List<MyClass>> candidates = new ArrayList<>(); ... //填充List of Lists List<List<MyClass>> product = Lists.cartesianProduct(candidates.get(0), candidates.get(1));
结果:java.lang.NoSuchMethodError: 'java.util.List com.google.common.collect.Lists.cartesianProduct(java.util.List[])'
调试器评估结果:Type does not implement selector cartesianProduct and signature ([Ljava/util/List;)Ljava/util/List;
问题原因
NoSuchMethodError本质是编译时依赖的Guava版本和运行时使用的版本不一致,或者当前使用的Guava版本太老,没有你调用的方法签名:
Lists.cartesianProduct(List<List<?>>)这个接受List of Lists的方法是Guava 19.0版本才新增的;- 接受可变参数(如
Lists.cartesianProduct(List<?>, List<?>))的版本虽然在更早版本就存在,但如果运行时的Guava版本过低,也会出现方法找不到的情况; - 泛型数组的类型擦除问题也可能导致签名不匹配,但核心还是版本不一致。
解决方案
- 统一Guava版本:确保项目编译和运行时使用同一个足够新的Guava版本(至少19.0及以上,推荐用最新稳定版)。
- Maven示例(在pom.xml中添加):
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>32.1.3-jre</version> <!-- 替换为最新稳定版 --> </dependency> - Gradle示例(在build.gradle中添加):
implementation 'com.google.guava:guava:32.1.3-jre'
- Maven示例(在pom.xml中添加):
- 排查依赖冲突:检查项目依赖树,排除其他依赖间接引入的旧版Guava,确保只有指定的新版本生效。
- 正确调用方法:
- 如果用的是Guava 19.0+,直接用
Lists.cartesianProduct(candidates)(List of Lists参数)即可; - 如果用的是更老的版本,改用可变参数形式:
Lists.cartesianProduct(candidates.get(0), candidates.get(1), ...),或者把List转成List<?>[]数组后传入,但要注意泛型类型匹配。
- 如果用的是Guava 19.0+,直接用
内容的提问来源于stack exchange,提问作者Joe7

