Java初始化块及执行顺序
- 理解
初始化块又称为代码块。属于类中的第四大成员。本质上是一个方法,它也有方法体,但没有方法名,没有参数,没有返回,而且也不是通过对象或类名显式调用,而是通过隐式调用
是构造器的补充
语法
[修饰符]{
方法体
}
注意:
①修饰符只能是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初始化块及执行顺序的更多相关文章
- 关于java中三种初始化块的执行顺序
许多小伙伴对于java中的三种初始化块的执行顺序一直感到头疼,接下来我们就来分析一下这三种初始化块到底是怎么运行的.有些公司也会将这个问题作为笔试题目. 下面通过一段代码来看看创建对象时这么初始化块是 ...
- java静态初始化块的执行顺序
先来观察下面的代码 package trr; class Root { static{ System.out.println("Root的静态初始化块"); } { System. ...
- java中静态初始化块的执行顺序
在java中,其应该是先于所有的方法执行. 下面是测试代码: public class Test1 { static{ System.out.println("执行静态初始化块test1.. ...
- java类的初始化块/执行顺序,实例化对象数据赋值
java里初始化一个类的对象,通过初始化快或者构造方法进行数据赋值.与其相关的执行代码有这么几种: 静态初始化块 初始化块 构造方法 静态初始化块 静态初始化块只在类加载时执行一次,同时静态初始化块只 ...
- 请运行TestStaticInitializeBlock.java示例,观察输出结果,总结出“静态初始化块的执行顺序”。
答:执行顺序:静态初始化块->初始化块->构造函数 静态初始化块:在第一次加载类时执行,与对象的创建无关. 构造代码块:在调用构造方法时执行. 构造函数:在调用构造函数时执行.
- 夯实Java基础系列7:一文读懂Java 代码块和执行顺序
目录 Java中的构造方法 构造方法简介 构造方法实例 例 1 例 2 Java中的几种构造方法详解 普通构造方法 默认构造方法 重载构造方法 java子类构造方法调用父类构造方法 Java中的代码块 ...
- 夯实Java基础系列7:Java 代码块和执行顺序
本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...
- java静态代码块,构造方法,初始化块的执行顺序
代码Parent和Sub进行讲解 public class Parent { private static final String name; public Parent() { System.ou ...
- java 代码块的执行顺序
举一个实例程序: class HelloA { public HelloA(){ System.out.println("Hello A!父类构造方法"); } { System. ...
随机推荐
- PHP简单的爬虫–原型
1.PHP简单的爬虫–原型 爬虫的原理: 给定原始的url: 分析链接,根据设置的正则表达式获取链接中的内容: 有的会更新原始的url再进行分析链接,获取特定内容,周而复始. 将获取的内容保存在数据库 ...
- AGC007题解
发现自己思维能力又跟不上了...做题有点吃力...所以回归AGC刷题计划... AGC040506都写了一部分题然后懒得补全了,所以从07开始做吧.大概是从C开始. C 这也太人类智慧了吧... 我先 ...
- canvas在图片上生成文字
newImage(text) { // 生成图片 var imageBox = document.getElementById(&quo ...
- Delphi--长线程
{ 长线程, 开启:随应用程序启用而启动 关闭:岁应用程序关闭而结束 } unit uLongThread; interface uses Classes, ADODB, DB, ActiveX, S ...
- Java 8 Date常用工具类
原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11983108.html Demo package org.fool.util; import java ...
- Wannafly挑战赛16 #E 弹球弹弹弹 splay+基环树+各种思维
链接:https://ac.nowcoder.com/acm/problem/16033来源:牛客网 有n个位置,标号为1到n的整数,m次操作,第i次操作放置一个弹球在b[i] xor c[i-1]处 ...
- POJ 1252 Euro Efficiency ( 完全背包变形 && 物品重量为负 )
题意 : 给出 6 枚硬币的面值,然后要求求出对于 1~100 要用所给硬币凑出这 100 个面值且要求所用的硬币数都是最少的,问你最后使用硬币的平均个数以及对于单个面值所用硬币的最大数. 分析 : ...
- PC端无论页面有没有完全撑开把footer保持在最底部(不用定位)
最近在写项目,有的页面没有占到一屏,然后footer也就是底部就靠上了,这样很影响美观,于是在网上找了找,下面是我的成果 解决该问题的最好方法是采用CSS3提供的一种先进布局模型 :flexbox,可 ...
- js判断浏览器的类型
我们很多时候都需要判断浏览器,下面就是一些常用的判断 var ua = navigator.userAgent.toLowerCase(); //用来判断移动端类型 var isWeixin = /M ...
- (3.3)狄泰软件学院C++课程学习剖析四
对课程前面40课的详细回顾分析(二) 1.一个类的成员变量是对于每个对象专有的,但是成员函数是共享的. 2.构造函数只是决定一个对象的初始化状态,而不能决定对象的诞生.二阶构造人为的将初始化过程分为了 ...