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

Why should functions used for creating a Predicate be defined as static?

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

考虑以下 Apple class 例如:

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;

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

What I am more interested in knowing is why are all examples on predicates shown using static methods?

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

Any specific reason for not using instance methods?

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

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

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

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

对于方法引用,实例方法A.foo()static方法foo(A)没有区别,实际上the compiler will reject a method reference as ambiguous if both exist.

所以决定是使用实例方法还是static方法并不取决于你是否想通过方法引用为它创建一个函数。

相反,您必须像往常一样应用相同的考虑因素。如果该方法是可覆盖的,它必须是一个实例方法,否则,如果它表示一个固定的算法,你可以考虑一个 static 方法,当然,一个 final 方法也可以。

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

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

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

上的实例方法 max(Foo)

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


关于为什么有这么多例子使用static方法;好吧,我不知道足够多的例子来决定你的观察是正确的还是只是主观看法。但也许一些教程编写者自己并没有意识到将实例方法引用为将方法接收者作为第一个参数的函数的可能性。

我想,有例子,比如

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

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