• 理解

初始化块又称为代码块。属于类中的第四大成员。本质上是一个方法,它也有方法体,但没有方法名,没有参数,没有返回,而且也不是通过对象或类名显式调用,而是通过隐式调用

是构造器的补充

语法

[修饰符]{
方法体
}

注意:

①修饰符只能是static,使用static修饰的初始化块称为静态初始化块

没有使用static修饰的初始化块称为普通初始化块

//静态初始化块
static{ }
//普通初始化块
{ }

②方法体中可以为任意逻辑语句,包含输入、输出、变量、运算等

  • 好处

1、和构造器很像,都是用于初始化信息

2、当多个构造器中有重复的语句,可以将这些重复的语句往上提取到初始化块中,提高代码的重用性

  • 特点

1、静态初始化块的调用时机:加载类
普通初始化块的调用时机:创建对象

初始化块示例:

class InitDemo{

    String name;
int age;
double height; {
System.out.println("初始化语句");
} public InitDemo(){ } public InitDemo(String name) {
super();
this.name = name;
} public InitDemo(String name, int age) {
super();
this.name = name;
this.age = age;
} public InitDemo(String name, int age, double height) {
super();
this.name = name;
this.age = age;
this.height = height;
}
}

2、静态初始化块只会调用一次,随着类的加载而加载,(类只加载一次)

普通初始化块可以调用多次,随着对象的创建而加载

/*
*此类用于演示初始化块的特点2:
*静态初始化块只能被调用一次,因为类只能加载一次。
*普通初始化块可以被调用多次,因为可以创建多个对象
*/
public class TestInit2 { public static void main(String[] args) {
// System.out.println(InitDemo2.a);//加载类
new InitDemo2();
new InitDemo2();
new InitDemo2();
new InitDemo2();
new InitDemo2();
}
}
class InitDemo2{
static int a =100; { System.out.println("我是普通初始化块");
}
static{
System.out.println("我是静态初始化块");
}
}

3、一个类中可以有多个静态初始化块和多个普通初始化块

静态初始化块的执行要早于普通初始化块
同一个类型的初始化块的执行顺序取决于定义的先后顺序!

/*
* 此类用于演示初始化块的特点3:
* 一个类中允许有多个普通初始化块和静态初始化块,则执行顺序:
* 静态初始化块————普通初始化块
* 同一个类别的初始化块,执行顺序取决于定义的先后顺序
*/
public class TestInit3 { public static void main(String[] args) {
// System.out.println(InitDemo2.a);//加载类
new InitDemo3();//加载+创建对象 } }
class InitDemo3{
{
System.out.println("我是普通初始化块1");
}
static{
System.out.println("我是静态初始化块1");
} {
System.out.println("我是普通初始化块2");
}
{
System.out.println("我是普通初始化块3");
}
static{
System.out.println("我是静态初始化块2");
}
static{
System.out.println("我是静态初始化块3");
} }

输出:

我是静态初始化块1
我是静态初始化块2
我是静态初始化块3
我是普通初始化块1
我是普通初始化块2
我是普通初始化块3

4、一个类中如果有:静态初始化块、普通初始化块、普通属性初始化、静态属性初始化、构造器

执行顺序:
静态初始化块 | 静态属性初始化 > 普通初始化块 | 普通属性初始化 > 构造器

/*
* 此类用于演示初始化块的特点4:
* 如果一个类中有普通属性初始化、静态属性初始化、普通初始化块、静态初始化块、构造器,则执行顺序:
* 静态属性初始化|静态代码块——>普通属性初始化|普通代码块——>构造器
* 同一个类别的属性初始化和代码块的执行顺序取决于定义的先后顺序
*
*/
public class TestInit4 { public static void main(String[] args) {
InitDemo4 id = new InitDemo4();
} }
class InitDemo4{ public InitDemo4(){
System.out.println("我是构造器");
}
String a=msg("普通属性初始化1"); public static String msg(String info){
System.out.println(info);
return info;
}
static{
System.out.println("静态初始化块2");
}
static String b=msg("静态属性初始化1"); {
System.out.println("我是普通初始化块1");
} String c=msg("普通属性初始化2"); {
System.out.println("我是普通初始化块2");
}
static String d=msg("静态属性初始化2"); static{
System.out.println("静态初始化块1");
}
}

输出:

静态初始化块2
静态属性初始化1
静态属性初始化2
静态初始化块1
普通属性初始化1
我是普通初始化块1
普通属性初始化2
我是普通初始化块2
我是构造器

5、有父子类

执行顺序:

爷爷类的静态初始化块 | 静态属性初始化 >

父类静态初始化块 | 静态属性初始化 >

子类静态初始化块 | 静态属性初始化 >

爷爷类普通初始化块 | 普通属性初始化 > 构造器 >

父类普通初始化块 | 普通属性初始化 > 构造器 >

子类普通初始化块 | 普通属性初始化 > 构造器

/*
* 此类用于演示初始化块的特点5:
* 如果父子类中都有普通属性初始化、静态属性初始化、普通初始化块、静态初始化块、构造器,
* 则执行顺序:
* 爷爷类的静态属性初始化|静态代码块——>父类的静态属性初始化|静态代码块——>子类的静态属性初始化|静态代码块——>
* 爷爷类的普通属性初始化|普通代码块——>爷爷类的构造器——>父类的普通属性初始化|普通代码块——>父类的构造器——>子类的普通属性初始化|普通代码块——>子类的构造器
* 同一个类别的属性初始化和代码块的执行顺序取决于定义的先后顺序
*
*/
public class TestInit5 { public static void main(String[] args) {
InitDemo5 id = new InitDemo5();
} }
class Grand{
public Grand(){ // System.out.println("爷爷类的普通代码块");
System.out.println("我是爷爷类的构造器");
}
String a=fun("爷爷类的普通属性初始化"); public static String fun(String info){
System.out.println(info);
return info;
}
static{
System.out.println("爷爷类的静态代码块");
} {
System.out.println("爷爷类的普通代码块");
} static String d=fun("爷爷类的静态属性初始化");
}
class Father extends Grand{
public Father(){
// System.out.println("爷爷类的普通代码块");
System.out.println("我是爷爷类的构造器");
// System.out.println("父类的普通代码块");
System.out.println("我是父类的构造器");
}
String a=method("父类的普通属性初始化"); public static String method(String info){
System.out.println(info);
return info;
}
static{
System.out.println("父类的静态代码块");
} {
System.out.println("父类的普通代码块");
} static String d=method("父类的静态属性初始化"); }
class InitDemo5 extends Father{ public InitDemo5(){
System.out.println("我是子类的构造器");
}
String a=msg("子类的普通属性初始化"); public static String msg(String info){
System.out.println(info);
return info;
}
static{
System.out.println("子类的静态代码块");
} {
System.out.println("子类的普通代码块");
} static String d=msg("子类的静态属性初始化");
}

6、静态初始化块中遵循静态成员的特点,只能直接访问静态成员!

7、初始化位置

普通的常量属性,初始化必须在声明时或构造器或普通代码块中

静态的常量属性,初始化必须在声明时或静态代码块中

示例:

class A{
final int x;
final static int y;
public A(){
y=10;
x=100; // × final变量初始化后不可重新赋值
}
{
x=100;
y=10; // × final static修饰的静态常量只能在static静态初始化块中初始化
}
}

第二种:

class A{
final int x;
final static int y;
public A(){
y=10; // × final变量初始化后不可重新赋值
x=100;
}
static{
x=100; // × static静态初始化块不可调用普通变量
y=10;
}
}

【总结】

类的对象创建包括:加载创建两部分。

加载中将所有静态的属性、静态初始化块执行

创建对象中将所有普通属性、普通初始化块执行,再执行构造方法

【面试题一】

public class Teacher {

    public static void main(String[] args) {
new Teacher("john");  // ⑥
}
String name ;
public Teacher(String string) {
this.name=string;
System.out.println("构造器:"+name);  // ④ 构造器执行 // ⑧ 构造器执行
}
static {
System.out.println("嘿嘿");  // ①
}
static Teacher t = new Teacher("鸠摩智");  // ② 加载时发现还需要加载不会再加载
{
System.out.println("哈哈哈:"+name);  // ③ 此时name(鸠摩智)还没赋值,为null // ⑦ 加载结束,但name(john)没被赋值,为null
}
static{
System.out.println("呵呵");  // ⑤ 继续加载类,加载结束
}
}

输出:

嘿嘿
哈哈哈:null
构造器:鸠摩智
呵呵
哈哈哈:null
构造器:john

【面试题二】

public class MyClass {
static int x,y;  // ① x=0, y=0
static{
int x=5;    // ② x = 5(局部变量,与static无关)
x--;      // ③ x = 4(局部变量,与static无关)
}
static{
x--;      // ④ x = -1
} public static void main(String[] args) {
x--;      // ⑤ x = -2
myMethod() ;  // ⑥
System.out.println(x+y + ++x);  // ⑧ 0+(-2)+1=-1
} public static void myMethod() {
y=x++ + ++x; // ⑦ y = (-2) + (0)=-2 x = 0
}
}

输出:

-1

【面试题三】

class A{
final int x;
final static int y;
public A(){
y=10;
x=100; // × final变量初始化后不可重新赋值
}
{
x=100;
y=10; // × final static修饰的静态常量只能在static静态初始化块中初始化
}
}
class A{
final int x;
final static int y;
public A(){
y=10; // × final变量初始化后不可重新赋值
x=100;
}
static{
x=100; // × static静态初始化块不可调用普通变量
y=10;
}
}

【面试四】

public class Test {     // 1.准备加载类
public static Test t1 = new Test(); // 2.加载静态变量, 这里比较特殊, 静态变量引用本类的实例
// 方法块
{
System.out.println("AAA"); // 3.实例化时调用
}
// 静态代码块
static {
System.out.println("BBB"); // 4.加载静态方法
}
public static void main(String[] args) {
Test t2 = new Test(); // 5.实例化对象 -> 调用方法块
}
}

Java初始化块及执行顺序的更多相关文章

  1. 关于java中三种初始化块的执行顺序

    许多小伙伴对于java中的三种初始化块的执行顺序一直感到头疼,接下来我们就来分析一下这三种初始化块到底是怎么运行的.有些公司也会将这个问题作为笔试题目. 下面通过一段代码来看看创建对象时这么初始化块是 ...

  2. java静态初始化块的执行顺序

    先来观察下面的代码 package trr; class Root { static{ System.out.println("Root的静态初始化块"); } { System. ...

  3. java中静态初始化块的执行顺序

    在java中,其应该是先于所有的方法执行. 下面是测试代码: public class Test1 { static{ System.out.println("执行静态初始化块test1.. ...

  4. java类的初始化块/执行顺序,实例化对象数据赋值

    java里初始化一个类的对象,通过初始化快或者构造方法进行数据赋值.与其相关的执行代码有这么几种: 静态初始化块 初始化块 构造方法 静态初始化块 静态初始化块只在类加载时执行一次,同时静态初始化块只 ...

  5. 请运行TestStaticInitializeBlock.java示例,观察输出结果,总结出“静态初始化块的执行顺序”。

    答:执行顺序:静态初始化块->初始化块->构造函数 静态初始化块:在第一次加载类时执行,与对象的创建无关. 构造代码块:在调用构造方法时执行. 构造函数:在调用构造函数时执行.

  6. 夯实Java基础系列7:一文读懂Java 代码块和执行顺序

    目录 Java中的构造方法 构造方法简介 构造方法实例 例 1 例 2 Java中的几种构造方法详解 普通构造方法 默认构造方法 重载构造方法 java子类构造方法调用父类构造方法 Java中的代码块 ...

  7. 夯实Java基础系列7:Java 代码块和执行顺序

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

  8. java静态代码块,构造方法,初始化块的执行顺序

    代码Parent和Sub进行讲解 public class Parent { private static final String name; public Parent() { System.ou ...

  9. java 代码块的执行顺序

    举一个实例程序: class HelloA { public HelloA(){ System.out.println("Hello A!父类构造方法"); } { System. ...

随机推荐

  1. systemd 相关及服务启动失败原因

    1 查看启用的units systemctl list-unit-files | grep enabled 2 查看指定服务的日志 按服务单元过滤 journalctl -u j   查看j.serv ...

  2. 第七周作业—N42-虚怀若谷

    一.简述OSI七层模型和TCP/IP五层模型 1. OSI七层模型 物理层:二进制传输,为启动.维护以及关闭物理链路定义了电气规范.机械规范.过程规范和功能规范:实际的最终信号的传输是通过物理层实现的 ...

  3. docker for windows 中挂载文件到容器

    docker for windows版本: 宿主机:windows10 场景: 容器是基于microsoft/donet的webapi 想把宿主机的文件挂载到容器中,比方说:a.txt 命令如下: d ...

  4. Activiti之Idea生成png图片及解决乱码问题(四)

    IDEA 工具中的操作方式 第一步:将 holiday.bpmn 文件改为扩展名 xml 的文件名称: holiday.xml修改前的 bpmn 文件,效果如下: 第二步: 在 holiday.xml ...

  5. 【bzoj1398】Vijos1382寻找主人 Necklace

    *题目描述: 给定两个项链的表示,判断他们是否可能是一条项链. *输入: 输入文件只有两行,每行一个由0至9组成的字符串,描述一个项链的表示(保证项链的长度是相等的). *输出: 如果两条项链不可能同 ...

  6. Leetcode 17. Letter Combinations of a Phone Number(水)

    17. Letter Combinations of a Phone Number Medium Given a string containing digits from 2-9 inclusive ...

  7. android读取xml

    /*** 从config.xml中获取版本信息以及应用id* * @param urlPath* @return* @throws Exception*/public List getUpdateIn ...

  8. 180128-----Java面试题

    1 不用第三个变量,交换两个的值 a=1;b=2;a=a+b;b=a-b;a=a-b; 2 Java动态代理用什么实现? 反射

  9. CSS札记(一):CSS选择器

    一.语法规则 选择器{ 属性1:属性值1; 属性2:属性值2; ...... } /*注释*/ 二.如何在html中应用CSS 1. 外部引用css文件 css文件:css/layout.css(cs ...

  10. EventBus和Otto第三方构架

    代码 添加依赖:implementation 'org.greenrobot:eventbus:3.0.0'1注册并声明订阅者,然后发布事件最后解除注册 @Override protected voi ...