【问题标题】:Java compilation of a .java file without a public class没有公共类的 .java 文件的 Java 编译
【发布时间】:2011-11-29 19:45:26
【问题描述】:

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

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

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

但让我烦恼的是,如果我从上面的代码中删除“公共”访问修饰符,代码仍然可以编译。我只是不明白。去掉它,代码如下:

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

在上面的代码中,由于我删除了public 访问修饰符,我的类具有defaultpackage 访问权限,即不能从外部访问它,只能从包内访问。

所以我的问题是,上面的代码是如何编译的?在这种情况下,文件 HelloWorld.java 没有 public HelloWorld 类(只有包私有的 HelloWorld.class),因此据我了解不应编译。

【问题讨论】:

标签: java


【解决方案1】:

一个java源文件必须至少有一个公共类并且文件应该被命名为class-name.java

不正确,顶级类不必声明为公共的。 JLS 声明;

如果顶级类或接口类型未声明为公共的,则只能从声明它的包内访问它。

请参阅http://java.sun.com/docs/books/jls/second_edition/html/names.doc.html#104285 第 6.6.1 节。

【讨论】:

  • 谢谢!那么你是说调用 main() 的人从某种包上下文中调用它吗?也就是说,调用 main() 的调用者(大概是 JVM)与我的 HelloWorld 类在同一个包中?只是糊涂!所以感谢您抽出时间回答我的问题。
  • 另外,你可以在一个java文件中定义多个非公共类。
  • 所以现在我的问题是:HelloWorld 是默认类中的一个包私有类,对吗?所以它应该可以从默认包内访问,但不能从默认包外访问,对吧?因此进一步推论,当 main() 被调用时,它必须是从 within 默认包中调用的,对吗?或者,调用 main() 的人与 HelloWorld 类在同一个包中。对吧?
【解决方案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 文件,但其中没有任何公共类。其中唯一的类是包私有类,而不是公共类。
  • 问题出在哪里?您可以在同一个包中创建另一个类(具有相同的效果)并使用该包私有类。
  • 再次,我的问题是不要在文件中添加任何新类。我只关心包私有访问。
  • 我编辑了代码,它不是文件中的新类,而是包中的。
  • 我的问题与您所说明的完全不同 :) 您所说的是正确的,但这不是我想知道的。我只是想知道为什么在文件中包含一个包私有类仍然可以编译。
【解决方案3】:

main 方法与任何其他方法一样。唯一的区别是它可以通过java 命令从命令行调用。即使从命令行看不到 main 方法,该类仍然可以像任何其他 Java 类一样使用,并且您的 main 方法可能被同一个包中的另一个类调用。因此,我认为它可以编译。

在 Java 中 main 函数在任何意义上都不是特别的。只存在一个终端命令,它能够调用称为 main 的静态方法...

【讨论】:

  • 现在,HelloWorld 类具有包私有的可访问性。因此,调用 main(JVM?)的人现在也必须在同一个包中,对吧?
  • 我直接从 java 类调用然后是的。然而,反射的规则略有不同。通过反射,可以调用任何非私有方法。 JVM 使用反射来调用你的 main 方法。
【解决方案4】:

这没什么好奇怪的。我想这种行为类似于某些 C/C++ 编译器的行为。

像“void main() { /.../ }”这样的代码将被这些编译器正确编译,尽管它不是符合标准的代码。简单来说就是编译器把“void”换成了“int”。

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

问候, 雄

【讨论】:

    【解决方案5】:

    非公共类有有效的用法。所以当你尝试编译文件时,编译器不会报错。

    【讨论】:

      【解决方案6】:

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

      Javabeginner.com 网站上有一篇关于该主题的文章 - 您应该熟悉 Java 中的访问修饰符,无论是从这个网站还是其他网站。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-09
        • 1970-01-01
        相关资源
        最近更新 更多