Unable to pass Consumer<> instance

55 Views Asked by At

I have a class for walking a directory tree and performing an action on each file/directory. It looks like this:

class DirWalker {
  public static void walkDirs(Path startingPath, Consumer<Path> vAction)  {...}
}

In another class I have the following:

public static Consumer<Path> doVisit = p -> {...}

I tried to use this in my Java code like this:

DirWalker.walkDirs(/* a path */, MyClass::doVisit);

However, I get an error here saying that 'MyClass does not define doVisit(Path) that is applicable here'. I can change the doVisit member to a method and it works.

If I were to use a lambda inline in the walkDirs call it would work fine. But creating an instance of a Consumer and passing that to the walkDirs method fails. Why is this the case?

2

There are 2 best solutions below

1
smallpepperz On BEST ANSWER

You would use the method reference syntax (MyClass::doVisit) only if doVisit was a method. As you're declaring it, doVisit is a field, and should be accessed as MyClass.doVisit

If you want to use the method reference syntax, you can write it as a method that satisfies the Consumer<Path> interface instead of an inline lambda expression, like below

public static void doVisit(Path p) {
    ...
}
2
Mr. Polywhirl On

Your doVisit is an instance of a Consumer. So you cannot use a method reference. Just pass the reference to your walkDirs method.

import java.nio.file.Path;
import java.util.function.Consumer;

public class MyClass {
    public static Consumer<Path> doVisit = path -> {};
    
    public static void main(String[] args) {
        DirWalker.walkDirs(Path.of("/tmp"), doVisit); // Static
    }

    public static class DirWalker {
        public static void walkDirs(Path startingPath, Consumer<Path> vAction)  {

        }
    }
}

If you want to reference the field, use instance.doVisit:

import java.nio.file.Path;
import java.util.function.Consumer;

public class MyClass {
    public Consumer<Path> doVisit = path -> {};

    public static void main(String[] args) {
        MyClass instance = new MyClass();
        DirWalker.walkDirs(Path.of("/tmp"), instance.doVisit); // Instance
    }

    public static class DirWalker {
        public static void walkDirs(Path startingPath, Consumer<Path> vAction)  {

        }
    }
}

Here is a variation of the first, with an additional wrapping class:

import java.nio.file.Path;
import java.util.function.Consumer;

public class Driver {
    public static void main(String[] args) {
        DirWalker.walkDirs(Path.of("/tmp"), MyClass.doVisit); // Static
    }

    public static class MyClass {
        public static Consumer<Path> doVisit = path -> {};
    }

    public static class DirWalker {
        public static void walkDirs(Path startingPath, Consumer<Path> vAction)  {

        }
    }
}

Finally, here is a version that I think you are requesting. Create a class called MyVisitor with a doVisit(path: Path): void method.

import java.nio.file.Path;
import java.util.function.Consumer;

public class Driver {
    public static void main(String[] args) {
        DirWalker.walkDirs(Path.of("/tmp"), MyVisitor::doVisit);
    }

    public static class MyVisitor {
        public static void doVisit(Path path) {
            // Print path
        }
    }

    public static class DirWalker {
        public static void walkDirs(Path startingPath, Consumer<Path> vAction)  {
            vAction.accept(startingPath); // Start traversal
        }
    }
}