Java 8中直接创建SFunction数组报错的原因及解决方法咨询
函数式接口数组初始化的编译问题分析与解决
代码背景
定义继承自Function并实现Serializable的函数式接口:
@FunctionalInterface public interface SFunction<T, R> extends Function<T, R>, Serializable { }
定义实体类FrameModel:
@Getter @Setter public class FrameModel { // 枚举类型 private FrameTypeEnum frameType; private Integer length; }
两种写法对比
编译正常的写法
先将方法引用赋值给SFunction变量,再创建数组:
SFunction<FrameModel, ?> getFrameType = FrameModel::getFrameType; SFunction<FrameModel, Integer> getLength = FrameModel::getLength; SFunction<FrameModel, ?>[] funcArray = new SFunction[]{getFrameType, getLength};
编译报错的写法
直接在数组初始化中使用方法引用,报错Non-static method cannot be referenced from a static context:
SFunction<FrameModel, ?>[] funcArray = new SFunction[]{FrameModel::getFrameType, FrameModel::getLength};
问题原因
- 第一种写法中,编译器通过左边的
SFunction变量类型,明确知道要把FrameModel::getFrameType这个实例方法引用转换为SFunction的实现。此时实例方法引用会被适配成符合Function.apply(T t)的签名——本质是把传入的FrameModel实例作为调用方法的主体,完全符合函数式接口的要求。 - 第二种写法中,数组初始化器里的
new SFunction[]没有明确泛型参数,编译器无法自动推断出方法引用需要被转换为SFunction类型。此时编译器会直接把FrameModel::getFrameType当作普通的实例方法引用处理,而静态上下文(这里的数组初始化代码如果在静态环境中)没有具体的FrameModel实例,就会触发“无法从静态上下文引用非静态方法”的错误。
解决方法
方法一:明确数组的泛型类型
在创建数组时指定完整的泛型参数,帮助编译器完成类型推断:
SFunction<FrameModel, ?>[] funcArray = new SFunction<FrameModel, ?>[]{FrameModel::getFrameType, FrameModel::getLength};
方法二:显式转换方法引用
给每个方法引用添加类型转换,明确告诉编译器要将其转换为SFunction实例:
SFunction<FrameModel, ?>[] funcArray = new SFunction[]{ (SFunction<FrameModel, FrameTypeEnum>) FrameModel::getFrameType, (SFunction<FrameModel, Integer>) FrameModel::getLength };
内容的提问来源于stack exchange,提问作者flyingfox
相关产品推荐
相关产品推荐

