为什么我可以在非公开课程中拥有公共成员?

2022-09-01 19:17:37
class MyClass 
{
    public static final int num=90;
}
  • 为什么允许在非公共类中创建公共成员?
  • 是否有另一种我不知道的访问此成员的方法(除了通过类名)?

答案 1

由于您的问题是关于成员的,我将讨论字段和方法(非静态;Anthony Accioly的答案触及了另一个很好的用例,其中还包括静态字段)。

虽然在许多情况下,这只是语言语法的一个模糊的结果(特别是:非公共类中的公共字段,如您的示例代码片段),但有很好的理由需要在非公共类中使用公共方法

扩展Mik378的答案,请考虑以下(人为示例):

import ...;

class BleebleAscendingComparator implements Comparator<Bleeble> {
    @Override public int compare (Bleeble o1, Bleeble o2) { ... }
}

class BleebleDescendingComparator implements Comparator<Bleeble> {
    @Override public int compare (Bleeble o1, Bleeble o2) { ... }
}

public class BleebleView {  
    public enum SortMode { ASC, DESC };
    public Comparator<Bleeble> getDisplayOrderComparator (SortMode mode) {
        if (mode == SortMode.ASC)
            return new BleebleAscendingComparator();
        else
            return new BleebleDescendingComparator();
    }
}

您不能直接在该上下文之外实例化其中一个实现,但它们必须重写 的公共方法,并且它们的功能可通过接口访问。ComparatorComparatorComparator

同样的推理也适用于,例如,或内部类。如果你不能声明方法,你将无法重写它们继承的接口或它们扩展的类的方法。privateprotectedpublicpublic

实例:

  • 每次在匿名内部类中重写 public 方法时(例如,每次在匿名中重写)时,都会使用它。public void actionPerformedActionListener

  • 考虑要存储在 .您将重写该非公共类中的 public 和,并且 无论该类是非公共的,实现都可以访问它们。HashMapequals()hashCode()HashMap

  • 经常被覆盖的是潜在非公共类的公共成员的另一个常见示例。public toString()

  • 一个更复杂的例子是在java中使用.sql.DriverManager(通常,工厂类型的设计大量使用这个概念) - SQL驱动程序实现可能不会公开实现类(例如,Oracle驱动程序生成非公共对象)。java.sql.DriverConnection

  • 还有更多...如果你留意这样的例子,你会惊讶于它到底有多普遍!


答案 2

不要忘记,具有访问权限的类可以由同一包中的类子类化。defaultpublic

package package1;

class MyDefaultClass {

    public static final int MY_CONSTANT = 0xCAFEBABE;
}

public class PublicExporter extends MyDefaultClass {

}

现在,该类充当桥梁,您可以使用其他包中的成员。publicMyDefaultClasspublic

package package2;

import package1.PublicExporter;

public class Consumer {
    public static void main(String[] args) {
        System.out.printf("%x\n", PublicExporter.MY_CONSTANT);
    }
}

消费者甚至可以导入静态成员:

import static package1.PublicExporter.MY_CONSTANT;

public class Consumer {
    public static void main(String[] args) {
        System.out.printf("%x\n", MY_CONSTANT);
    }
}