Java中类加载时静态方法的初始化

8

我对静态方法有疑问。在下面的程序中,输出将为:main。我理解这是因为main是静态方法,所以当类加载时,它被执行。如果是这样,同样的原则也应该适用于met(),对吗?因为它也是静态的。为什么只有main在类加载时执行,而met()却不执行呢?

public class Test {

    static void met() {
        System.out.println("method");    
    }

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

因为它是 main() - timrau
main(String[]) 是第一个被调用的方法。它必须是静态的,但这并不意味着所有静态方法都会被调用。它还必须返回 void,但这并不意味着所有返回 void 的方法都会被调用。它必须有一个 String[] 作为唯一参数,但这也并不意味着所有带有 String[] 的方法都会被调用。 - Peter Lawrey
main是一个特殊的方法。它在JVM启动时被调用。请查看Java语言规范第12章执行 - default locale
请检查我的答案,我解释了静态方法是什么。 - gprathour
12个回答

18

不,这不是正确的。

当类被加载时,这两种方法都不会被调用。

只有当你执行类Test时,main()才会被调用。

当类被加载时,只有静态初始化器会被调用。静态初始化器长这样:

static
{
    //code here
}

在执行main()方法之前,会加载一个类,因此它的静态初始化程序会在main()方法之前运行。以下代码片段将说明这一点。

public class TestA
{
    static
    {
        System.out.println( "hello" );
    }

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

简明有效的解释!+1 - Ved
你遵循了KISS原则,用尽可能少的词语涵盖了所有方面。太棒了,赞一个! - ADTC

9

让我详细解释一下

方法类型 基本上有两种类型的方法,

  1. 实例方法
  2. 类方法

实例方法 属于对象,您总是需要一个对象/实例来调用这些方法。

静态方法 是类方法,它们可以通过类名直接调用,无需拥有类的实例来调用它们。

例如:

class Demo{
    public void sayHello(){
         System.out.println("Hello");
    }

    public static void sayHi(){
         System.out.println("Hi")
    }

    public static void main(String args[]){
          Demo.sayHi();    //Call to static/class method

          Demo.sayHello(); //It will not work

          Demo d = new Demo();
          d.sayHello();    //It will work.
    }
}

但是,当类加载时,没有一个静态方法会自动调用。

两者之间的主要区别

在内存中,静态方法只有一个副本可供所有对象使用。但是,每当创建对象时,都会为该对象创建一个新的实例方法的副本,因此每个对象都有其自己的实例方法。与实例和类变量类似。

静态方法不是自动运行的,而是被所有对象共享。为什么会调用main()方法呢?因为它是程序的入口点。

除此之外,还有一个静态块,它只在类加载时自动调用一次。

示例

class Main{
     static{
           System.out.println("static block");
     }

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

输出结果将会是:

静态代码块

主函数


1
需要进行一些清理,但是回答非常全面和周到。赞扬你涵盖了所有方面! - ADTC

5

完全不是。仅当该特定类作为入口点运行时,主方法才会运行。

只有在调用met()方法之后,它才会运行。它与实例方法的主要区别在于,您无需创建类的实例即可运行它,只需通过类本身运行即可:Test.met();

你所说的是静态块:

private static String description;

static{
  description = "this runs on loading the class";
}

5
由于main()方法是静态的,它不是因为被执行而被执行,而是因为它是任何Java程序的入口点。如果你想让某些东西运行,你需要从main方法中调用它。当执行类时,不会自动调用其他方法。

没有其他东西会自动执行 这个语句可能会让 OP 产生其他的困惑,因此需要进行一些详细的解释。 - gprathour
1
这与他的困惑有关,因为他将两者混淆为“同一件事”。因此,你应该解释“两者”。如果你只解释了main方法作为入口点执行的原因,那么提问者就会对他听说过的“静态块”感到困惑。他错了吗?现在他有了一个新但相关的困惑来源。清晰明了地解释main方法、static方法和static块以及它们之间的所有区别可以消除所有的困惑,并且总是更好的答案。 - ADTC
“仅此自动执行,没有其他内容。” - 这并不是真的。 - jr.
1
@studro 感谢您的反馈,我已经更新了最后一条陈述,使其更加精确。 - Cameron
1
我想知道你为什么感谢Studro,因为他说的和我和@ADTC说的一样。 - gprathour
显示剩余4条评论

3
您可以使用 静态代码块 代替静态方法,在主方法之前打印它,就像这样 -
public class Test
{

static{
 System.out.println("method");
}

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

}

2

如果您想在加载时执行,只需将其初始化为static块:

static{
System.out.println("method");    
}

因为静态块是在类加载时执行的。在其他静态方法中,main() 优先级最高。

2

met() 是一个静态方法,它会在类加载时被加载到内存中,你需要调用它。你可以使用 static block 来打印 "method"。


(说明:该段内容讲解了静态方法的特点和如何调用以及使用静态块打印信息)

1

并非所有静态方法都会在程序运行时被默认调用。

来自文档

The java tool launches a Java application. It does this by starting a Java runtime environment, loading a
specified class, and invoking that class's main method. The method declaration must look like the following:

  **public static void main(String args[])**

因此,JVM将调用main函数,并且需要有人调用met()以使其执行。

附注:在支持它的Java版本中,也允许基于varargs的声明。例如:public static void main(String... args)。无论如何,“必须看起来像”只是一个指导方针。唯一的规则是它应该是公共的,它应该是静态的,它应该返回void,它必须被命名为main,并且它的参数是一个字符串数组。其余的由你决定,所以这是完全正确的:static public void main(String[] wondrousThings) throws CrappyThingsException, SomeOtherException - ADTC

1

静态方法、静态块和静态变量之间有区别。如果您不调用静态方法,它将不会打印。

要使其打印,您需要调用Test.met();

或者您可以将其设置为静态块

例如:

static {
   System.out.println("static block");
}

这将在Test加载时立即调用。


1
当你仅调用静态方法时,不会调用任何静态方法,你正在混淆静态初始化程序和静态方法。
它打印主要是因为当你运行Java应用程序时,它会调用main()方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接