Java 8中静态方法和实例方法的区别

14

假设我有以下代码

public class A {
    int x;
    public boolean is() {return x%2==0;}
    public static boolean is (A a) {return !a.is();}
}

并且在另一个分类中...

List<A> a = ...
a.stream().filter(b->b.isCool());
a.stream().filter(A::is); 
//would be equivalent if the static method is(A a) did not exist

问题是如何使用A::is类型标记来引用实例方法版本?非常感谢


你是指如果这两个方法都存在,如何调用实例方法吗? - Rohit Jain
2
编译器错误提示:“对is的引用不明确,A中的方法is(A)和方法is()都匹配”。显然编译器无法决定。我建议您最好将符号更改为lambda表达式以使其明显。 - Edwin Dalorzo
2个回答

16

在您的示例中,静态方法和非静态方法都适用于过滤器方法的目标类型。在这种情况下,您不能使用方法引用,因为无法解决歧义。请参见§15.13.1 方法引用的编译时声明以获取详细信息,特别是以下引用和下面的示例:

如果第一次搜索产生一个静态方法,并且没有可用的非静态方法[..],那么编译时声明就是第一次搜索的结果。否则,如果没有可用的静态方法[..],并且第二次搜索产生了一个非静态方法,则编译时声明就是第二次搜索的结果。否则,就没有编译时声明。

在这种情况下,您可以使用lambda表达式代替方法引用:

a.stream().filter(item -> A.is(item));

关于查找静态方法和非静态方法的规则有些特殊,因为哪个方法更适合并不重要。即使静态方法需要一个Object而不是A,它仍然是模糊的。因此,我建议作为一般准则:如果在类中有几个同名方法(包括从基类继承的方法):

  • 所有方法都应具有相同的访问修饰符,
  • 所有方法都应具有相同的final和abstract修饰符,
  • 所有方法都应具有相同的static修饰符

-7
我们不能使用 className::methodName 的记法来调用非静态或非全局方法。 如果你想要使用某个类的方法,你必须拥有该类的一个实例。
So if you want to access is() method then you can use : 
A a = new A();
a.is();
OR 
(new A()).is();

谢谢。


4
这是关于Java-8方法引用的内容。 - Not a bug

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接