不同变量的赋值时机 | 常见的面试题 | 静态代码块
数据类型:
1、基本数据类型(整型、浮点型、布尔型、char型)
2、引用数据类型(类、接口、数组)
按变量在类中的位置划分:类变量(每一个new出来的对象都拥有)、实例变量、局部变量
成员变量:在使用前、都经历过默认初始化赋值。
类变量(static修饰):linkling的prepare阶段:给类变量默认赋值—>在initial阶段:给类变量显式赋值。静态代码块赋值。
【类变量表有两次初始化的机会,第一次是在准备阶段,对变量设置零值。第二次是在初始化阶段,赋予在代码中定义的初始值】
实例变量:随着对象的创建,会在堆空间中分配实例变量空间,并进行默认赋值
局部变量:在使用前,必须是显式赋值的,否则,编译不通过。(在栈中分配空间)
1、局部变量不赋初始值,编译不通过
2、实例变量的默认初始值
3、静态代码块、代码块、构造函数执行顺序
package com.zheng.demo;
public class MyTest {
static {
System.out.println("我是静态代码块");
}
{
System.out.println("我是构造块");
}
public MyTest() {
System.out.println("我是无参构造函数");
}
public static void main(String[] args) {
new MyTest();
}
}
子类继承父类,静态代码块、构造块、构造函数执行顺序。
package com.zheng.demo;
public class MyTest extends A {
{
System.out.println("我是子类的构造块");
}
static {
System.out.println("我是子类的静态代码块");
}
public MyTest() {
System.out.println("我是子类的无参构造函数");
}
public static void main(String[] args) {
new MyTest();
}
}
class A {
{
System.out.println("我是A的构造块");
}
static {
System.out.println("我是A的静态代码块");
}
public A() {
System.out.println("我是A的无参构造函数");
}
}
在类加载器中的初始化阶段,javac编译器自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并而来。
父类的静态代码块–>子类的静态代码块–>父类的构造块–>父类的构造函数–>子类的构造块–>子类的构造函数。