public static Function<Object,String> toStringFunction() { ... }
Object的所有非原始根,因此该函数运行良好.
但是当我尝试用另一个函数组合它时,例如:
Function<Integer,Double> f1 = Functions.compose(Functions.forMap(someMap),Functions.toStringFunction());
someMap变量是map< String,Double>,所以我希望toStringFunction将Integer转换为String,然后forMap将String转换为Double.
但是我收到编译错误:
Function<Integer,^ required: Function<Integer,Double> found: Function<Object,Double> 2 errors
我的两个问题是:
1.具体告诉编译器toStringFunction应该是Function<整数,字符串>?一个简单的演员不会起作用,我正在寻找这两个函数的真实组合.
Function< Integer,String> g1 = (Function< Integer,String>)Functions.toStringFunction(); // cause error
2.将toStringFunction写成如下:
@SuppressWarnings("unchecked") public static <E> Function<E,String> toStringFunction(){ return (Function<E,String>) ToStringFunction.INSTANCE; } // enum singleton pattern private enum ToStringFunction implements Function<Object,String>{ INSTANCE; // @Override public String toString(){ // return "Functions.toStringFunction()"; // } @Override public String apply(Object o){ return o.toString(); } }
我可以指定类型:
Function<Integer,Functions.<Integer>toStringFunction());
这很好用.但番石榴团队现在拥有的版本的动机是什么?
解决方法
要修复编译错误:
Function<Object,Double> f1 = Functions.compose(Functions.forMap(someMap),Functions.toStringFunction());
你的问题意味着你需要一个函数< Integer,Double>而不是函数< Object,Double>.根据评论中的讨论,并试图考虑其他方案,您想要这个的唯一原因是验证. toStringFunction中的代码不受您的控制,因此该函数中的验证是不可能的.至于forMap函数中的验证,该代码也是您无法控制的.如果要防止IllegalArgumentException,则无论您提供的输入是Object还是Integer,都必须执行此验证.因此,验证也超出了forMap,toStringFunction和compose的范围,因为这些函数都没有提供这种验证,你必须编写自己的代码来执行此操作(捕获异常并处理它或预先验证在调用这个组合函数之前以某种方式).
对于特定的组合,通过将Function的输入参数从Object更改为Integer,你什么也得不到,因为Function只需要Object中的方法,所以这是一个很好的决定,因为它简化了这种情况下的事情并使其更广泛可用.假设您能够将参数类型强制为Integer,您仍然无法获得任何好处,无论是IllegalArgumentException的验证还是您正在尝试的其他内容.
在设计API时,您希望尽可能多的消费者使用它,而不必偏离您的方式,即您应该使用满足您要求的最高级别的类.通过在toStringFunction中使用Object,Guava函数满足了这个原则.这使得该功能更通用并且可以更广泛地使用.这就是选择Object而不是参数化此函数的原因.
如果函数接受了一个参数,它就不会像现在这样做,所以为什么在不需要时使用参数.这种方法大大简化了设计,而不是添加不需要的东西.
原始答案:
每个类都是Object的子类,Function只调用Object类中存在的输入上的toString.因此,在这种情况下,声明一个Function等同于声明Function.通过将Function的输入参数从Object更改为Integer,您将无法获得任何结果,因为它简化了这种情况下的事情.
您应尽可能使用满足您要求的最高级别的课程.这使得该功能更通用并且可以更广泛地使用.这就是选择Object而不是参数化此函数的原因.
修复编译错误:函数f1 = Functions.compose(Functions.forMap(someMap),Functions.toStringFunction());