为什么我能在非公开课上有公共会员?

XFo*_*E07 24 java class public-members

class MyClass 
{
    public static final int num=90;
}
Run Code Online (Sandbox Code Playgroud)
  • 为什么我被允许在非公开课中创建公共成员?
  • 是否有另一种访问此成员的方法我不知道(除了通过类名)?

Jas*_*n C 17

由于你的问题是关于成员的,我将解决两个领域和方法(非静态; 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

同样的推理适用于,例如,privateprotected内部类.如果您无法声明方法public,则无法覆盖public它们继承的接口方法或它们扩展的类.

实际例子:

  • 每次重写匿名内部类中的公共方法时都会使用它(例如,每次public void actionPerformed以匿名方式覆盖ActionListener).

  • 考虑您想要存储在的任何非公共类HashMap.您将覆盖公共equals()hashCode()非公共类,并且HashMap无论该类是非公共的,都可以访问它们.

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

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

  • 还有更多...如果你留意这个例子,你会惊奇地发现它真的很普通!

  • 完全同意;)很好地说明了我试图写的想法. (2认同)

Ant*_*oly 5

不要忘记具有default访问权限的类可以由public同一个包中的类进行子类化。

package package1;

class MyDefaultClass {

    public static final int MY_CONSTANT = 0xCAFEBABE;
}

public class PublicExporter extends MyDefaultClass {

}
Run Code Online (Sandbox Code Playgroud)

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

package package2;

import package1.PublicExporter;

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

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

import static package1.PublicExporter.MY_CONSTANT;

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


Ale*_*dro 0

当你声明一个变量时,public它本质上就变成了这样;它可以在整个程序中看到,无需任何特殊的 getter/setter。该类不一定需要使其public成员也是公开的。

请记住,在 Java 中,每个编译单元(. 文件)只能有 1 个公共类java,并且该公共类需要与编译单元具有相同的名称。除此之外,它不“拥有”关键字 public 的所有权。

事实上,您声明numpublicstatic允许您说 System.out.println(MyClass.num)。该public属性允许您直接获取num变量。因此,您不必创建一个方法来num为您返回。因为它是公开的,所以你也可以说

      MyClass mc = new MyClass();
      System.out.println(mc.num);
Run Code Online (Sandbox Code Playgroud)

但是,由于您还添加了static声明,因此您只能通过类名访问它,即 MyClass.num

要点:公共变量可以存在于任何类型的类中,并且它们允许您访问它们而无需 getter 和 setter。然而,公共类并不是唯一可以拥有公共变量的类。

  • 啊,我明白我在哪里犯了错误。感谢您指出了这一点 (2认同)