题
该方法的签名Java 主() 方法是:
public static void main(String[] args){
...
}
是有一个原因,这种方法是静态的?
解决方案
该方法是静态的,否则会出现歧义:应该调用哪个构造函数?特别是如果你的班级看起来像这样:
public class JavaClass{
protected JavaClass(int x){}
public void main(String[] args){
}
}
JVM应该调用new JavaClass(int)
吗?它应该通过什么x
?
如果没有,JVM是否应该在不运行任何构造函数方法的情况下实例化JavaClass
?我认为它不应该,因为这将特殊情况下你的整个类 - 有时你有一个尚未初始化的实例,你必须在每个可以调用的方法中检查它。
有很多边缘情况和含糊之处使得JVM必须在调用入口点之前实例化一个类。这就是为什么main
是静态的。
我不知道为什么public
总是标记为<=>。
其他提示
这仅仅是《公约》。事实上,甚至连名字主要(),和参数,通过纯粹的公约》。
当你在跑java.exe (或javaw.exe Windows),什么是真正发生的事情是一对爪哇地接口(JNI)的呼吁。这些呼叫中载的DLL是真的JVM(这是正确的-java.exe 不是JVM)。JNI的工具,我们使用的时候,我们必须桥虚拟机的世界,世界的C、C++、等等。反过来也是如此-这是不可能的(至少就我所知)实际上得到一个JVM运行而不使用JNI.
基本上,java.exe 是一个超级简单的C中的应用程序,分析的命令行,创建一个新的串列在JVM持那些参数,分析了类名指定为含有主(),使用JNI调,以找到主要的()方法本身,然后将调用的主要()方法,通过在新建立的串列作为一个参数。这是非常,非常喜欢你做什么的时候你使用反映从Java-它只是使用令人混淆名为当地功能的电话,而不是。
这将是完全合法的为你写你自己的版本java.exe (源分布与JAVA),并把它做完全不同的东西。事实上,这正是我们做什么与我们所有的Java的基础的应用程序。
我们每个Java应用程序都有其自己的发射器。我们主要这样做,这样我们得到我们自己的图标和进程名称,但它已经在便利在其他情况下,我们想要做的事情除了常规的主要()呼吁得到的东西去(例如,在一种情况下,我们正在做COM互操作性,我们实际上通过一COM处理为主()而不是一串阵列)。
因此,长期和短:原因是静态是b/c那是方便的。原因,它被称为'主要'是,它已经被什么东西,主要()为什么他们没有在老天的C(和在那些日子里,名称的功能 是 重要)。我想,java.exe 可以允许你只需指定一个完全合格的主要方法的名称,而不只是类(java com.(.Foo。someSpecialMain),但这只是使得它很难在IDEs自动侦测的'台发射'类中的一个项目。
main()
,C++
和C#
中的Java
方法是静态
因为运行时引擎可以调用它们而不需要实例化任何对象,所以<=>正文中的代码将完成剩下的工作。
为什么public static void main(String [] args)?
这就是Java语言的设计和Java虚拟机的设计和编写方式。
Oracle Java语言规范
查看第12章执行 - 第12.1.4节调用Test.main :
最后,在完成类Test的初始化之后(在此期间可能发生了其他相应的加载,链接和初始化),调用了Test的方法main。
方法main必须声明为public,static和void。它必须接受一个字符串数组的参数。此方法可以声明为
public static void main(String[] args)
或
public static void main(String... args)
Oracle Java虚拟机规范
Java虚拟机通过调用某个指定类的方法main并向其传递一个参数(即一个字符串数组)来开始执行。这会导致指定的类被加载(<!>#167; 2.17.2),链接(<!>#167; 2.17.3)到它使用的其他类型,并初始化(<!>#167; 2.17。 4)。方法main必须声明为public,static和void。
Oracle OpenJDK Source
下载并解压缩源jar并查看JVM的编写方式,查看../launcher/java.c
,其中包含命令java [-options] class [args...]
后面的本机C代码:
/*
* Get the application's main class.
* ... ...
*/
if (jarfile != 0) {
mainClassName = GetMainClassName(env, jarfile);
... ...
mainClass = LoadClass(env, classname);
if(mainClass == NULL) { /* exception occured */
... ...
/* Get the application's main method */
mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
"([Ljava/lang/String;)V");
... ...
{ /* Make sure the main method is public */
jint mods;
jmethodID mid;
jobject obj = (*env)->ToReflectedMethod(env, mainClass,
mainID, JNI_TRUE);
... ...
/* Build argument array */
mainArgs = NewPlatformStringArray(env, argv, argc);
if (mainArgs == NULL) {
ReportExceptionDescription(env);
goto leave;
}
/* Invoke main method. */
(*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
... ...
让我们只需假装, static
将不需要作用的进入点。
应用程序类就是这样的:
class MyApplication {
public MyApplication(){
// Some init code here
}
public void main(String[] args){
// real application code here
}
}
之间的区别码和构造 main
方法是必要的,因为在OO说话一个构造应确保,一个实例是 初始化 正确。初始化之后,实例可以用于预定的"服务"。把完成的应用代码转的构造将破坏。
因此,这种办法将力 三 不同的合同应该应用程序:
- 还有 必须 是的默认构造。否则,JVM不会知道的构造对话和哪些参数应该提供。
- 还有 必须 被一个
main
方法1.好吧,这是不足为奇的。 - 类 必须不 可
abstract
.否则,JVM不能实例。
的 static
方法在另一方面,只需要 一个 合同:
- 必须有一个
main
方法1.
这里既没有 abstract
也没有多个构造的事项。
由于Java被设计成一个简单的语言 用户 这并不奇怪,也应用的进入点已经设计成一个简单的方式使用 一个 合同,而不是在一个复杂的方式使用 三 独立和脆合同。
请注意:这种说法是 不 关于简化内部JVM或内部java运行环境.这一论点是关于简单的 用户.
1这里完整的签名数为只有一个合同。
如果不是,如果有多个构造函数,应该使用哪个构造函数?
有关 Java语言规范。
在调用main方法之前,不会实例化任何对象。使用static关键字意味着可以在不先创建任何对象的情况下调用该方法。
因为否则,它需要一个要执行的对象的实例。但它必须从头开始调用,而不首先构造对象,因为它通常是main()函数(引导程序)的任务,通常通过使用这些参数/程序参数来解析参数并构造对象。 p>
public static void main(String args[])
是什么意思?
-
public
是一个访问说明符,意味着任何人都可以访问/调用它,例如JVM(Java虚拟机。 -
static
允许在创建类的对象之前调用main()
。这是必要的,因为在创建任何对象之前,JVM会调用void
。由于它是静态的,因此可以通过类直接调用。class demo { private int length; private static int breadth; void output(){ length=5; System.out.println(length); } static void staticOutput(){ breadth=10; System.out.println(breadth); } public static void main(String args[]){ demo d1=new demo(); d1.output(); // Note here output() function is not static so here // we need to create object staticOutput(); // Note here staticOutput() function is static so here // we needn't to create object Similar is the case with main /* Although: demo.staticOutput(); Works fine d1.staticOutput(); Works fine */ } }
同样,我们在某些时候对用户定义的方法使用static,这样我们就不需要创建对象了。
-
String[] args
表示正在声明的args
方法 没有返回值。 -
String
指定<=>方法中的唯一参数。<=> - 包含类类型<=>的对象数组的参数。
醇>
让我以更简单的方式解释这些事情:
public static void main(String args[])
除applet之外的所有Java应用程序都从main()
开始执行。
关键字public
是一个访问修饰符,允许从类外部调用该成员。
static
是因为它允许在不必实例化该类的特定实例的情况下调用void
。
<=>表示<=>不返回任何值。
构建各种类型的Applet,midlet,servlet和bean,然后调用生命周期方法。调用main是对主类所做的所有操作,因此不需要在多次调用的对象中保存状态。把main写在另一个类上是很正常的(尽管不是一个好主意),这会妨碍使用类来创建主对象。
这只是一个惯例,但可能比替代方案更方便。使用静态main,调用Java程序所需要知道的是类的名称和位置。如果它不是静态的,你还必须知道如何实例化该类,或者要求该类具有空构造函数。
如果main方法不是静态的,则需要从程序外部创建主类的对象。你想怎么做?
使用java
命令
java ClassName argument1 argument2 ...
执行应用程序时,将其类名指定为java命令的参数,如上所述
JVM尝试调用您指定的类的main方法
<!>#8212;此时,尚未创建该类的任何对象。
将
main
声明为allows
静态invoke
JVM,以without
主instance
创建 一个ClassName
的班级。
让我们回到命令
command-line argument
是JVM的list of Strings
,告诉它要执行哪个类。在ClassName之后,您还可以将String[] args
(由空格分隔)指定为JVM将传递给应用程序的命令行参数。 - 这些参数可用于指定运行应用程序的选项(例如,文件名) - 这就是为什么在主
我认为关键字'static'使main方法成为一个类方法,而类方法只有一个副本,并且可以被所有人共享,而且,它不需要一个对象供参考。因此,在编译驱动程序类时,可以调用main方法。 (我只是在java的字母表级别,对不起,如果我错了)
main()是静态的,因为;在应用程序生命周期的那一点上,应用程序堆栈本质上是程序性的,因为还没有实例化的对象。
这是一个干净的名单。您的应用程序正在运行,即使没有声明任何对象(请记住,还有程序和OO编码模式)。作为开发人员,您可以通过创建对象的实例并根据编译的代码将应用程序转换为面向对象的解决方案。
面向对象非常适合数百万个显而易见的原因。然而,大多数VB开发人员经常使用<!>“goto <!>”等关键字的日子已经过去了。在他们的代码中。 <!> QUOT;转到QUOT <!>;是VB中的一个过程命令,由其OO副本替换:方法调用。
您还可以将静态入口点(main)看作纯粹的自由。如果Java已经足够不同来实例化一个对象并且在运行时只向你呈现该实例,那么你就没有选择但是编写一个程序性应用程序。正如Java听起来难以想象的那样,有很多场景需要采用程序方法。
这可能是一个非常模糊的回复。记住,<!> quot; class <!> quot;只是相互关联的代码的集合。 <!> QUOT;实例QUOT <!>;是一个孤立的,生活和呼吸的自主一代。
该protoype public static void main(String[])
是《公约》中定义的 捷尔思 :
该方法主要必须宣布公、静态和无效的。它必须指定一个正式的参数(§8.4.1)其声明的类型阵列的串。
在JVM规范 5.2.虚拟机开始了 我们可以读到:
Java虚拟机开始通过创建一个初始级,这是指定一个实现相关的方式,使用引导舱装载机(§5.3.1).Java虚拟机然后链接的初始级,初始化,并调用 公共类方法无效主(String[]).援引这种方法推动所有进一步的执行。执行Java虚拟机指令构成的主要方法可能会导致链接(并因此创建)的额外课程和接口,以及援引另外的方法。
有趣的事情,在JVM说明它没有提到,主要方法是静态的。但是在规范还说,Java虚拟机执行的2个步骤之前:
初始化的一类或接口,包括执行其类或接的初始化的方法。
在 2.9.特殊的方法 :
一个 类或接的初始化的方法 定义:
一类或接口最多的一类或接的初始化的方法和初始化(§5.5)通过调用这一方法。初始化方法的一类或口具有特别的名字
<clinit>
, ,需要有参数,并是无效的。
和一个 类或接的初始化的方法 是不同的 实例的初始化的方法 定义如下:
在Java虚拟机,每一个构造写的Java编程语言(捷尔思§8.8)的出现作为一个实例的初始化方法,该方法具有特别的名字
<init>
.
所以JVM初始化 类或接的初始化的方法 并不是一个 实例的初始化的方法 这实际上是一个构造。所以他们不需要提及的主要方法是静态的JVM规范,因为它暗示的事实,没有实例是创造之前呼吁的主要方法。
最近,类似的问题已经在程序员。SE
- 为什么一个静态的主要方法在爪哇和C#,而不是一个构造?
寻找一个明确的答案,从一个主要或次要的来源对于为什么没有(特别是)Java和C#决定有一个静态的方法,为他们进入点,而不是代表一个应用程序的实例的实例
Application
类与进入点被一个适当的构造?
TL博士 部分接受的答案是,
在爪哇的原因
public static void main(String[] args)
是,
- 小鹅 想
- 代码写的人的经验C(不在Java)
- 要执行通过某人用来运行 PostScript 上 新闻
对,理由是 间接相似 可以这么说。语言设计师不停的 程序的进入点 语法的熟悉程序员来自爪哇。C#建筑师 安德斯*Hejlsberg把它,...我们的方法与C#只是提供一个替代...Java程序员...
...
这只是一个惯例。如果这是惯例,JVM当然可以处理非静态主方法。毕竟,您可以在类上定义静态初始化程序,并在进入main()方法之前实例化zillion对象。
public
关键字是一个访问修饰符,允许程序员控制
班级成员的知名度。当一个类成员以private
开头时,那就是
成员可以通过声明它的类之外的代码访问。
main()
的反面是static
,它阻止成员被其类外部定义的代码使用。
在这种情况下,void
必须声明为<=>,因为必须调用它
程序启动时,通过其类外的代码。
关键字<=>允许 无需实例化类的特定实例即可调用<=>。这是必要的,因为在创建任何对象之前,Java解释器会调用<=>。
关键字<=>只是告诉编译器<=>不返回值。
任何应用程序的真正入口点都是静态方法。如果Java语言支持实例方法作为<!>“入口点<!>”,则运行时需要在内部实现它作为静态方法,该方法构造对象的实例,然后调用实例方法。 / p>
有了这个,我将检查选择以下三个选项中特定一个的理由:
- 我们今天看到的
static void main()
。 - 在新构造的对象上调用实例方法
void main()
。 - 使用类型的构造函数作为入口点(例如,如果条目类被称为
Program
,则执行将实际上由new Program()
组成。)
醇>
- 调用封闭类的静态构造函数。
- 调用静态方法
new ClassName()
。
醇>
- 调用封闭类的静态构造函数。
- 通过有效地调用<=>来构造封闭类的实例。
- 调用实例方法<=>。 醇>
- 调用封闭类的静态构造函数。
- 构造一个类的实例(然后对它做任何事情并简单地返回)。 醇>
故障:
main()
<=>
<=>
理由:
我将以相反的顺序执行此操作。
请记住,Java的一个设计目标是强调(尽可能需要)良好的面向对象编程实践。在此上下文中,对象的构造函数初始化对象,但不应对对象的行为负责。因此,给出<=>入口点的规范会通过强制设置<!>“理想<!>”来设置异常,从而混淆新Java开发人员的情况。每个应用程序的构造函数。
通过使<=>实例方法,上述问题肯定得到解决。但是,它要求规范列出条目类构造函数的签名以及<=>方法的签名,从而产生复杂性。
总之,指定<=>创建一个复杂性最低的规范,同时遵循将行为放入方法的原则。考虑实现一个<=>方法是多么简单,该方法本身构造一个类的实例并调用实例方法,将<=>指定为实例方法没有任何实际优势。
static - 当JVM调用main方法时,没有对象被调用,因此它必须有静态方法来允许从类调用。
我不知道JVM是否在实例化对象之前调用main方法...但是有一个更强大的原因,为什么main()方法是静态的...当JVM调用main方法时上课(比方说,人)。它通过<!>“ Person.main() <!>”来调用它。你看,JVM通过类名调用它。这就是为什么main()方法应该是静态的和公共的,以便JVM可以访问它。
希望它有所帮助。如果有,请通过评论告诉我。
静态方法不需要任何对象。它直接运行,因此直接运行。
使用main方法中的静态关键字,因为main方法中没有任何实例化。 但是对象是构造而不是调用,因此我们在main方法中使用静态关键字。 在jvm上下文中,当类加载到内存中时会创建内存。所有静态成员都存在于该内存中。如果我们现在使main为静态,它将在内存中并且可以被jvm(class.main(..))访问,因此我们可以调用main方法,甚至不需要创建堆。
这只是一个惯例,我们可以在这里看到:
方法必须声明为public和static ,它不能返回任何方法 值,它必须接受一个String数组作为参数。默认情况下, 第一个非选项参数是要调用的类的名称。 应使用完全限定的类名。如果-jar选项是 如果指定,则第一个非选项参数是JAR存档的名称 包含应用程序的类和资源文件 Main-Class清单标题指示的启动类。
http://docs.oracle。 COM / JavaSE的/ 1.4.2 /文档/ tooldocs /窗/ java.html#描述
public static void keywords意味着Java虚拟机(JVM)解释器可以调用程序的main方法来启动程序(公共),而无需创建类的实例(静态),并且程序不返回数据结束时的数据到Java VM解释器(void)。
基本上我们将那些数据成员和成员函数设置为STATIC,它们不执行任何与对象相关的任务。在main方法的情况下,我们将它作为STATIC,因为它与object无关,因为无论我们是否创建对象,main方法总是运行。
在Java中声明为static的任何方法都属于类本身。
同样,只能通过引用类Class_name.method_name();
因此,在访问静态方法之前,不需要实例化类。
因此main()方法被声明为static
,因此可以在不创建该类对象的情况下访问它。
因为我们使用main方法所在的类的名称(或程序应该从哪里开始执行)保存程序,适用于没有main()
方法()(高级)的类。所以通过上面提到的方式:
Class_name.method_name();
可以访问主要方法。
简而言之,当编译程序时,它会在所提及的类中(即通过程序的名称)搜索String
方法,其中包含main(String args[])
参数:<=>,并且从一开始它就具有没有实例化该类的范围,因此main()方法被声明为static。
来自 java.sun.com (有更多信息在网站上):
main方法是静态的,为Java VM解释器提供了一种启动类的方法,而无需先创建控件类的实例。程序启动后,在main方法中创建控件类的实例。
我的理解一直只是主要方法,就像任何静态方法一样,可以在不创建关联类的实例的情况下调用,允许它在程序中的任何其他内容之前运行。如果它不是静态的,你必须在调用它之前实例化一个对象 - 这会产生'鸡和鸡蛋'问题,因为main方法通常是你在程序开始时用来实例化对象的。