精华内容
下载资源
问答
  • java之静态、非静态代码块详解
    2019-08-14 11:52:00

    1、基本原理       

            同C语言一样,java中也是将花括号{...},包括起来的代码称为一个代码块。java中我们通常将static修饰的代码块,称为静态代码块,随类存在,仅在类初始化时执行一次,那么类在什么时候初始化,主要有以下六种:  

           1)创建类的实例,也就是new一个对象 
      2)访问某个类或接口的静态变量,或者对该静态变量赋值 
      3)调用类的静态方法 
      4)反射(Class.forName(“com.lyj.load”)) 
      5)初始化一个类的子类(会首先初始化子类的父类) 
      6)JVM启动时标明的启动类,即文件名和类名相同的那个类 ;

           若无此修饰则称为非静态代码块,随对象存在,创建几个对象就执行几次。废话不多,请看如下代码:

    package jvm_mode;
    
    public class CodeBlock {
    
    	static {
    		System.out.println("静态代码块被执行");
    	}
    	
    	{
    		System.out.println("非静态代码块被执行");
    	}
    	public void show() {
    		System.out.println("类方法被执行");
    	}
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		System.out.println("main方法被执行");
    		new CodeBlock().show();
    		new CodeBlock().show();
    	}
    }
    

    执行结果如下:

    静态代码块被执行
    main方法被执行
    非静态代码块被执行
    无参构造方法被执行
    类方法被执行
    非静态代码块被执行
    无参构造方法被执行
    类方法被执行
     

    初步分析:

           由输出结果我们可以看见,最先被打印的是静态代码块的输出内容,这就说明在类初始化(JVM启动时标明的启动类)的时候是先执行了静态代码块的内容,随后执行main主方法。通过new调用了类中的无参数构造方法创建对象,有打印结果可知,非静态代码块优先于构造方法执行。当再次创建实例调用方法的时候只有方法被调用了,而静态代码块不再执行,因此,静态代码块的特点是在着类的初始化时执行,而且只执行一次!show方法就不解释了。

    初步结论:

    静态代码块:随类存在,类初始化时执行一次,貌似优先于main主方法执行

    非静态代码块:随对象存在,创建几次对象就执行几次,且优先于构造方法执行

    2、从继承中看代码块的执行顺序

    请看如下代码:

    package jvm_mode;
    
    public class CodeBlock extends CodeBlockParent{
    	static {
    		System.out.println("本类静态代码块被执行");
    	}
    	
    	{
    		System.out.println("本类非静态代码块被执行");
    	}
    	
    	CodeBlock(){
    		System.out.println("本类无参构造方法被执行");
    	}
    	
    	public void show() {
    		System.out.println("本类类方法被执行");
    	}
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		System.out.println("本类main方法被执行");
    		//new CodeBlockParent().show();
    	    new CodeBlock().show();
    	    //new CodeBlockChild().show();
    		//CodeBlockChild.static_func();
    	}
    }
    
    
    class CodeBlockParent{
    	public static int P_S_VAL =100;
    	public int P_VAL =101;
    	static {
    		System.out.println("父类静态代码块被执行,P_S_VAL="+P_S_VAL);
    	}
    	
    	{
    		System.out.println("父类非静态代码块被执行,P_VAL="+P_VAL);
    	}
    	
    	CodeBlockParent(){
    		System.out.println("父类无参构造方法被执行");
    	}
    	
    	public void show() {
    		System.out.println("父类类方法被执行");
    	}
    	
    }
    
    
    class CodeBlockChild extends CodeBlock{
    
    	static {
    		System.out.println("子类静态代码块被执行");
    	}
    	
    	{
    		System.out.println("子类非静态代码块被执行");
    	}
    	
    	CodeBlockChild(){
    		System.out.println("子类无参构造方法被执行");
    	}
    	
    	public void show() {
    		System.out.println("子类类方法被执行");
    	}
    	
    	public static void static_func() {
    		System.out.println("子类静态方法被执行");
    	}
    }

    代码中创建一个父类CodeBlockParent和一个子类CodeBlockChild

    2.1、main方法中创建一个父类CodeBlockParent对象

    执行结果:

    父类静态代码块被执行,P_S_VAL=100
    本类静态代码块被执行

    本类main方法被执行
    父类非静态代码块被执行,P_VAL=101
    父类无参构造方法被执行
    父类类方法被执行

    程序在执行流程如下:

          1、首先,程序在执行时,需要进行本类(main主类)的初始化即CodeBlock类,初始化时发现本类有继承的父类CodeBlockParent,所以先要对父类进行初始化[执行父类静态代码块],之后执行本类的初始化操作[执行本类的静态代码块],由父类中的静态成员变量可知P_S_VAL,在执行时静态代码块时已经先于此被初始化成100了,静态成员变量的值在类链接[准备阶段]被初始化成0.

          2、次之,进入本类的main主方法执行

          3、创建父类对象,执行父类的非静态代码块、构造方法、方法等,需要说明的是,父类中的成员变量P_VAL在执行非静态代码块时已经先于此被初始化成101了。

    2.2、main方法中创建一个本类的CodeBlock对象

    执行结果:

    父类静态代码块被执行,P_S_VAL=100
    本类静态代码块被执行

    本类main方法被执行
    父类非静态代码块被执行,P_VAL=101
    父类无参构造方法被执行
    本类非静态代码块被执行
    本类无参构造方法被执行
    本类类方法被执行
     

    程序执行流程:

          初始化、和进入main主方法同2.1小节一样,不同的是创建子类对象前先要隐式的创建一个父类对象[继承特性],因此先要执行父类的非静态代码块、构造方法。之后才轮到本类的一系列操作

    2.3、main方法中创建一个子类的CodeBlockChild对象

    执行结果:

    父类静态代码块被执行,P_S_VAL=100
    本类静态代码块被执行

    本类main方法被执行
    子类静态代码块被执行
    父类非静态代码块被执行,P_VAL=101
    父类无参构造方法被执行
    本类非静态代码块被执行
    本类无参构造方法被执行
    子类非静态代码块被执行
    子类无参构造方法被执行
    子类类方法被执行

    程序执行流程:

           首先,子类的初始化在代码中第一次被主动使用,用new创建对象仅仅是主动使用其中的一种,因此当主方法中调用new CodeBlockChild().show();时先进行一次子类的初始化操作[子类静态代码块],如果后面继续创建子类对象,该子类初始化不在执行。 创建在子类的对象时根据继承特性先隐式创建的子类的父类CodeBlock、父类的父类CodeBlockParent对象

    2.4、main方法中调用CodeBlockChild静态方法

    运行结果

    父类静态代码块被执行,P_S_VAL=100
    本类静态代码块被执行

    本类main方法被执行
    子类静态代码块被执行
    子类静态方法被执行

    程序执行流程:程序调用子类的静态方法static_func,子类第一次被主动使用进行初始化操作,执行静态代码块,之后调用了静态方法

    结论:

    静态代码块:随类存在,类初始化[发生于第一次主动使用]时执行一次,优先于非静态代码执行,优先于本类main主方法执行

    非静态代码块:随对象存在,创建几次对象就执行几次,优先于构造方法执行

    具体类的初始化顺序:父类的静态字段——>父类静态代码块——>子类静态字段——>子类静态代码块——>

    父类成员变量(非静态字段)——>父类非静态代码块——>父类构造器——>子类成员变量——>子类非静态代码块——>子类构造器

    疑问:在静态代码块中不能访问成员变量,想想这是为什么?它是否与成员的初始化顺序有必然的联系?

    答:初始化顺序仅仅是次要原因,根本原因是此时的成员还没有随对象被创建出来

    3、应用场景看代码块

    ......

    更多相关内容
  • java 静态代码块、非静态代码块、构造方法 执行顺序
    1.静态(static)成员变量和静态代码块代码块

    static修饰的成员都是类成员,会随着JVM加载类的时候加载而执行,而没有被static修饰的成员也被称为实例成员,需要创建对象才会随之加载到堆内存。所以静态的会优先非静态的。静态成员变量优先于静态代码块执行;

    2.非静态代码块和非静态成员变量

    非静态代码块和静态代码块都是在JVM加载类时且在构造方法执行之前执行,非静态代码块在类中都可以定义多个;非静态代码块是在类被实例化的时候执行。每被实例化一次,就会被执行一次;非静态成员变量优先于非静态代码块和构造方法执行;

    3.构造方法

    执行构造方法的时候,在执行方法体之前存在隐式三步:
    1)构造方法体的第一行是this语句,则不会执行隐式三步,
    2)构造方法体的第一行是super语句,则调用相应的父类的构造方法,
    3)构造方法体的第一行既不是this语句也不是super语句,则隐式调用super(),即其父类的默认构造方法,这也是为什么一个父类通常要提供默认构造方法的原因;

    代码示例:

    package com.dhcc.demo.springbootymldemo02.test;
    
    public class Teacher {
        private String name;
        private Integer age;
    
        public Teacher(String str) {
            System.out.println(str + "--成员变量Teacher初始化");
        }
    }
    
    package com.dhcc.demo.springbootymldemo02.test;
    import java.sql.Timestamp;
    public class Person {
        private static Teacher teacher = new Teacher("静态");
        private  Teacher teacherOne = new Teacher("非静态");
        private Integer no;
        private Integer age;
        private String name;
        static {
            Timestamp timestamp = new Timestamp(System.currentTimeMillis());
            try {
                Thread.sleep(1000);
                System.out.println("------父类的静态代码块执行------" + timestamp);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
         {
            Timestamp timestamp = new Timestamp(System.currentTimeMillis());
            try {
                Thread.sleep(1000);
                System.out.println("------父类的非静态代码块执行------" + timestamp);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Person() {
             Timestamp timestamp = new Timestamp(System.currentTimeMillis());
            try {
                Thread.sleep(1000);
                System.out.println("------父类的构造方法执行------" + timestamp);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }
    
    package com.dhcc.demo.springbootymldemo02.test;
    import java.sql.Timestamp;
    public class Student extends Person {
        private Integer sNo;
        private Integer classNO;
        static {
             Timestamp timestamp = new Timestamp(System.currentTimeMillis());
            try {
                Thread.sleep(1000);
                System.out.println("------Student类的静态代码块执行------" + timestamp);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        {
            Timestamp timestamp = new Timestamp(System.currentTimeMillis());
            try {
                Thread.sleep(1000);
                System.out.println("------Student类的非静态代码块执行------" + timestamp);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        public Student() {
            super();
            Timestamp timestamp = new Timestamp(System.currentTimeMillis());
            try {
                Thread.sleep(1000);
                System.out.println("------Student类的构造方法执行------" + timestamp);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }
    
    
    package com.dhcc.demo.springbootymldemo02.test;
    public class Test {
        public static void main(String[] args) {
            new Student();
        }
    }
    
    静态--成员变量Teacher初始化
    ------父类的静态代码块执行------2022-03-28 11:16:40.657
    ------Student类的静态代码块执行------2022-03-28 11:16:41.661
    非静态--成员变量Teacher初始化
    ------父类的非静态代码块执行------2022-03-28 11:16:42.669
    ------父类的构造方法执行------2022-03-28 11:16:43.679
    ------Student类的非静态代码块执行------2022-03-28 11:16:44.682
    ------Student类的构造方法执行------2022-03-28 11:16:45.689
    
    展开全文
  • 静态代码块和非静态代码块的描述 代码块的作用 在类或者对象执行代码块,初始化属性的时候,可以写逻辑。静态代码块,只能直接定义静态属性 代码块的执行顺序:由父及子,静态先行

    静态代码块和非静态代码块的描述

    在这里插入图片描述

    代码块的作用

    在类或者对象执行代码块,初始化属性的时候,可以写逻辑。静态代码块,只能直接定义静态属性
    在这里插入图片描述
    代码块的执行顺序:由父及子,静态先行
    在这里插入图片描述


    在这里插入图片描述

    展开全文
  • 非静态代码块:是用来初始化类的实例信息,在创建对象的时候就会被执行,且每创建一个对象都会被执行一次。执行的时候如果有静态初始化块,先执行静态初始化块再执行非静态初始化块,非静态初始化块会在构造函数执行...

    静态代码块:是用来初始化类的信息,在类被加载的时候就会被执行,且只执行一次。执行优先级高于非静态的初始化块。

    非静态代码块:是用来初始化类的实例信息,在创建对象的时候就会被执行,且每创建一个对象都会被执行一次。执行的时候如果有静态初始化块,先执行静态初始化块再执行非静态初始化块,非静态初始化块会在构造函数执行时,在构造函数主体代码执行之前被运行。

    构造方法:是用来创建对象的。

    一、同类中静态代码块,非静态代码块,构造方法的执行顺序

    执行顺序:静态代码块>非静态代码块>构造方法

    即:程序在执行时,首先执行静态代码块,且只执行一次。接下来再创建对象时(new),首先执行非静态代码块,再执行构造方法。

    示例1:

    代码:

    package com.csu.marden;
    
    public class Demo {
    	static{
    		System.out.println("static");
    	}
    	{
    		System.out.println("no static");
    	}
    	Demo5(){
    		System.out.println("constructor");
    	}
    	
    	
    	
    	public static void main(String[] args) {
    		
    	}
    
    }
    

    执行结果:

    分析:

    上述Demo类包含静态代码块,非静态代码块和构造方法。但是该类中没有具体的执行,只完成了类的加载,即只有静态代码块在类加载的时候被执行,且只执行一次。由于没有对类的实例化,所有非静态代码块和构造方法均未执行。

     

     

    示例2:

    代码:

    package com.csu.marden;
    
    public class Demo5 {
    	static{
    		System.out.println("static");
    	}
    	{
    		System.out.println("no static");
    	}
    	Demo5(){
    		System.out.println("constructor");
    	}
    	
    	
    	
    	public static void main(String[] args) {
    		Demo demo=new Demo();
    	}
    
    }
    

    执行结果:

    分析:

    上述Demo类包含静态代码块,非静态代码块和构造方法。上述代码首先完成了类加载,即静态代码块执行,且仅执行一次。然后创建了该类的实例,首先执行了非静态代码块,然后执行了构造方法。

     

     

    示例3:

    代码:

    package com.csu.marden;
    
    public class Demo5 {
    	static{
    		System.out.println("static");
    	}
    	{
    		System.out.println("no static");
    	}
    	Demo5(){
    		System.out.println("constructor");
    	}
    	
    	
    	
    	public static void main(String[] args) {
    		Demo demo1=new Demo();
    		Demo demo2=new Demo();
    	}
    
    }
    

    执行结果:

    分析:

    上述Demo类包含静态代码块,非静态代码块和构造方法。上述代码首先完成了类加载,即静态代码块执行,且仅执行一次。然后创建了该类的两个实例,首先执行了非静态代码块,然后执行了构造方法。并且非静态代码块和构造方法,在每次创建新的对象时,都会被执行一次。

     

    二、父类和子类中静态代码块,非静态代码块,构造方法的执行顺序

    在Java继承中,父类子类构造方法、静态代码块、非静态代码块的执行顺序:

    父类静态代码块 > 子类静态代码块 > 父类非静态代码块 > 父类构造方法 > 子类非静态代码块 > 子类构造方法

    示例1:

    代码:

    //父类
    public class Parent {
        static String name = "hello";
        {
            System.out.println("parent-no-block");
        }
        static {
            System.out.println("parent-static");
        }
    
        public Parent() {
            System.out.println("parent-constructor");
        }
        
    }
    
    
    
    //子类
    public class Child extends Parent {
        static String childName = "hello";
        {
            System.out.println("child-no-static");
        }
        static {
            System.out.println("child-static");
        }
    
        public Child() {
            System.out.println("child-constructor");
        }
    }
    
    
    
    
    //测试类
    public class Demo {
    	public static void main(String[] args) {
    		new Child();
    	}
    }
    
    
    
    

    执行结果:

    分析:

    Java继承体系中,若子类继承了父类,在创建子类的时候,首先会调用父类的构造方法和非静态代码块完成类实例的初始化,然后调用子类的构造方法和非静态代码块完成类实例的初始化(子类需要根据父类的构造方法生成)。

    所以在执行时(创建子类对象时),首先加载父类,即执行父类的静态代码块,且只执行一次,然后加载子类,即执行子类的静态代码块,同样只执行一次。然后执行父类的非静态代码块和构造方法完成父类实例的初始化,最后执行子类的非静态代码块和构造方法完成子类实例的初始化。

     

     

    示例2:

    代码:

    //父类
    public class Parent {
        static String name = "hello";
        {
            System.out.println("parent-no-block");
        }
        static {
            System.out.println("parent-static");
        }
    
        public Parent() {
            System.out.println("parent-constructor");
        }
        
    }
    
    
    
    //子类
    public class Child extends Parent {
        static String childName = "hello";
        {
            System.out.println("child-no-static");
        }
        static {
            System.out.println("child-static");
        }
    
        public Child() {
            System.out.println("child-constructor");
        }
    }
    
    
    
    
    //测试类
    public class Demo {
    	public static void main(String[] args) {
    		new Child();
            new Child();
    	}
    }
    
    
    
    

    执行结果:

    分析:

    在执行时(创建子类对象时),首先加载父类,即执行父类的静态代码块,且只执行一次,然后加载子类,即执行子类的静态代码块,同样只执行一次。然后执行父类的非静态代码块和构造方法完成父类实例的初始化,最后执行子类的非静态代码块和构造方法完成子类实例的初始化。由于本例中创建了两个子类对象,所以执行两次父类非静态代码块和构造函数,子类非静态代码块和构造函数。

     

     

     

     

    展开全文
  • Java的静态代码块、非静态代码块、构造函数的简单的java代码
  • 静态代码块和非静态代码块什么时候执行? 静态代码块随着类的加载而加载,非静态代码块随着对象的加载而加载 所以静态代码块再调用类的时候执行。非静态代码块创建对象时或者通过反射获取其类信息的时候执行 ...
  • 总结: 在外部调用静态方法时,可以使用”类名.方法名”的方式,也可以使用”对象名.方法名”的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。...static{}静态代码块与{}非静态...
  • 测试函数 public class TestStaticCon { public ... System.out.println"父类的非静态代码块在执行a=" + a; } { a = 8; System.out.println"父类的非静态代码块在执行a=" + a; } public TestStaticCon) { this"a在
  • java静态代码块与非静态代码块比较

    千次阅读 2018-10-23 00:20:45
    得出结论1:非静态代码块不会在调用方法与成员时执行.     结论2:非静态代码块在创建实例时执行   结论3:非静态代码块每次创建实例时执行,而静态代码块只执行一次 结论4:静态代码块优先非静态代码块优先...
  • 静态代码块和非静态代码块的区别

    千次阅读 2018-06-02 16:19:34
    摘自原文小结:1、静态代码块是在类加载时自动执行的,非静态代码块在创建对象自动执行的代码,不创建对象不执行该类的非静态代码块。 顺序: 静态代码块--》非静态代码块--》类构造方法。2、在静态方法里面只能直接...
  • 执行顺序:静态代码块--非静态代码块--默认构造方法--普通方法 使用地方:非静态代码块可在普通方法中定义(不过作用不大)。静态代码块必须在类中进行 使用场景:静态代码块可用来初始化一些项目最常用的变量或对象...
  • 1、静态代码块(静态初始化块,静态域): 使用static关键字和{}声明的代码块,格式如下: public class People{ static{ System.out.println("静态代码块"); } } 作用: 需要在项目启动时就执行的代码...
  • 静态代码块是以static修饰的代码块,反之没有用static修饰的代码块为非静态代码块,如下所示: 静态代码块: static{ 若干代码 } 非静态代码块: { 若干代码 } 它们之间的区别主要如下: 静态代码块在...
  • java中静态和非静态代码块

    千次阅读 2017-11-18 21:34:37
    java中经常有一些静态块,这是用来在生成类之前进行的...非静态语句代码块 } 异同点 相同点:都是在JVM加载类时且在构造方法执行之前执行,在类中都可以定义多个,一般在代码块中对一些static变量进行赋  值
  • ③父类非静态代码块>>④父类构造函数>>⑤子类非静态代码块>>⑥子类构造函数 大致总结: 父类早于子类,静态早于非静态,非静态早于构造函数。 1、验证代码 package ...
  • 先给出代码,大家可以先思考一下将会打印什么内容: public class StaticTest { public static void main(String[] args) { staticFunction(); System.out.println("main中b:"+b); } static StaticTest static...
  • 静态代码块在第一次创建对象的时候执行...非静态代码块每创建一次对象就执行一次。class Cat{ Cat(){ System.out.println("构造代码块"); } static{ System.out.println("静态代码块"); } { System.out.println
  • 主要探讨一下关于静态代码块,非静态代码块,构造函数的执行顺序。 如有错误,欢迎指出。首先: 静态成员变量和静态代码块的优先级是一样的,先定义的先执行。 在创建一个对象的时候会执行非静态代码块和构造函数...
  • 它们之间的执行顺序为:静态代码块—>非静态代码块—>构造方法。静态代码块只在第一次new执行一次,之后不再执行,而非静态代码块在每new一次就执行一次。非静态代码块可在普通方法中定义(不过作用不大);而静态代码...
  • 序言 前几天在复习J2SE的时候,看到了这个Java类在new的过程中,静态域、静态块、非静态域、非静态块、构造函数的执行... 实现自身的静态属性和静态代码块。 注意:它们两个的执行顺序根据自身出现的顺序决定2...
  • public class Test { public Test() { ... //非静态代码块 { System.out.print("非静态代码块!--"); } //静态代码块 static { System.out.print("静态代码块!--"); } private static void test() { .
  • java静态代码块、非静态代码块、构造器执行顺序 1)有静态代码块,先执行父类静态代码块,再执行子类静态代码块;...2)有非静态代码块,先执行父类非静态代码块,父类构造器,再执行子类非静态代码块,子类构造器
  • 1、静态代码块和非静态代码块: 相同点:都是JVM加载类时且在构造函数执行之前执行,在类中都可以定义多个,一般在代码块中对一些static变量进行赋值。 不同点:静态代码块在非静态代码块之前执行。静态代码块只...
  •     ...与构造器作用非常类似的是初始化,它也可以对Java对象进行初始化操作。 初始化      &nbsp...
  • java静态代码块面试题 public class Father { static{ System.out.println("Father___的静态代码块&amp...
  • 一、观察一段源码与结果 public class StaticDemo { private static int i=1; static { System.out.println("static前代码块执行顺序...System.out.println("static代码块执行顺序为"+i); i=i+1; } public StaticDem
  • 3,非静态代码块优于构造函数执行 所以执行顺序如下: 父类B静态代码块->子类A静态代码块->父类B非静态代码块->父类B构造函数->子类A非静态代码块->子类A构造函数 转载于:...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 297,117
精华内容 118,846
关键字:

非静态代码块