含义
- 普通代码块:常规出现在方法,循环,判断等等语句中被{}括起来的代码。
1 if(condition){
code
}
2 for(;;){
code
}
3 while(){
code
}
- 静态代码块:在类中定义使用static修饰的代码块。
- 它是随着类的加载而执行,只执行一次是优先于主函数的。具体来说,静态代码块是由类调用的。类调用时,先执行静态代码块,然后才执行主函数。
- 静态代码块是给类进行初始化的
- 静态代码块中的变量是局部变量,
- 一个类中可以有多个静态代码块
class A{
static {}
}
- 构造函数
- 对象一旦建立就会调用与之对应的构造函数
- 构造函数的作用是用于给对象进行初始化
- 一个对象建立,构造函数只运行一次,而一般方法可以被对象调用多次
class A{
A(){无参}
A(****){有参}
}
- 构造代码块(非静态代码块)
- 构造代码块的作用是给对象进行初始化
- 对象一旦建立就运行构造代码块了,而且优于构造函数执行。注意,有对象建立的情况下才会运行构造代码块,类是不能调用构造代码块的,构造代码块的执行在构造函数之前
- 构造函数与构造代码块的区别:构造代码块是给所有对象进行统一初始化,而构造函数是给对应的对象初始化,因为构造函数是可以有多个的,需要哪个就用哪个,而构造代码块中定义的是不同对象中相同的部分。
class A{
{
code
}
}
java 各方法块的初始化顺序
对于一个类的情况
- 类仅仅被加载
public class codeblock {
{
System.out.println("这是构造代码块");
}
static {
System.out.println("这是静态代码块");
}
codeblock(){
System.out.println("这是构造方法");
}
public static void main(String[] args) {
}
}
可以看出只有静态代码块运行
- 类被创建
public class codeblock {
{
System.out.println("这是构造代码块");
}
static {
System.out.println("这是静态代码块");
}
codeblock(){
System.out.println("这是构造方法");
}
public static void main(String[] args) {
new codeblock();
}
}
可以看出 先执行静态代码块,然后是构造代码块,最后是构造方法
3. 创建同一个类的两个对象
public class codeblock {
public String name = "gg";
{
System.out.println("这是构造代码块"+name);
}
static {
System.out.println("这是静态代码块");
}
codeblock(String n){
name = n;
System.out.println("这是构造方法"+name);
}
public static void main(String[] args) {
new codeblock("A");
new codeblock("B");
}
}
同一个类中静态代码块只会被执行一次
4. 对于含有静态变量,静态初始化块,变量,初始化块,构造器的类
public class codeblock {
public String name = "姓名";
public static String staticname="静态name";
{
System.out.println(name);
System.out.println("这是构造代码块"+name);
}
static {
System.out.println(staticname);
System.out.println("这是静态代码块");
}
codeblock(String n){
name = n;
System.out.println("这是构造方法"+name);
}
public static void main(String[] args) {
new codeblock("A");
// new codeblock("B");
}
}
可以看出初始化的顺序为:静态变量、静态初始化块、变量、构造代码块、构造器
对于继承情况
class A{
public A(){
System.out.println("A的构造函数");
}
{
System.out.println("A的构造代码块");
}
static{
System.out.println("A的静态代码块");
}
}
class B extends A{
public B(){
System.out.println("B的构造函数");
}
{
System.out.println("B的构造代码块");
}
static{
System.out.println("B的静态代码块");
}
}
- 先执行父类的静态代码块,并初始化父类的静态成员变量
- 执行子类的静态代码块,并初始化子类的静态成员变量
- 执行父类的构造代码块,执行父类的构造函数,并初始化父类普通成员变量
- 执行子类的构造代码块,执行子类的构造函数,并初始化子类的普通成员变量
更进一步
class GrandParent{
static {
System.out.println("爷爷类的静态代码块");
}
{
System.out.println("爷爷类的构造代码块");
}
}
class Parent extends GrandParent {
/* 静态变量 */
public static String p_StaticStr = "父类--静态变量";
/* 变量 */
public String p_Str = "父类--变量";
protected int i = 9;
protected int j = 0;
/* 静态初始化块 */
static {
System.out.println( p_StaticStr );
System.out.println( "父类--静态初始化块" );
}
/* 初始化块 */
{
System.out.println( p_Str );
System.out.println( "父类--初始化块" );
}
/* 构造器 */
public Parent()
{
System.out.println( "父类--构造器" );
System.out.println( "i=" + i + ", j=" + j );
j = 20;
}
}
class SubClass extends Parent {
/* 静态变量 */
public static String s_StaticStr = "子类--静态变量";
/* 变量 */
public String s_Str = "子类--变量";
/* 静态初始化块 */
static {
System.out.println( s_StaticStr );
System.out.println( "子类--静态初始化块" );
}
/* 初始化块 */
{
System.out.println( s_Str );
System.out.println( "子类--初始化块" );
}
/* 构造器 */
public SubClass()
{
System.out.println( "子类--构造器" );
System.out.println( "i=" + i + ",j=" + j );
}
}
爷爷类的静态代码块
父类–静态变量
父类–静态初始化块
子类–静态变量
子类–静态初始化块
main
爷爷类的构造代码块
父类–变量
父类–初始化块
父类–构造器
i=9, j=0
子类–变量
子类–初始化块
子类–构造器
i=9,j=20
分析:
- SubClass.main()方法是一个static方法装载器寻找已经编译的SubClass类的代码。在装载的过程中发现SubClass有一个父类,于是就去装载父类,不管创不创建父类对象,都会去装载它。如果父类还有父类,那么以此类推。
- 执行根基类的静态代码块,之后是下一个类的静态代码块,知道这个类本身的静态代码块
- 所有必要的类都被装载后,开始执行main方法体,并用new SubClass() 创建对象
- 依次从爷爷、父亲、自己的顺序执行构造代码块以及构造方法。
- 对子类成员变量按照他们声明的顺序初始化,执行子类构造函数的其余部分
参考 :https://www.cnblogs.com/Qian123/p/5713440.html