Java Lambda表达式是否使用"隐藏"或本地包导入?

mbm*_*ast 7 java lambda

这个问题是关于lambda表达式似乎使用的Java包的明显"隐藏"或本地导入.

以下示例代码编译并运行正常(它只列出给定目录中的文件):

package com.mbm.stockbot;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class Temp2 {
    public static void main(String[] args) {
        Temp2 t = new Temp2();
        t.readDir();
    }

    public void readDir() {
        try {
            Files.walk(Paths.get("C:/Users/mbmas_000/Downloads/SEC Edgar"), 1).forEach(filePath -> {
                if (Files.isRegularFile(filePath)) {
                    System.out.println(filePath);
                }
            });
        } catch (IOException e1) {
            e1.printStackTrace();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,该变量filePath是一个实例Path,我认为它的实现包含在包中java.nio.file.Path,尽管import该包没有.

现在,如果我做了一个小修改,可以通过重构System.out.println对它自己的方法的调用来说:

package com.mbm.stockbot;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class Temp2 {

    public static void main(String[] args) {
        Temp2 t = new Temp2();
        t.readDir();
    }

    public void readDir() {
        try {
            Files.walk(Paths.get("C:/Users/mbmas_000/Downloads/SEC Edgar"), 1).forEach(filePath -> {
                if (Files.isRegularFile(filePath)) {
                    printPath(filePath);
                }
            });
        } catch (IOException e1) {
            e1.printStackTrace();
        }
    }

    public void printPath(Path passedFilePath) {
        System.out.println(passedFilePath);
    }
}
Run Code Online (Sandbox Code Playgroud)

我现在必须'导入' import java.nio.file.Path,否则我会收到编译器错误.

所以我的问题是:

  1. 如果filePath的确是一个实例java.nio.file.Path,为什么不要我需要导入它在第一个例子,和

  2. 如果使用lambda表达式执行进口"在幕后,"那么为什么我需要添加import,当我创建需要的实例的方法Path作为参数?

可用的方法,以在两个呼叫filePathpassedFilePath是相同的,导致我相信他们的两个实例java.nio.file.Path.

Hol*_*ger 6

import声明并不意味着声明您的代码正在使用哪些类; 他们只是声明用于解析非限定标识符的内容.因此,如果您Path在代码中使用非限定标识符,则必须使用import java.nio.file.Path;它来声明它应该被解析为此限定类型.顺便说一下,这不是解决名称的唯一方法.名称也可以通过类继承来解析,例如,如果它们与继承的成员类的简单名称匹配.

如果您在不引用其名称的情况下隐式使用类型,则不需要import语句,这不仅限于lambda表达式,它甚至不是特殊的Java 8功能.例如

Files.walk(Paths.get("C:/Users/mbmas_000/Downloads/SEC Edgar"), 1)
Run Code Online (Sandbox Code Playgroud)

你已经Path隐式使用了这个类型,因为它是返回类型Paths.get和参数类型Files.walk,换句话说,你正在接收一个实例java.nio.file.Path并将其传递给另一个方法而不引用它的类型名称,因此你不需要import.此外,您正在调用接受任意数量FileVisitOption实例的varargs方法.您没有指定任何内容,因此您的代码将创建一个零长度FileVisitOption[]数组并Files.walk再次将其传递给没有import.

使用改进的类型推断,还有另一种可能使用类型而不引用其名称,例如,如果您调用:

Files.newByteChannel(path, new HashSet<>());
Run Code Online (Sandbox Code Playgroud)

您不仅FileAttribute[]要为varargs参数创建零长度数组而不通过名称引用此类型,还要创建一个HashSet<OpenOption>不引用类型OpenOption的名称.所以这也不需要,java.nio.file.attribute.FileAttribute也不需要java.nio.file.OpenOption.


所以最重要的是,你是否需要一个import不依赖于类型的使用,而是你是否通过它的简单名称来引用它(并且有多种方法可以使用类型而不是通过名称引用它).在第二个示例中,您指的是Path方法中的名称printPath(Path passedFilePath); 如果你改成它printPath(Object passedFilePath),一切都会在没有明确import的情况下再次发挥作用java.nio.file.Path.