首页 > 试题广场 >

以下代码的输出结果是?

[单选题]
以下代码的输出结果是?
public class B
{
    public static B t1 = new B();
    public static B t2 = new B();
    {
        System.out.println("构造块");
    }
    static
    {
        System.out.println("静态块");
    }
    public static void main(String[] args)
    {
        B t = new B();
    }
}

  • 静态块 构造块 构造块 构造块
  • 构造块 静态块 构造块 构造块
  • 构造块 构造块 静态块 构造块
  • 构造块 构造块 构造块 静态块
开始时JVM加载B.class,对所有的静态成员进行声明,t1 t2被初始化为默认值,为null,又因为t1 t2需要被显式初始化,所以对t1进行显式初始化,初始化代码块→构造函数(没有就是调用默认的构造函数),咦!静态代码块咋不初始化?因为在开始时已经对static部分进行了初始化,虽然只对static变量进行了初始化,但在初始化t1时也不会再执行static块了,因为JVM认为这是第二次加载类B了,所以static会在t1初始化时被忽略掉,所以直接初始化非static部分,也就是构造块部分(输出''构造块'')接着构造函数(无输出)。接着对t2进行初始化过程同t1相同(输出'构造块'),此时就对所有的static变量都完成了初始化,接着就执行static块部分(输出'静态块'),接着执行,main方法,同样也,new了对象,调用构造函数输出('构造块')
发表于 2016-04-07 08:57:39 回复(93)
之前我一直有一个误区!就是认为静态块一定是最先初始化的!但是,阿里爸爸今天又用一记重拳猛击我的脸,额,好疼....当时的情况是这样的:
我在牛客网找虐中,碰到了这样的一道题,心中充满了鄙夷,心想"这tm还用看吗,肯定先是静态块,再接着三个构造块,弱鸡题",但是 = = ,答案却是"构造块 构造块 静态块 构造块".
......[黑线|||||||||]
于是总结了一下,以警后世 - -
正确的理解是这样的:
并不是静态最先初始化,而是静态.(BM:啊!多么痛的领悟!)
而静态域中包含静态变量、静态块和静态方法,其中需要初始化的是静态变量和静态块.而他们两个的初始化顺序是靠他们俩的位置决定的!
So!
初始化顺序是 t1 t2 静态块
发表于 2016-10-10 19:38:11 回复(62)
C
静态块:用static申明,JVM加载类时执行,仅执行一次
构造块:类中直接用{}定义,每一次创建对象时执行
执行顺序优先级:静态块>main()>构造块>构造方法
静态块按照申明顺序执行,所以先执行publicstaticB t1 = newB();该语句创建对象,则又会调用构造块,输出构造块
接着执行public static B t1 = new B();输出构造块
再执行
static
{
System.out.println("静态块");
}输出静态块
最后main方法执行,创建对象,输出构造块。
编辑于 2019-12-25 11:52:29 回复(55)
(非常详细的解析)看了几个大神的解析,茅塞顿开,总结一下: 1.程序入口main方法要执行首先要加载类B 2.静态域:分为静态变量,静态方法,静态块。这里面涉及到的是静态变量和静态块,当执行到静态域时,按照静态域的顺序加载。并且静态域只在类的第一次加载时执行 3.每次new对象时,会执行一次构造块和构造方法,构造块总是在构造方法前执行(当然,第一次new时,会先执行静态域,静态域〉构造块〉构造方法) 注意:加载类时并不会调用构造块和构造方法,只有静态域会执行 4.根据前三点,首先加载类B,执行静态域的第一个静态变量,static b1=new B,输出构造块和构造方法(空)。ps:这里为什么不加载静态方法呢?因为执行了静态变量的初始化,意味着已经加载了B的静态域的一部分,这时候不能再加载另一个静态域了,否则属于重复加载 了(静态域必须当成一个整体来看待。否则加载会错乱) 于是,依次static b2 =new B,输出构造块,再执行静态块,完成对整个静态域的加载,再执行main方法,new b,输出构造块。
发表于 2017-03-06 21:03:23 回复(29)
静态的东西,类加载的时候都被加载t1 t2 静态块,之后是按照顺序 且静态只一次,所以t1仅执行构造块,t3同理。第三个是执行完t12后的静态块,最后是构造块。这么理解可对?不对的踹我一脚,谢谢,下一题了
发表于 2022-08-09 14:17:57 回复(0)
做个标记: 1.如果将静态属性和静态代码块调换一下位置? 2.再加一个父类会输出什么?
发表于 2022-06-13 09:10:11 回复(0)
首先类要加载了才能用,那么在类加载的连接过程中会有准备的这一过程。该过程会将类变量,注意不是类的变量,一定是类变量(被static修饰)分配内存空间,除非被final修饰,不然统统不会首先赋予正确值,而是先赋予null值。接着在类被第一次主动使用时,触发初始化。而初始化的核心作用之一就是要为类变量赋予正确的值。
通过上面这一波分析,基本上就一目了然了。首先t1和t2将会被分配内存空间,但是为null值,进入main方法中,触发B类的初始化,从而为t1、t2分配正确的值,也就进一步触发了B类的构造方法。当为t1、t2赋予正确的值后,初始化还未结束,要继续去执行其静态代码块,从而有了C选项。
发表于 2020-05-07 22:53:57 回复(0)
静态块是static{},在jvm加载类的时候执行,只执行一次,构造块是{},每创建对象就执行一次,执行顺序是先静态块,再构造块,再主方法,再构造方法。 所以本题中static按照申明顺序执行,先有两个创建对象的静态方法,调用了构造块,所以是输出两次构造块。 然后执行静态块。 最后执行主方法中的建立一个对象,调用了构造块,所以输出构造块。
发表于 2019-04-15 06:59:55 回复(0)
C 构造块
构造块
静态块
构造块
发表于 2018-06-05 22:06:39 回复(0)
静态域>构造块>构造方法。 静态域只加载一次,其中包括静态变量、静态方法、静态块,它们依次执行。 本例中,B1加载后为何不执行静态块?因为静态域在加载B1时已经加载了一次,是不能重复加载的。
编辑于 2017-03-19 10:01:20 回复(0)
C
Java 程序初始化对象的顺序为:父类静态变量、父类静态代码块、子类静态变量、子类静态代码块、父类非静态变量、父类非静态代码块、父类构造函数、子类非静态变量、子类非静态代码块、子类构造函数。
发表于 2017-03-07 23:35:36 回复(0)
1.执行静态块 有三个静态块,这三个按照写的顺序执 行,执行第一个静态块(第一句),先执行构造块(第一个“构造块”),执行构造方法;执行第二个静态块(第二句),先执行构造块(第二个“构造块”),执行构造方法;执行第三个构造块,打印“静态块”。 2.执行main() main()里的语句是new,所以先执行构造块,打印“构造块”,接着执行构造方法。
发表于 2016-12-04 08:31:51 回复(0)
在Java中所谓static指的就是优先于普通的属性、操作、域先执行;在同属于一个static的时候就是使用顺序执行。

发表于 2016-11-06 00:31:24 回复(0)
JVM知识点 建议看看 <<深入理解Java虚拟机>>这本书
发表于 2016-01-28 22:12:53 回复(0)
执行顺序分别是静态块,main,构造块,构造方法。按申请顺序依次执行
发表于 2015-07-27 11:32:30 回复(0)
rtS头像 rtS
构造代码块在创建对象的时候会执行一次,而静态代码块只在类第一次被虚拟机加载的时候执行一次
发表于 2015-04-07 08:31:10 回复(0)
本题注意如下几点:
1、每调用一次构造方法,则执行一次构造块
2、静态块只在类加载的时候加载一次
3、有多个静态变量或块时,按声明顺序加载
发表于 2015-08-17 19:54:37 回复(11)
1:类加载到内存中分为三个步骤 1)加载 2)链接 3)初始化
2:链接分为 1)验证 2)准备 3)解析
3:在准备阶段,会给类的静态变量分配内存,将其初始化为默认值。
4:在初始化阶段会给静态变量赋予初始值。
5:初始化过程是按照代码顺序来的。
发表于 2020-04-25 09:41:40 回复(0)
静态变量会按声明的顺序初始化,所以先会执行
 public static B t1 = new B();
 public static B t2 = new B();
所以会打印两个“构造块”
接着在执行静态代码块
打印“静态块”,
最后执行
B t = new B();
打印“构造块”


发表于 2015-03-31 10:20:06 回复(7)
总结一下:
1.执行顺序:静态代码块>构造代码块>构造方法
    理由:静态代码块(static{})在类加载的时候执行一次。
               构造代码块({}内的部分)在每一次创建对象时执行,始终在构造方法前执行。
               构造方法在新建对象时调用( 就是new的时候 )。
    注意: a.静态代码块在类加载的时候就执行,所以它的优先级高于入口main()方法。
                b.当三种形式不止一次出现,同优先级是按照先后顺序执行。

2.现在来看下有继承时的情况:
public class HelloB extends HelloA {
	
	 public HelloB(){
		 System.out.println("B的构造方法");
	 }
	 {
	     System.out.println("B的构造代码块");
	 }
	 static{
	     System.out.println("B的静态代码块");
	 }
	 //public static HelloB hB = new HelloB();
	 public static void main(String[] args){
	     new HelloB();//调用B的构造方法
	 }
}

class HelloA{
	 public HelloA(){
		 System.out.println("A的构造方法");
	 }
	 {
	     System.out.println("A的构造代码块");
	 }
	 static{
	     System.out.println("A的静态代码块");
	 }
} 
输出结果为:
A的静态代码块
B的静态代码块
A的构造代码块
A的构造方法
B的构造代码块
B的构造方法

可以看出:
        a.父类始终先调用(继承先调用父类),并且这三者之间的相对顺序始终保持不变
        b.因为静态代码块在类加载时执行,所以先输出的是父类和子类的静态代码块
        c.调用B的构造方法创建对象时,构造块和构造方***一起按顺序执行,还是父类的先调用


补充:如果在B的静态代码块之前加一句:static HelloB hB = new HelloB();   B的静态代码块会在其执行完后再执行;如果加在之后,则会先执行,说明优先级相同时是按照先后顺序执行的。
    
编辑于 2016-08-05 11:48:42 回复(4)