先来看一道最常见的面试题:静态代码块的执行顺序?
看一下实际运行:
class A{ static { System.out.println("A的静态代码块"); } { System.out.println("A的构造代码块/非静态代码块"); } public A() { System.out.println("A的构造函数"); } } class B extends A{ static { System.out.println("B的静态代码块"); } { System.out.println("B的构造代码块/非静态代码块"); } public B() { System.out.println("B的构造函数"); } }
//测试程序执行public static void main(String[] args) { System.out.println("==== main开始执行 ===="); new B(); System.out.println("==== B已经被创建 ====="); }
答案是:
==== main开始执行 ====
A的静态代码块
B的静态代码块
A的构造代码块/非静态代码块
A的构造函数
B的构造代码块/非静态代码块
B的构造函数
==== B已经被创建 =====
好了,现在开始小白的问答环节:
Q1:不是说,静态块里的内容在类被加载的时候就执行,存在方法区(静态区)中,那为什么是先有main开始执行的语句打印呢?
A1:首先要明白,什么叫类加载:类加载就是把需要的类的代码加载到内存中,且在此类首次使用时静态代码块被加载执行,也就是说静态代码块只执行一次。
什么时候有类加载:1.创建实例 2.调用该类的静态方法时(静态块代码优先于静态函数执行) 3.使用该类的非常量静态字段 4.使用反射方法时 5.初始化该类的子类
Q2:上面说存在方法区中,那么方法区是什么?Java内存布局里没有方法区呀?
A2:《Java虚拟机规范》只是规定了有方法区这个概念,在HotSpot上使用永久代来实现方法区。而到了JDK8,永久代被元空间(MetaSpace)替换,其他内容由永久代移入元空间,比如说
类元信息,字段,静态属性,方法,常量等,除了字符串常量,它被移入了堆内存。
Q3:什么是构造代码块呢?
A3:构造代码块:初始化所有对象。属于对象的,在new 的时候才会执行,而构造函数是new的时候,调用了构造方法,所以构造代码块会先一步
Q4:为什么我构造方法写成了 public void A(){} 就不可以了呢?构造方法为什么不可以有返回值?
A4:构造方法在Java语言规范里面叫 “Constructor” ,并不是一个成员方法(成员方法叫 Method),其实应该叫 “构造器”更合适。
构造方法在类创建的期间(new)被执行用于对象初始化的,只有在构造方法执行完了,类的创建才算是完成了。
既然是用于初始化对象的,那么没有返回值是很正常的事情了,虚拟机规范中也是这么形容的。
原文地址:https://www.cnblogs.com/zzfree/p/12189882.html