问题 静态内部类中的主要方法。


我了解到Java文件中唯一的公共类也必须具有main方法。但是,在下面你可以看到内部类中的main方法而不是? 关于源文件中主要方法定义的规则是什么?

public class TestBed {
    public TestBed() {
        System.out.println("Test bed c'tor");
    }

    @SuppressWarnings("unused")
    private static class Tester {
        public static void main(String[] args) {
            TestBed tb = new TestBed();
            tb.f();
        }
    }

    void f() {
        System.out.println("TestBed::f()");
    }
}

9731
2018-02-03 08:56


起源

如果你把那个内部类公开,那应该有用。 - Thilo
它按原样工作。在我的情况下,我不得不逃避 $ 从shell启动的字符: $ java TestBed\$Tester - Vlad
@Thilo - NESTED课程的需要 不公开。公开只适用于(非常)第一版Java。如今Java是 聪明 足以在私有类中找到该方法(在Windows XP上使用Java 5,6和7进行测试) - Carlos Heuberger
“现在Java非常聪明,可以在私有类中找到这种方法”。我不知道这是不是很聪明。将课程设为私有可能是有原因的。我希望,这种方法本身仍然需要公开。 (OTOH,除非我们讨论远程访问,类可见性是一种代码结构化工具,而不是安全功能,所以在这种情况下哪种方式都可以) - Thilo
@Thilo:d'accord - 这就是我写的原因 聪明 斜体......是的,这个方法必须是公开的,至少作为文件的记载 java的 甲骨文的工具。 - Carlos Heuberger


答案:


如果你想用java启动一个类(Java启动器:java test.MyClass),那么这个类必须有一个带有众所周知签名的main方法。

您可以在任何地方使用相同签名的main方法。但不要指望发射器能找到它。

附:语言的名称是Java,而不是JAVA。

有一个小细节:

你可以这样做:

package test;

public class Test {

    /**
     * @param args the command line arguments
     */
    static public class A {

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

java test.Test $ A.

但这是非标准的......


5
2018-02-03 09:04



我想知道它是否适用于这种情况,因为包含main方法的类是私有的,静态的并且不在任何地方使用。 - Kurt Du Bois
@KurtDuBois - 它可以工作,但你必须使用正确的类名 TestBed$Tester 开始吧 - Carlos Heuberger
请注意,在* nix shell中运行时,您可能不得不逃避 $: java test.Test\$A。 - T.J. Crowder


任何可以拥有静态方法的类都可以拥有 public static void main(String[] args)

这包括:

顶级课程(无论是否公开),例如

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

和内部静态类(无论是否公开)(如你的例子)。

它不包括:

  • 匿名课程
  • 内部非静态类

所以这些都是非法的:

public class Foo {
    private Object bar = new Object() {
        public static void main(String[] args) {
            System.out.println("Hello");
        }
    };
}


public class Foo {
    private class Bar {
        public static void main(String[] args) {
            System.out.println("Hello");
        }
    };
}

4
2018-02-03 09:11



迂腐: 内部阶级  能够 不 有一个静态方法 - JLS 8.1.3: [...]Inner classes may not declare static initializers (§8.7) or member interfaces[...]。没有 内在的静电 类,根据定义(再次JLS 8.1.3)a 内心阶级 是一个非静态嵌套类。 - Carlos Heuberger
@CarlosHeuberger你是对的。我的术语很草率,使用'内部'这个词与'嵌套'一起使用。 - Chris B
让我们说公共类有main方法,类有一个带main方法的静态内部类。 JVM如何查找并运行具有main方法的类?它是如何解决这两个类的? - user3705478
JVM运行您在命令行上指定的类的主方法,即 java OuterClass 与 java OuterClass$NestedClass。 - weibeld
静态嵌套类几乎完全独立于其封闭类。为方便起见,它只是在另一个类中声明,但行为类似于在自己的文件中声明为顶级类。看到 Oracle Java教程。 - weibeld


每个Java应用程序都必须有一个main方法。它是在应用程序中执行代码的起点。它的方法签名是:

public static void main(String[] args) 

静态内部类是在不同类的定义内定义并标记为静态的类。

例如,如果外部类名为TestBed,那么名为Tester的内部类TestBed将被编译为TestBed $ Tester.class。 .class文件的分离意味着您可以将补充的嵌套代码与主外部类紧密耦合。

它们位于相同的源文件中,内部类实际上位于外部类中。所有这一切,您不必支付任何类型的部署或运行​​时间成本。

通过使用静态内部类,您可以为系统添加其他支持功能,以实现测试等功能,同时在正常的生产部署中不会受到任何处罚。

要执行该TestBed.Tester类的main()方法,

% java TestBed$Tester

2
2018-02-03 09:02



迂腐:根据定义(JLS 8.1.3)an 内心阶级 是一个嵌套类 不 声明 static! - Carlos Heuberger


这很有趣,因为代码将在Eclipse中编译和运行,但只能使用命令行进行编译。从eclipse运行时,它将从内部类中找到静态main方法并运行它。

但是跑步的时候 java TestBed 从命令行你会得到错误 - Exception in thread "main" java.lang.NoSuchMethodError: main 这是一个有效的错误,因为您没有在主类中定义main方法。

为什么要在内部类中定义main方法?你的主要方法应该在公共类中定义,这不是一个规则,而是常见的做法。

在下面的代码中,我将main方法移动到外部类,它在Eclipse和命令行中都有效:

public class TestBed {
    public TestBed() {
        System.out.println("Test bed c'tor");
    }

    @SuppressWarnings("unused")
    private static class Tester {

    }

    public static void main(String[] args) {
        TestBed tb = new TestBed();
        tb.f();
    }

    void f() {
        System.out.println("TestBed::f()");
    }
}

-1
2018-02-03 09:14



错了:命令行 - java TestBed$Tester  - 工作正常(Windows XP,Java 6和7),并且不需要将主要方法公开的类。 - Carlos Heuberger
当然java TestBed $ Tester工作正常,java Tester不会。 “没有必要让主要方法公开的班级”我意识到它不需要,我只是建议什么是常见的做法,至少在我看到的情况下。我从未见过需要声明主类“最终”或“抽象”。 - blue-sky
当然 java Tester 在Eclipse中也不会工作。您必须使用完全限定的正确类名。而且你不仅仅是 "just suggesting what is common practice"  - 你写了它 will only compile from using the command line (但不执行) - 这是错误的 - 它从命令行运行!那么“最终”还是“抽象”呢?你是第一个在这里使用这些术语的人(BTW摘要不能用static编译,而main必须是静态的)。 - Carlos Heuberger
该类(最初发布)将在Eclipse中编译和运行。 Eclipse自动查找内部类并执行其main方法,但是从命令行运行必须将其指向内部类main方法。 “它从命令行运行”是的,它从命令行运行,但你需要将它指向内部类。当您通过Eclipse运行java类时,如果main方法在内部类中,或者main方法在外部类中,则它运行时没有错误。我接受你的观点 - blue-sky
当然,你总是必须指向正确的类,无论是外层还是NESTED ......在Eclipse中都是一样的。仅仅因为Eclipse发现它,并不意味着你不必指向该类。看看有两个人会发生什么 main 方法,一个在外层,第二个在嵌套类中!但这不是相关的。你写道它不是从命令行运行的,而且main必须在公共类中声明 - 两者都是错的(无论你是否想要别的东西)! - Carlos Heuberger