问题 方法参考。无法对非静态方法进行静态引用


有人可以向我解释,
为什么将非静态方法引用传递给方法 File::isHidden 没关系,
但是将方法引用传递给非静态方法 MyCass::mymethod  - 给我一个 “无法对非静态方法进行静态引用” ?

public static void main(String[] args) {
    File[] files = new File("C:").listFiles(File::isHidden); // OK
    test(MyCass::mymethod); // Cannot make a static reference to the non-static method
}

static interface FunctionalInterface{
    boolean function(String file);
}

class MyCass{
    boolean mymethod(String input){
        return true;
    }
}

// HELPER
public static void test(FunctionalInterface functionalInterface){}

6680
2017-09-16 21:32


起源



答案:


对非静态方法的方法引用需要一个实例来操作。

在的情况下 listFiles 方法,参数是一个 FileFilter 同 accept(File file)。在操作实例(参数)时,可以引用其实例方法:

listFiles(File::isHidden)

这是简写

listFiles(f -> f.isHidden())

现在为什么你不能使用 test(MyCass::mymethod)?因为你根本没有实例 MyCass 操作。

但是,您可以创建一个实例,然后将方法引用传递给您的实例方法:

MyCass myCass = new MyCass(); // the instance
test(myCass::mymethod); // pass a non-static method reference

要么

test(new MyCass()::mymethod);

10
2017-09-16 22:31



你无法实例化 MyClass 来自一个 static 方法(如 main)因为是一个 非静态 内心阶级。您必须将该类声明为静态。我假设原始示例中的代码包含在类中。 - Marco Torchiano


答案:


对非静态方法的方法引用需要一个实例来操作。

在的情况下 listFiles 方法,参数是一个 FileFilter 同 accept(File file)。在操作实例(参数)时,可以引用其实例方法:

listFiles(File::isHidden)

这是简写

listFiles(f -> f.isHidden())

现在为什么你不能使用 test(MyCass::mymethod)?因为你根本没有实例 MyCass 操作。

但是,您可以创建一个实例,然后将方法引用传递给您的实例方法:

MyCass myCass = new MyCass(); // the instance
test(myCass::mymethod); // pass a non-static method reference

要么

test(new MyCass()::mymethod);

10
2017-09-16 22:31



你无法实例化 MyClass 来自一个 static 方法(如 main)因为是一个 非静态 内心阶级。您必须将该类声明为静态。我假设原始示例中的代码包含在类中。 - Marco Torchiano


正如彼得瓦尔瑟所指出的那样 MyCass::mymethod 是一个实例方法,它需要将实例转换为 Function 实例。

static 在您的界面声明前面只是使它成为一个 静态接口,它不会将每个方法变为静态方法。

一种可能的解决方案是将类中的方法声明为static:

class MyCass{
   static boolean mymethod(String input){
       return true;
   }
}

为了更好地理解它的工作原理,您可以将代码视为等效于方法参考 MyCass::mymethod 那就是(假设上面修改过的声明 MyClass):

new FunctionalInterface{
  boolean function(String file){
    return MyClass.mymethod(file);
  }
}

您的原始代码将尝试排序转换为:

new FunctionalInterface{
  boolean function(String file){
    return _missing_object_.mymethod(); # mymethod is not static
  }
}

另一种可能性是使用a BiFunction 而不是你的 FunctionalInterface。在那种情况下,第一个参数 apply 将是对象,第二个将成为对象 mymethod


1
2017-09-17 10:17



你的第一个例子必须是 MyClass.mymethod(file)。 OP的代码也将被翻译成。这就是“无法制作静态参考......”错误的地方。第二个示例中没有静态引用。 - a better oliver