.java 文件中的包私有类 - 为什么它可以访问?
考虑以下代码,其中 HelloWorld
类具有默认或包私有访问权限:
class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!"); // Display the string.
}
}
并假设上述代码保存在名为 HelloWorld.java
的文件中。所以我的问题是:既然 HelloWorld
现在是一个包私有类,它是如何工作的? main()
方法不应该跨包可见或可访问,对吗?
如果类 HelloWorld
被声明为 public,这对我来说是非常有意义的。仅当使用默认的包私有访问权限声明时才会产生混淆。
Consider the following code, where the HelloWorld
class has default or package-private access:
class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!"); // Display the string.
}
}
And assume that the above code is saved in a file called HelloWorld.java
. So my question is: since HelloWorld
is now a package-private class, how does it work? The main()
method should not be visible or accessible across packages, am I right?
It makes perfect sense to me if the class HelloWorld
is declared public. Confusion is only when it is declared with the default package-private access.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
JVM 启动在§12.1 虚拟机启动中进行了描述JLS。
请注意,本章没有提及关于类的可见性检查。它仅指定
main
方法必须是public
。这意味着根本没有检查类级别的可见性(这种情况是有意义的,因为还没有上下文来检查可见性:其中“包”是“调用者”?)。
JVM startup is described in §12.1 Virtual Machine Start-Up of the JLS.
Note that this chapter says nothing about visibility checks with regards to the class. It only specifies that the
main
method must bepublic
.This means that there simply is no check for visibility on the class level (which kind-of makes sense as there is no context yet against which to check the visibility: in which "package" is the "caller"?).
Main 方法对于驻留在不同包中的其他类不可见。但 JVM 可以看到这一切。它不会有任何困难找到你的主要方法并为你运行它。
如果您想模拟访问限制,请在不同的包中编写另一个类并尝试调用
HelloWorld.main
并查看编译器是否保持安静。Main method won't be visible to other classes which reside in different packages. But the JVM can see it all. It won't have any difficulty in finding your main method and running it for you.
If you want to simulate the access restriction, write another class in a different package and try to call
HelloWorld.main
and see if the compiler keeps quiet.您还没有说得很清楚,但我认为您的问题是为什么当您在命令行中键入 java HelloWorld 时可以运行该 main 方法。
答案是Java 语言规范 根本不要求包含 main 方法的类是公共的。访问修饰符是一种语言机制,主要旨在通过封装来帮助维护。它们并不是真正的安全功能,当然也不是不可动摇的物理定律。 JVM 启动机制简单地忽略它们。
事实上,您甚至可以使用私有内部类,它仍然会运行。
You have not made it very clear, but I assume that your question is why that main method can be run when you type
java HelloWorld
at the command line.The answer is that the Java Language Specification simply does not require the class that contains the main method to be public. Access modifiers are a language mechanism mainly intended to help maintainability via encapsulation. They're not really a security feature, and certainly not unshakable laws of physics. The JVM startup mechanism simply ignores them.
In fact, you can even use a private inner class, and it will still run.
也许 JLS 的设计者认为,如果你知道类名,就不需要限制对 main 方法的访问,但乍一看,这似乎违反直觉;从另一侧 - 访问始终可以通过反射获得,因此不能将其视为安全漏洞......
无论如何,例如通过创建一个包私有类的外观,我们可以间接访问该类...因此,保护是防止错误使用并允许进一步的更改。
Probably the designers of JLS decided there is no need to restrict access to main method if you know the class name, while at the first glance it looks counter-intuitive; from the other side - the access could be always got via reflection so it couldn't be treated as a security hole...
Anyway e.g. by creating facade to a package-private class we access that one indirectly... So the protection is rather from incorrect usage and to allow further changes.