首页 > 试题广场 >

以下代码执行后输出结果为( )

[单选题]
以下代码执行后输出结果为( )
public class Test
{
    public static Test t1 = new Test();
    {
         System.out.println("blockA");
    }
    static
    {
        System.out.println("blockB");
    }
    public static void main(String[] args)
    {
        Test t2 = new Test();
    }
 }

  • blockAblockBblockA
  • blockAblockAblockB
  • blockBblockBblockA
  • blockBblockAblockB
类加载 如果实例化静态类,就不会执行下一个静态块,都是类加载时加载
编辑于 2018-07-02 09:34:49 回复(0)
更多回答
1.首先,需要明白类的加载顺序
(1) 父类静态对象和静态代码块
(2) 子类静态对象和静态代码块
(3) 父类非静态对象和非静态代码块
(4) 父类构造函数
(5) 子类 非静态对象和非静态代码块
(6) 子类构造函数
其中:类中静态块按照声明顺序执行,并且(1)和(2)不需要调用new类实例的时候就执行了(意思就是在类加载到方法区的时候执行的)
2.因而,整体的执行顺序为

public static Test  t1 = new Test();         //(1)
static
{
System.out.println("blockB");                //(2)
}
Test t2 =new Test();                             //(3)
在执行(1)时创建了一个Test对象,在这个过程中会执行非静态代码块和缺省的无参构造函数,在执行非静态代码块时就输出了blockA;然后执行(2)输出blockB;执行(3)的过程同样会执行非静态代码块和缺省的无参构造函数,在执行非静态代码块时输出blockA。因此,最终的结果为
blockA
blockB
blockA


编辑于 2017-05-18 16:03:06 回复(36)
静态块:用static申明,JVM加载类时执行,仅执行一次
构造块:类中直接用{}定义,每一次创建对象时执行
执行顺序优先级:静态块>main()>构造块>构造方法
静态块按照申明顺序执行,先执行Test t1 = new Test();
所有先输出blockA,然后执行静态块,输出blockB,最后执行main
方法中的Test t2 = new Test();输出blockA。
发表于 2017-07-11 09:29:41 回复(42)
我认为是,t2执行然后后先加载t1,为什么先输出A是因为在加载t1的同时B静态块也加载过了。t1完了然后输出B,最后输出那个A
发表于 2022-03-03 23:33:42 回复(0)
静态块:用static申明,JVM加载类时执行,仅执行一次
构造块:类中直接用{}定义,每一次创建对象时执行
发表于 2019-11-08 14:46:27 回复(0)
 public class Test
{
    public static Test t1 = new Test();//静态变量

        //构造块
    {
        System.out.println("blockA");
    }

        //静态块
     static
    {
        System.out.println("blockB");
    }
    public static void main(String[] args)
    {
        Test t2 = new Test();
    }
}
静态域:用staitc声明,jvm加载类时执行,仅执行一次
构造代码块:类中直接用{}定义,每一次创建对象时执行。
执行顺序优先级:静态域,main(),构造代码块,构造方法。
1 静态域 :首先执行,第一个静态域是一个静态变量 public static Test t1 = new Test(); 创建了Test 对象,会执行构造块代码,所以输出blockA。然后执行第二个静态域(即静态代码块)输出blockB。
2 main():Test t2 = new Test()执行,创建Test类对象,只会执行构造代码块(创建对象时执行),输出blockA。
3 构造代码块只会在创建对象时执行,没创建任何对象了,所以没输出
4 构造函数:使用默认构造函数,没任何输出

所以结果为ABA
发表于 2018-03-30 20:25:00 回复(18)
初始化类的时候,首先在其他任何事物发生之前,将分配给对象的存储空间初始化为二进制的0。所以加载时,对t1初始化为null,对static静态块做了初步的初始化,但是还未执行里面的代码。然后按照静态变量的初始化顺序,首先对t1进行具体的初始化,由于static静态块已经进行了初步的初始化,所以这时候是直接跳过这里的,所以首先输出 blockA,然后初始化t1后,执行到static静态块之后,再执行里面的内容,所以输出blockB,最后执行普通的初始化块blockA.
发表于 2017-05-18 20:26:58 回复(17)

答案是 blockAblockBblockA

首先区别<clinit>是类初始化,<init>是实例初始化

类装载准备阶段->类初始化clinit阶段

类装载准备阶段:变量赋系统要求的初始值(0或者null等),final变量会在此时赋用户定义的初始值

类初始化<clinit>过程:

Step1 编译器收集t1的赋值动作,static语句块,main方法语句块

Step2 执行收集好的语句块:

Step2.1 执行t1 = new Test,发现clinit过程已经调用,于是可以开始触发init过程,执行成员变量的初始化(此处没有),以及非静态代码块,输出blockA,最后调用构造函数(此处没有)

Step2.2 按照顺序,执行static语句块,输出blockB

Step2.3 按照顺序,执行main方法语句块,执行t2 = new Test,触发init方法,执行非静态代码块,输出blockA

编辑于 2017-08-09 17:45:22 回复(16)
之前有疑惑,觉得输出应该是BAA。 在网上查了一下,学习了个新名词,叫构造代码块。构造块:直接在类中定义,且没有加static关键字的代码块。构造代码块在创建对象时被调用,每次创建对象都会被调用,并且构造代码块的执行顺序要优于类构造函数。 在创建t1时,新建一个对象,所以调用了构造块,输出了A。所以顺序成为了ABA。 以上为个人见解,不对之处请指出。
发表于 2017-06-29 14:25:09 回复(11)
这个题看了很多人的解释,都没解释清楚,下面写出我的理解:我先来修改一下代码,把test2注释掉,这样有助于理解:

 答案是:blockAblockB,下面我来解释:
首先弄懂一个概念:静态成员变量,静态代码块是一个级别的,谁在前面先执行谁,test1是静态成员变量,在第一行。当我们运行程序的时候,类开始加载,加载类的时候加载静态的东西,test1是Test类的静态成员变量,并且在第一行,那么先加载它,test1=new Test(),这里只看等号的右侧,因为是new所以是创建Test的对象,创建对象的时候使用init,而在init中,构造代码块是优先于构造方法,所以先走构造代码块,(估计很多同学就卡在这里了,说为啥不走下面的satic{},输出“blockB”。因为这里就是单纯的创建对象,创建对象只走init只走init,只走init,init只包含构造代码块和构造方法不包含下面的static,所以输出““blockA”)输出“blockA”,接着走构造无惨构造,走完后,完成test1的创建,将地址值赋值给test1,至此,静态成员变量test1结束;然后接着往下,执行下面的静态代码块,输出“blockB”。至此,类加载结束,控制台上看到的是blockAblockB。
 -----------------------分割线----------------------------------------------
打开注释回到原题:
    上面已经说的很清楚了,我们运行代码,开始加载类控制台上输出blockAblockB,然后创建test2对象,因为静态的东西只执行一次,所以到test2=new Test()的时候,就不会再走静态成员变量test1和静态代码块了,直接就是init创建test2,走构造代码块,输出“blockA”,然后走构造方法,程序结束,最后控制台上就是:blockAblockBblockA;
我讲的都是口头语,更容易懂一点,如果错了,别喷我0.0
发表于 2021-05-17 16:35:11 回复(11)
编辑于 2017-05-16 20:55:48 回复(0)
对于这道题,我的理解是这样的。由于类在加载时,先执行的是静态类,然后是静态代码块(只执行一次),接下来执行非静态的代码块,最后执行构造函数。在这道题中,由于有一个
public static Test t1 = new Test(); 
所以会先执行这个静态类,但是这个类的静态代码块是有类Test来执行的所以它就跳过执行静态代码块,
转而执行非静态代码块也就是先输出 blockA。然后,到类Test执行静态代码块所以接着输出了blockB。接下来由于main函数里执行了
Test t2 = new Test(); 
由于静态类和静态代码块都已经执行过了,所以接下来就是执行非静态的代码块,所以就又输出了blockA
综上所述,执行的就过就是 blockA blockB blockA

发表于 2017-05-31 15:34:10 回复(5)
在JDK1.8中运行答案确实是ABA,当把t1去掉时,很明显输出的BA,根据我单步调试的过程发现,第一个A是在创建t1时输出的、然后再输出后面的BA,但创建t1时为何只输出A呢,我很迷惑。
编辑于 2017-05-18 10:24:37 回复(11)
执行顺序:
1,先执行静态变量public static Test t1 = new Test();
    1.1,在new的时候执行构造块
        {
            System.out.println("blockA");//构造块:在new的时候调用
         }
2,执行静态块
        static {
            System.out.println("blockB");//只会执行一次
        }
3,执行Test t2 = new Test();
    3.1  在new的时候执行构造块
        {
            System.out.println("blockA");
         }

所以结果:blockAblockBblockA

PS:构造块在new对象时执行。
发表于 2017-12-06 14:09:06 回复(2)
1、JVM类加载机制中有讲,类加载的最后一个阶段是初始化阶段,即为真正执行java 代码的时候终于到了。
2、这一阶段,会依次执行2个方法:<clinit>()方法和<init>()方法。
3、<clinit>()方法:是编译器自动收集类中的所有类变量和静态语句块(static{})中的语句合并而成的。知道这一点很重要,而<clinit>()方法里面语句的顺序由源程序代码决定。<clinit>()方法和类实例构造器<init>()方法是不同的。同一个类加载器,一个类型只会初始化一次,对应此方法只被调用一次。
4、<init>()方法:涉及到实例代码块、构造方法的调用的执行。同时,实例化几次类,则进行“实例代码块”和“构造器方法”的几次调用,并且,“实例代码块”优先于“构造器方法”的调用。
本程序中,实例代码块是:
{
System.out.println("blockA");
}
编辑于 2017-07-24 21:07:12 回复(0)
都没说到重点

这里涉及到一个知识点
类加载阶段的初始化阶段 编译器会按从上至下的顺序,收集所有 static 静态代码块和静态成员赋值的代码,合并为一个特殊的方法 < cinit> ()V 
题目中的
static
    {
        System.out.println("blockB");
    }
在 t 2 创建时中就已经被合并到 < cinit> ()V 中了,用于后续的执行 且只执行一次
因此创建t 1时,没有抢先执行 blockB,blockB 的所有权早已被 t 1 夺走了 ;

发表于 2021-09-30 14:33:11 回复(1)
他们的讨论太复杂,就先执行static代码块,且按顺序执行,最后再执行main方法,就这么简单
发表于 2018-04-12 17:17:25 回复(1)
t2初始化Test,输出blockAblockB、t1初始化,输出 blockA。
发表于 2017-05-16 20:35:58 回复(4)
静态块:jvm加载类时执行,仅执行一次;
构造代码块:类中直接用{}定义,每一次创建对象时执行;
本题执行过程:
    Test t2 =newTest();,此时,jvm需要加载Test类到方法中,然后根据加载类的过程。先加载静态成员变量和静态代码块,即执行publicstaticTest t1 =newTest();,新建一个对象。因为构造块在每次新建对象时执行,则,输出blockA,再加载静态代码块,输出blockB。加载完类之后,main方法中新建Test 对象,再执行blockA。
    最后结果:blockAblockBblockA

发表于 2022-01-30 12:12:54 回复(0)
感觉很多答案都答非所问,我的理解是这样的:
首先明确是先进行类的加载,再进行实例化
其次是一个static对象它在内存中仅有一个,且JVM只会为它分配一次内存,首先进行类的加载,在这过程中已经为题中的static对象,分配好了内存,执行顺序为:
1.public static Test t1 = new Test();
2.static
    {
        System.out.println("blockB");
    }
所以它在执行第一步实例化中不会再去执行static代码块,因为已经分配过一次内存,只会进行实例化,也就是输出A,然后按照顺序执行static语句块,输出B,最后实例化t2,输出A
有错误欢迎指出,谢谢
发表于 2021-12-29 20:35:09 回复(0)
1、执行Test t2 = newTest();,首先进行类的加载(静态资源),再进行类的对象初始化操作
2、类的加载过程:先加载静态属性按声明顺序从上到下首先执行,public static Test t1 = newTest();
3、当执行public static Test t1 = new Test(); 的new Test()时,Test类已经处于加载过程了,即第2部正在进行了,因此这个new Test()无需再进行类的加载操作,直接进入类的对象实例化阶段。
4、第3步的new Test()进入对象实例化阶段,因此开执行非静态代码块,此时输出 block A,调用了默认的空参构造器
5、第4步完成了第3步的静态变量的初始化,接下来继续载第3步开始进行类的加载操作(静态资源加载),即加载静态资源,此时静态代码块被执行,输出 block B
6、在第5步时完成了第2步类加载的所有过程,最后开始进行第1步的类的对象初始化操作,即main函数中的new Test()操作
7、执行非静态资源,调用代码块,输出 blockA
8、最后main函数的Test t2 = newTest();执行完毕

发表于 2021-07-01 21:20:17 回复(0)