单个文件中的多个类:这里不允许使用修饰符private。

23

我无法理解为什么这段代码无法编译:

class A {
    public static void main(String[] args) {
        System.out.println("hi");
    }
}

private class B {
    int a;
}

我将文件保存为名为A.java的文件,但是出现了错误:

modifier private not allowed here // where I have defined class B

当我将B设置为私有或受保护时,都会出现这种情况。有人能否解释一下背后的原因?

谢谢!


内部类可以是私有的。 - Konstantin Burov
不,它似乎不依赖于A。 - dev
7个回答

27

根据Java语言规范

 

访问修饰符protected和private只适用于直接封闭类声明内的成员类

因此,是的,顶级类声明不允许使用private和protected修饰符。

顶级类可以是公共的或非公共的,而privateprotected是不允许的。如果一个类被声明为public,则可以从任何包中引用它。否则,它只能在同一个包(命名空间)中被引用。

一个私有的顶级类没有太多意义,因为它不能被任何类引用。它从定义上来说是无法使用的。private对于成员类来说是可以接受的,以使类只能被其封闭类引用。

一个受保护的成员类可以从(1)相同包中的任何类和(2)封闭类的任何子类中引用。将此概念映射到顶级类很困难。第一种情况由没有访问修饰符的顶级类涵盖。第二种情况对于顶级类不适用,因为没有封闭类或其他来自不同包的与此类有特殊关系(如子类)的东西。因此,我认为protected是不允许的,因为它的基本概念在顶级类中不适用。


谢谢Andreas,但您能否让我明白为什么Java开发人员会强制执行此限制?我知道这个问题可能听起来很荒谬,但我很好奇。谢谢! - dev
2
好的。已经理解了私有变量的逻辑,但是保护变量怎么办呢?“保护”比“默认”限定符更加开放,而且已经被允许使用! - dev

4
使B成为A的嵌套元素,如下所示:
class A {
    public static void main(String[] args) {
        System.out.println("hi");
    }

    private class B {
        int a;
    }
}

或者将B移动到单独的文件中。此外,您可以保持默认访问级别,这样该类只能从包内访问:

class A {
    public static void main(String[] args) {
        System.out.println("hi");
    } 
}

class B {
    int a;
}

我不想嵌套,也不想移动到不同的文件。我只想知道错误的原因。 - dev
错误其实很明显。如果你不将它嵌套或放在单独的文件中,那么这个类将无法从任何地方访问,因为它是私有的。你也不能将它设为公共的,因为Java限制每个文件只能有一个公共顶级类。 - Konstantin Burov
对于顶层类,protected 没有意义。因为如果它具有默认访问级别(未指定修饰符),则可以从包内访问,如果是 public,则也可以从包外访问。Protected 对此没有任何添加。顺便提一下,我忘了注意到您可以使用默认访问级别。请参见答案更新。 - Konstantin Burov

1

private和protected对于顶级(非成员)类/接口是没有意义的。

它们仅适用于类成员,包括变量、常量、构造函数、方法、类和接口。

为什么:

(1) private: 如果我们将类定义为私有的,那么它的作用域应该是私有的。默认访问权限已经是包私有的。而且没有人希望一个类成为源文件私有的。(猜测原因)允许这样做可能不是一个好的编程实践,因为Java应用程序最终以包的形式组织,而不是以源文件的形式。任何源文件都应该是某个包的一部分,因此从广泛/最终的视角来看,每个类/接口都是某个包的一部分,而不仅仅是某个.java文件的一部分。因此不适用。

(2) protected: 如果某些内容是受保护的,那么它只能在包内使用,并且只能在其他包中的子类中使用。要扩展不同包中的类,它应该对其他包中的所有类都可用,但是protected表示该类仅对扩展它的类可用。这是一种死锁情况。因此不适用。

来源:我的阅读和理解


只要一个类不是公共的,它的名称可以与文件名不同。这个类也可以有主方法。类文件将以类名生成,而不是源文件名。应该使用类名来执行它。 - Venkataswamy

0

根本就没有任何私有/受保护修饰符。


我想说的是我已经分别尝试了私有和受保护的方式,但在两种情况下都不起作用。 - dev
我只是在尝试访问控制,我只想知道错误的原因。 - dev

0
B需要对某个东西保密。将其放在类A的定义内部或创建另一个文件B.java并在那里定义,但这样它就不能是私有的。

在Java中,将类/变量设置为私有或受保护是一种规则吗?我们不能将独立的类/变量设置为私有或受保护吗? - dev
我的陈述比概念更抽象。根本问题在于您在A.java文件中声明了另一个类。看起来您想将B设为A的私有类或者放在“某个地方”内部。然而,您关于是否可以将独立类设置为私有或受保护的陈述并不真正合理,因为修饰符只有在相对于某些东西时才具有上下文。 - linuxuser27

-1
如果你不使用public关键字来修饰类,那么它默认是私有的(只能在文件内部可见)。
每个.java文件中只能有一个public类,其他类都需要被声明为私有。所以在你的例子中,类A可以是public的,而类B不需要任何修饰符。公共类的名称必须与.java文件的名称相匹配(例如,A.java文件中只能包含一个名为"A"的公共类)。

这不是正确的。没有修饰符的顶层类是包私有的。它可以从同一包中的任何类中引用。 - Andreas Dolk

-2

A.java 不能包含两个类。


2
是的,只要有一个类是公共的(它给源文件命名),而其他所有类都是非公共的(没有访问修饰符,也就是包可访问的),源文件就可以包含多个类。 - Andrei Fierbinteanu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接