【问题标题】:Why doesn't Java's main use a variable length argument list?为什么 Java 的 main 不使用可变长度参数列表?
【发布时间】:2011-01-13 04:30:57
【问题描述】:

我对 Java main 声明的语法有疑问:

public static void main (String[] args)

既然你可以在调用主函数时传递可变数量的字符串,这不应该是一个可变长度的参数列表而不是一个数组吗?为什么使用字符串参数列表对该方法的命令行调用甚至可以工作? (除非有幕后处理使用字符串列表构建一个数组,然后将该数组传递给 main 方法......?) main 声明不应该更像这样......? -

public static void main(String... args) 

【问题讨论】:

  • 我猜这是一个向后兼容性问题...
  • 我真的不认为你应该自己调用主函数......它应该从VM调用。
  • 我自己不调用主函数。我不认为这是可能的。我想这确实是一个关于 Java 内部工作原理的问题......
  • 很多人都在说“你永远不会从代码中调用 main”。这不是真的,只是很少见。通常我会看到在插件/运行时加载场景中从代码调用 main,类似于 jUnit 在运行时加载新代码的方式。 (仅供参考,我在这里做了一个很大的假设,即 jUnit 像 NUnit 一样工作。Java 听起来很酷,但我只使用过 C# :)
  • 谢谢大家的回答和cmets!自从我第一次了解可变长度参数列表以来,这个问题一直困扰着我,感谢大家帮助我理解它。

标签: java main variadic-functions


【解决方案1】:

main(String... args) 和 main (String[] args) 实际上是同一件事:你得到的是一个 String 数组。可变参数只是调用者的语法糖。

我猜你从来没有从代码中调用main(),所以在引入可变参数时它没有被改造。

编辑:实际上,把最后一句话删掉。 main(String... args) 当然是完全有效的语法。这两种风格是完全可以互换的。这工作得很好:

public class Test {

    public static void main(String... args) {
        System.out.println("Hello World");
    }

}

【讨论】:

  • 所以当你从命令行执行一个程序时,你实际上并没有直接调用主程序吗?在 main 执行之前发生了一些处理? (即从传递的字符串构建数组)
  • 您没有使用 Java 调用 main() 方法。运行时会为您调用它。
  • “永远不要从代码中调用 main()”:)。和不。您不能从命令行调用 Java 方法。事实上,命令行是一个解析你的命令的程序,告诉操作系统执行一些带有一堆参数的程序,并且那个程序(例如 java.exe)将很多东西加载到内存中(类定义等),创建系统程序执行 args 命令行接收的 Java 友好表示,最后调用 main 方法。所以不行。您实际上并没有直接调用 main。
  • 我对从代码调用 main 没有太多意见——这似乎不是你想做的事情,但在某些情况下它应该是完全有效的(对于例如,导致一个程序从另一个程序内部或作为它自己的实体运行)。 @helios 你有现实生活中的经验,甚至有过这个问题的理论例子吗?
  • 当然,您可以从代码中调用“main”,这样做可能非常有意义。例如,考虑一个 Java 实用程序在一系列一个或多个类中调用“main”。你会怎么写?另一个例子是编写粘合到现有 Java(命令行)实用程序上的 Ant 任务。
【解决方案2】:

你可以用任何一种方式声明 main,它工作得很好。不存在“向后兼容性”或“改造”问题。但是,您的代码的读者可能会觉得它分散了注意力,并且不太可能以任何方式改进您的程序。

The Java Language Specification (third edition) section 8.4.1 表示“如果最后一个形参是 T 类型的可变参数,则认为定义了 T[] 类型的形参”。

Java 程序如何启动的规范在 JLS 12.2 中,它引用了 VM 规范的第 5 章。 VM spec section 5.2 表示 VM 调用公共类方法“void main(String[])”。由于 VM 规范没有变量数量的概念,因此使用“...”声明的 main 满足要求。

【讨论】:

    【解决方案3】:

    main 方法是为 Java 1.0 设计的。

    “...”语法是在 Java 1.5 中引入的

    它是通过您定义的类型的数组实现的(我猜,但是...如果 Java 1.4 和 1.5 字节代码兼容,那么它必须用数组实现)。

    【讨论】:

      【解决方案4】:

      没有Java的main方法,实际上你可以在你的main方法中将数组声明为可变参数:

      public static void main(String... args) { System.out.println("Hi!"); }
      

      【讨论】:

      • 有趣。从其他答案/cmets 来看,我猜这个新的主要声明语法是在 Java 1.5 中添加的。所以 Java 运行时会根据你的 main 方法声明来决定是将字符串直接传递给 main 还是先构建一个数组?
      • 可变参数是在 Java 5 中作为数组的语法糖引入的,这意味着它们隐藏了实际的数组,但在下面,它是相同的,这就是它起作用的原因。另见java.sun.com/j2se/1.5.0/docs/guide/language/varargs.html
      • 没有。它总是构建一个数组。这只是表达完全相同的底层代码的不同语法。 Java 仍然会将命令行 args 解析为字符串数组,加载引用的类,找到它的 main 方法,并使用 args 调用它。
      • @froadie:不,它总是构建一个数组。 String... args == String[] args,就被调用的方法而言。参数无论如何都是一个数组。
      【解决方案5】:

      java 主要语法早于 varargs,它只在 java 1.5 中引入。

      【讨论】:

        【解决方案6】:

        主要声明不应该更像这样吗...?

        public static void main(String... args) 
        

        实际上,这可以毫无问题地完成。

        在引入 var args 之前是 String [] args,但现在两者都可以工作。

        【讨论】:

          【解决方案7】:

          嗯,第二种语法只是第一种语法的变体,是的,它会很好,但目前它还没有内置到 Java 中

          【讨论】:

            【解决方案8】:

            你为什么在乎?没有人手动调用 main 方法。它是 Java 内部的。

            编辑:我想现在没关系,因为您可以将 main 方法定义为:

            public static void main(String... args);
            

            我的观点仍然有效,因为没有人明确调用 main。

            【讨论】:

            • 除非你从当前类中调用另一个类的 main 方法...毕竟你可能想要这样做。
            • 我明确地调用“main()”——理论被破坏了
            猜你喜欢
            • 2020-06-05
            • 2011-09-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多