没有公共类的Java文件编译

8

好的,一个Java源文件必须至少有一个公共类,并且文件应该被称为“class-name.java”。很公平。

因此,如果我有一个类,那么以下内容将被编译:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World!"); // Display the string.
    }
}

但是让我困惑的是,如果我从上面的代码中删除“public”访问修饰符,代码仍然可以编译通过。我就是不明白。删除后,代码如下:

class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World!"); // Display the string.
    }
}

在上面的代码中,由于我移除了“public”访问修饰符,我的类具有默认或包访问权限,即它无法从外部访问,只能在包内访问。
那么我的问题是,上面的代码如何编译? 在这种情况下,文件“HelloWorld.java”没有公共的HelloWorld类(仅有一个包私有的HelloWorld.class),因此根据我的理解不应该编译。

“Java源文件必须至少有一个公共类。”不,它根本不需要任何东西。 - ADTC
6个回答

10

谢谢!那么你的意思是说,无论谁调用main()都是从某种包上下文中调用它的?也就是说,调用main()的调用者(JVM可能)与我的HelloWorld类在同一个包中?有点困惑!所以感谢您抽出时间来回答我的问题。 - anon1981
此外,您可以在Java文件中定义多个非公共类。 - Matthew Farwell
那么现在我的问题是:HelloWorld是默认类中的包私有类,我是对的吗?因此它应该可以从默认包内部访问,但不能从默认包外部访问,对吗?进一步推断,当main()被调用时,它必须是从默认包内部被调用的,我是对的吗?或者,无论谁调用main()都在与HelloWorld类相同的包中。对吗? - anon1981

2

你可以把非公共类放在一个文件中,这不是一个错误,而是一项功能。

你的问题在于包级别,而不是编译。因为你可以使用非公共类编译这个文件,但你不能从外部调用它,所以它不能作为应用程序基类工作。

像这样:

// [+] single file: SomeWrapper.java 

public class SomeWrapper {
    ArrayList<_PrivateDataType> pdt;
}
// [-] single file: SomeWrapper.java 

// [+] single file: _PrivateDataType.java 
class _PrivateDataType {
    // members, functions, whatever goes here
}

// [-] single file: _PrivateDataType.java 

谢谢,但我的观点不是要添加私有数据类型或其他任何东西。我的问题是上面的代码如何编译和工作,因为这里有一个.java文件,但其中没有任何公共类。其中唯一的类是一个包私有类,而不是公共类。 - anon1981
问题出在哪里?您可以在同一包中创建另一个类(具有相同的效果),并使用该包私有类。 - Marek Sebera
再次强调,我的问题不是在文件中添加任何新类。我只关心包私有访问权限。 - anon1981
我编辑了代码,它不是文件中的新类,而是在包内。 - Marek Sebera
我的问题与你所阐述的完全不同 :) 你所说的是正确的,但那不是我想知道的。我只想知道为什么在文件中有一个包私有类仍然可以编译。 - anon1981
就像我之前所说的那样,它编译通过是因为单个文件中只有一个包私有类是有效的。这类似于类的私有成员,可以有包的私有类。 - Marek Sebera

1

主方法就像任何其他方法一样。唯一的区别是它可以通过java命令从命令行调用。即使主方法在命令行上不可见,该类仍然可以像任何其他Java类一样使用,并且您的主方法可以由同一包中的另一个类调用。因此,编译它是有意义的。

在Java中,主函数没有任何特殊之处。只是存在一个终端命令,能够调用名为main的静态方法...


1
现在,HelloWorld类具有包私有访问权限。因此,无论谁调用main方法(JVM?),现在也必须在同一个包中,对吗? - anon1981
如果我直接从一个java类中调用,那么是的。不过,使用反射的规则略有不同。通过反射,任何非私有方法都可以被调用。JVM使用反射来调用您的主方法。 - Mathias Schwarz

1

非公共类有其有效的用途。因此,当您尝试编译文件时,编译器不会报错。


0

这并不足为奇。我认为这种行为类似于某些 C/C++ 编译器的行为。

像 "void main() { /.../ }" 这样的代码将被这些编译器正确编译,尽管它不符合标准的代码规范。简单地说,编译器会将 "void" 替换为 "int"。

我认为 Java 编译器也实现了类似的行为。


-1

当您未指定类(或其字段或方法)的访问修饰符时,它被分配为“默认”访问。这意味着它只能从同一包中访问(在这种情况下是默认包)。

Javabeginner.com 网站上有一篇关于此主题的文章 - 您应该熟悉 Java 中的访问修饰符,可以从该网站或其他网站了解相关知识。


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