为什么用于创建谓词的函数应该定义为静态?

时间:2015-01-15 18:13:53

标签: java-8 predicate

在阅读Java 8中引入的新功能的同时,我发现了Predicates的概念。我注意到互联网和书籍中提供的大多数示例都使用静态函数来创建谓词。

例如,考虑以下Apple类:

public class Apple {

    private String color;
    private int weight;

    private static final int SMALL_APPLE_MAX_WEIGHT = 150;

    public Apple(String color, int weight) {
        this.color = color;
        this.weight = weight;
    }

    public static boolean isGreenApple(Apple apple) {
        return null!=apple && null!=apple.getColor() && "green".equals(apple.getColor());
    }

    public boolean isBigApple() {
        return this.getWeight() > SMALL_APPLE_MAX_WEIGHT;
    }
}

我现在可以按如下方式创建一个新谓词:

Predicate<Apple> isGreenApple = Apple::isGreenApple;
Predicate<Apple> isBigApple = Apple::isBigApple;

如上所示,我可以使用静态和实例方法创建谓词。那么哪种方法是首选方法,为什么?

2 个答案:

答案 0 :(得分:6)

对于方法参考,实例方法A.foo()static方法foo(A)之间没有区别,事实上,the compiler will reject a method reference as ambiguous if both exist

因此,是否使用实例方法或static方法的决定并不依赖于是否要通过方法引用为其创建函数的问题。

相反,你必须按照惯例应用相同的考虑因素。如果方法可以覆盖,则它必须是实例方法,否则,如果它表示固定算法,您可以考虑static方法,但当然,final方法也可以。

当您不是要处理其实例的类的维护者时,

static方法显然是不可避免的,换句话说,当包含类必须与实例的类不同时。但即使该类是相同的,但您认为它也可以放在另一个(实用程序)类中,将其声明为static可能是更好的选择。

这尤其适用于存在多个参数且第一个参数对操作不特殊的情况,例如: max(Foo,Foo)应该是static方法,而不是max(Foo)上的实例方法Foo

但最终有不同的编程风格,答案是方法引用不要求特定的编程风格。


关于为什么有这么多使用static方法的例子;我不知道足够的例子来决定你的观察是正确的还是仅仅是主观的观点。但是也许一些教程编写者本身并不知道将实例方法引用为将方法接收器作为第一个参数的函数的可能性。

我认为,有一些例子,比如

Predicate<String> empty=String::isEmpty;
Predicate<CharSequence> isHello="hello"::contentEquals;

值得在教程中显示,以强调您不需要创建专门用作方法引用的方法,但实际上有很多已有的方法,static和非 - static,可直接与方法参考一起使用。

答案 1 :(得分:1)

  

我更感兴趣的是为什么使用静态方法显示谓词上的所有示例?

引用出现在Class上,因为不需要额外的参数。

  

不使用实例方法的任何特定原因?

对于有意义的非静态方法。在

的情况下
Predicate<Apple> isBigApple = Apple::isBigApple;

Predicate需要一个参数,因此需要this。非方法调用的示例类似于

List<Apple> bigApples = new ArrayList<>();
apples.stream().filter(Apple::isBigApple).forEach(bigApple::add);