javafunctional-interface

Unable to pass Consumer<> instance


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?


Solution

  • 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
            }
        }
    }