Java 导入通配符不导入包内的所有内容

Java import wildcard not importing everything inside package

我正在编写一个 Java 程序,它有一个带有动作侦听器的按钮:

    JButton button = new JButton("Change");
    button.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            label.setText(textField.getText());
        }
    });

在文件的顶部,我有这两个导入语句:

import java.awt.*;
import javax.swing.*;

我知道这是糟糕的做法,我正在复习考试,把它写在页面顶部会更容易、更快捷。

但是我收到一个错误,告诉我导入 java.awt.event.ActionListener

如果 event 包在 java.awt 中并且我使用通配符 * 导入所有内容,那么为什么它没有被导入??

java.awt.* 不包括 java.awt.event.ActionListenerjava.awt.event 不是 java.awt 的子包。 import java.awt.event.* 将包括 java.awt.event.ActionListener.

这里是Java Language Specification中type-import-on-demand的定义:

A type-import-on-demand declaration allows all accessible types of a named package or type to be imported as needed.

TypeImportOnDemandDeclaration: import PackageOrTypeName . * ;

理解术语很重要:"all accessible types of a named package" 表示 package 声明为 的所有类型,特别是 .* 之前的类型.

所以,如果 class 的包定义如下:

package my.pkg.name;

然后它将对 import my.pkg.name.* 可用,但是如果 class 定义如下:

package my.pkg.name.subname;

那么它将无法用于 import my.pkg.name.*,因为它不属于那个包。它特别属于 my.pkg.name.subname,就 Java 而言,这是一个不同的包。

确实 Java 实现通常希望包在目录层次结构中排序,因此 my.pkg.name.subname 的目录将位于 my.pkg.name 的目录下。如果你想到它,假设你写了

ls my/pkg/name/*

在该目录中。它的行为非常相似:它只会直接给你这个目录下的文件,而不是它下面的目录。按需导入类型的语义几乎相同(不包括 subname "directory" 本身,因为它不是类型)。