27

为什么Java中的main方法总是需要参数?为什么我们String[] args每次都要写,而不是在使用任何参数时才写?

像这样的方法会产生Main method not found编译器错误。由于我们从不对 main 方法使用任何参数,因此应该允许这样做。

public static void main()
{
}

这不是一个面试问题。它只是在编程时出现在我的脑海中。

4

8 回答 8

33

基本上,有四个答案:

  1. 因为它就是这样设计的。是的,我知道这是一个循环的原因。但关键是,这就是现状,而且不会改变。因此,除非您打算设计自己的语言,否则这个问题没有实际意义。

  2. 设计的清洁度(又名 DRY 原则)。当一个人可以完成这项工作时,不要指定两个入口点签名。很明显,它可以。

  3. 语义简单。假设(假设地)Java确实同时支持void main(String[])void main()入口点。如果一个类定义了这两种方法会发生什么?这是一个错误吗?如果不是,当有歧义时,哪一个优先?这还令人困惑吗?

    通过仅识别void main(String[]),JLS 避免了该问题1

  4. 这类似于标准的 C 和 C++ 入口点签名。(诚​​然,一些 C / C++ 运行时也支持其他非标准入口点......但这并不是一件好事...... IMO。)

这并不意味着以另一种方式做这件事肯定是错误的。例如,C# 为您提供替代签名,并通过要求开发人员以其他方式指定入口点来处理歧义问题。

FWIW,这个维基百科页面描述了多种语言的“主要”方法。


1 - 虽然你有一个“问题”,Java 新手可能会(错误地)猜测多个入口点应该工作,尝试一下,然后得到一个惊喜。但我认为任何设计都无法应对“猜测编程”。

于 2012-05-28T11:20:36.067 回答
5

因为java运行应用程序的工具会查找main具有特定签名的 a,所以它知道它调用的是正确的。Java 有方法重载,所以在查找方法时,必须指定一个相当完整的签名。假设该java工具可以做一些更复杂的事情(寻找特定的签名,如果没有找到它,则查找任何签名,main如果它只找到一个就调用它),但这不是 Java 设计者决定做的事情(主观上,FWIW,我认为这是最好的——保持简单)。

您可以在 Java 语言规范第 12 章:执行中找到详细信息。请注意,当 Java 获得变量参数列表时,可以以main两种不同的方式声明:

public static void main(String[] args)
// or
public static void main(String... args)
于 2012-05-28T10:36:37.293 回答
0

当 JVM 开始执行 java 程序时,它会搜索具有此签名的 main 方法(即字符串数组)

于 2012-05-28T10:38:30.587 回答
0

这只是他们设计的方式。由此推论,您可能会问为什么它的表亲(C#)允许带或不带参数的 Main 方法,这正是他们设计的方式。

那里没有严肃的理由,每个语言设计者都有自己的偏好,您应该遵循哪些原则。有时这是由我们推断或同时坚持(有时我们无法按照自己的方式行事)。

嗯……这让我想起了我现在正在使用的操作系统。在 OS X Lion 之前,您只能在窗口的右下角调整大小。在他们最终在其操作系统上的任何窗口角落调整大小之前,他们等待了 28 年以上。

即使我非常喜欢 Mac OS,我也不会在一个窗口只能在一个角落调整大小之前为他们的立场辩护。狂热是一回事,但盲目的坚持是另一回事。

因此,您正在练习批判性思维,而不是盲目地相信 Java 的主要方法签名是唯一正确的方法,这是一件好事


一个题外话,等待 Mac 在任何角落都有可调整大小的边缘类似于我等待 Java 拥有一流的属性。尽管有 JSON 名称(Java Script Object Notation,当然 Javascript 不是 Java),但 C# 对象初始化器(通过其属性初始化器和集合初始化器)与使用 JSON 的 Java 对象初始化器相比更接近 JSON。C# 对象初始化器非常简洁,非常类似于 JSON。

C#

var p = new {
    Lastname = "Lennon",
    Firstname = "John",
    PlacesBeen = 
        new[]
        {
            new { City = "Liverpool", Country = "England" },
            new { City = "New York", Country = "US" },
            new { City = "Tokyo", Country = "Japan" }
        }
};

return Json(p);

Javascript:

var p = {
    "Lastname" : "Lennon",
    "Firstname" : "John",
    "PlacesBeen" :             
        [
            { "City" : "Liverpool", "Country" : "England" },
            { "City" : "New York", "Country" : "US" },
            { "City" : "Tokyo", "Country" : "Japan" }
        ]
};

因此,借助 C# 的一流属性(不拘泥于方法)和集合初始化器,不仅代码变得简洁明了,而且现在与大多数开发人员现在使用的数据交换格式(即 JSON)非常相似。

Java 的对象初始化器语法与 JSON 风格相去甚远。我不会在这方面为 Java 的设计决策(例如属性语法/设计)辩护:-)

因此,与我不会为 Java 语言设计者对 Java 属性语法/设计的设计决策辩护一样,我也不会辩护public static void main(String[] args)ツ</p>

于 2012-05-28T10:53:51.400 回答
-1

当您尝试运行 java 程序时,JVM 将使用字符串数组作为参数搜索 main 方法,以从那里开始执行程序。由于您给出的方法没有该签名,因此它会引发异常No main method found

于 2012-05-28T10:39:40.287 回答
-1

我认为 Java 从 c/c++“复制”了这个习惯,并在 java.c 中硬编码:

  /* Get the application's main method */
  mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
                                     "([Ljava/lang/String;)V");
  if (mainID == NULL) {
      if ((*env)->ExceptionOccurred(env)) {
          ReportExceptionDescription(env);
      } else {
        message = "No main method found in specified class.";
        messageDest = JNI_TRUE;
      }
      goto leave;
  }
于 2012-05-28T10:40:30.783 回答
-1

java就是这样设计的。如果我们不写字符串 args[] ,那么程序将被编译但不会运行。

于 2013-11-05T15:57:57.870 回答
-1

它可能是因为大多数输入来自 main() 外部,例如来自命令行参数,因此要捕获这些值,它具有 String[]args 签名。

于 2015-09-24T04:25:40.610 回答