• Java对象相关元素的初始化过程


    1、类的成员变量、构造函数、成员方法的初始化过程

         当一个类使用new关键字来创建新的对象的时候,比如Person per = new Person();JVM根据Person()寻找匹配的类,然后找到这个类相匹配的构造方法,这里是无参构造,如果程序中没有给出任何构造方法,则JVM默认会给出一个无参构造。当创建一个对象的时候一定对调用该类的构造方法,构造方法就是为了对对象的数据进行初始化。JVM会对给这个对象分配内存空间,也就是对类的成员变量进行分配内存空间,如果类中在定义成员变量就赋值的话,就按初始值进行运算,如果只是声明没有赋初始值的话,JVM会按照规则自动进行初始化赋值。而成员方法是在对象调用这个方法的时候才会从方法区中加载到栈内存中,用完就立即释放内存空间。

    初始化过程:成员变量->构造函数->成员方法。

    package com.yyq;
    /**
     * Created by Administrator on 2015-10-30.
     */
    class Person {
        int age;
        String name;
        public Person() {
            System.out.println("This is Person()");
            System.out.println("Name:" + this.name + ";  Age:" + this.age);
        }
        public void show() {
            System.out.println("This is show()");
            System.out.println("Name:" + this.name + ";  Age:" + this.age);
        }
    }
    public class Exercise01 {
        public static void main(String[] args) {
            Person per = new Person();
            per.show();
            per.age = 30;
            per.name = "Wendy";
            per.show();
        }
    }
    输出结果:
    This is Person()
    Name:null;  Age:0
    This is show()
    Name:null;Age:0
    This is show()
    Name:Wendy;Age:30

    2、类的成员变量、静态代码块、构造代码块、局部代码块、构造方法、成员方法的初始化过程

        静态代码块是在类中方法外成员位置出现,用了static修饰;一般用于给类进行初始化。静态代码块在这个类第一次被调用或实例化的时候就会被执行。 静态代码块只会执行一次,一般会用来初始化一些值,并且在所有对象中全局共享。构造代码块在类中方法外成员位置出现;可以把多个构造方法中共同的代码放到一起,每次调用构造都执行,并且在构造方法前执行,对对象进行初始化。局部代码块在方法中出现,局部位置;限定变量的生命周期,及早释放,提高内存利用率。

    初始化过程:静态代码块(只执行一次)->构造代码块(每次调用构造方法都执行)->构造方法。执行顺序与代码块所在的具体位置无关。

    局部代码块的初始化顺序由具体位置决定。

    package com.yyq;
    /**
     * Created by on 2015-10-30.
     */
    class CodeBlockDemo {
        //静态代码块
        static {
            int a = 1000;
            System.out.println("静态代码块1:"+a);
        }
        //构造代码块
        {
            int x = 100;
            System.out.println("构造代码块1:"+x);
        }
        //构造方法
        public CodeBlockDemo(){
            System.out.println("Exercise02()");
        }
        //构造方法
        public CodeBlockDemo(int a){
            System.out.println("Exercise02(int a):"+a);
        }
        //构造代码块
        {
            int y = 200;
            System.out.println("构造代码块2:"+y);
        }
        //静态代码块
        static {
            int b = 2000;
            System.out.println("静态代码块2:"+b);
        }
    }
    public class Exercise02{
        public static void main(String[] args) {
            //局部代码块
            {
                int x = 10;
                System.out.println("局部代码块1:"+x);
            }
            //出错:找不到符号
            //System.out.println(x);
            System.out.println("演示一---------------");
            CodeBlockDemo ex1= new CodeBlockDemo();
            System.out.println("演示二---------------");
            CodeBlockDemo ex2 = new CodeBlockDemo();
            System.out.println("演示三---------------");
            CodeBlockDemo ex3 = new CodeBlockDemo(1);
            {
                int y = 20;
                System.out.println("局部代码块2:"+y);
            }
        }
    }
    输出结果:
    局部代码块1:10
    演示一---------------
    静态代码块1:1000     ==>静态代码块只是在该类第一次创建对象的时候才会被调用,而且初始化顺序与代码所在具体位置无关
    静态代码块2:2000
    构造代码块1:100       ==>构造代码块在每次初始化对象的时候都会被调用,而且初始化顺序与代码所在具体位置无关
    构造代码块2:200
    Exercise02()
    演示二---------------
    构造代码块1:100       ==>构造代码块在每次初始化对象的时候都会被调用,而且初始化顺序与代码所在具体位置无关
    构造代码块2:200
    Exercise02()
    演示三---------------
    构造代码块1:100        ==>构造代码块在每次初始化对象的时候都会被调用,而且初始化顺序与代码所在具体位置无关
    构造代码块2:200
    Exercise02(int a):1
    局部代码块2:20          ==>局部代码块只是简单的顺序执行程序,与实际位置有关

        这里没有将成员变量和成员方法加入分析,但是我们可以知道,静态代码块在类加载的时候就已经初始化了,而成员变量是要在创建对象的时候才会根据构造方法进行分配内存,初始化赋值,所以如果你在静态代码块中打印成员变量或者成员变量赋值的话就会显示出错,显示要将变量类型改为static,而在构造代码块和构造方法中都能正常使用。

    初始化过程:静态代码块(只执行一次)->成员变量(每次创建对象都会初始化赋值)->构造代码块(每次调用构造方法都执行)->构造方法(每次创建对象都会调用相匹配的构造方法)->成员方法(对象调用的时候运行)。

    3、有继承关系的父类和子类的成员变量、构造方法、成员方法的初始化过程

         在创建子类对象的时候会去调用子类的构造方法,其实子类的构造方法的第一条执行语句是super();即会自动去调用父类的无参构造方法,也就是说会自动去检测子类所继承的父类,并对父类的成员变量进行初始化操作。初始化完父类的成员变量、构造方法后,就初始化子类的成员变量和构造方法。因为子类会继承父类的非私有成员变量和成员方法(这里我把成员变量和成员方法都定义为默认访问权限),所以子类中如果定义了相同的成员变量,在初始化的时候就会被覆盖,而成员方法在调用的时候如果父类有子类没有,就执行父类的方法,如果父类没有子类有就执行子类的方法,如果父类有子类也有的话,那子类的成员方法就是复写了父类的成员方法,那最终执行就是子类的成员方法。

    初始化过程:父类的成员变量->父类构造方法->子类成员变量->子类构造方法->父类/子类成员方法。

    package com.yyq;
    /**
     * Created by Administrator  on 2015-10-30.
     */
    class Father{
        int age = 40;
        String name = "Father";
        int num = 321;
        public Father(){
            System.out.println("Father()");
            System.out.println("Name:"+name+"; Age:"+age+"; Num:"+num);
        }
        public void show(){
            System.out.println("I am Father.");
        }
        public void play(){
            System.out.println("Father play.");
        }
    };
    class Son extends Father{
        int age = 15;
        String name = "Son";
        public Son(){
            System.out.println("Son()");
            System.out.println("Name:"+name+"; Age:"+age+"; Num:"+num);
        }
        public void show(){
            System.out.println("I am Son.");
        }
        public void study(){
            System.out.println("Son play.");
        }
    }
    public class Exercise03 {
        public static void main(String[] args){
            Son son = new Son();
            son.show();
            son.play();
            son.study();
        }
    }
    输出结果:

    Father()

    Name:Father; Age:40; Num:321

    Son()

    Name:Son; Age:15; Num:321

    I am Son.

    Father play.

    Son play.

     

    4、有继承关系的父类和子类的成员变量、静态代码块、构造代码块、构造方法,成员方法的初始化过程

        因为如果有继承关系的子类和父类,在创建子类对象的时候会自动的去调用父类的构造方法,对父类的数据进行初始化。但是如果父类和子类都有静态代码块的话,那会先执行父类的静态代码块,接着执行子类的静态代码块,因为静态代码块不需要创建对象才能执行,所以在加载类的时候首先运行静态代码块,然后接着运行父类的构造代码块和父类的构造方法,最后才是运行子类的构造代码块和子类的构造方法。

    初始化过程:父类静态代码块->子类静态代码块->父类构造代码块->父类构造方法->子类构造代码块->子类构造方法

    package com.yyq;
    /**
     * Created by Administrator on 2015-10-30.
     */
    class BaseClass{
        static
        {
            System.out.println("静态代码块BaseClass");
        }
        {
            System.out.println("构造代码块BaseClass");
        }
        public BaseClass() {
            System.out.println("构造方法BaseClass");
        }
    }
    class SonClass extends BaseClass {
        static {
            System.out.println("静态代码块SonClass");
        }
        {
            System.out.println("构造代码块SonClass");
        }
        public SonClass() {
            System.out.println("构造方法SonClass");
        }
    }
    public class Exercise04 {
        public static void main(String[] args){
            SonClass son1 = new SonClass();
            System.out.println("-------------------");
            SonClass son2 = new SonClass();
        }
    }
    输出结果:
    静态代码块BaseClass
    静态代码块SonClass
    构造代码块BaseClass
    构造方法BaseClass
    构造代码块SonClass
    构造方法SonClass
    -------------------
    构造代码块BaseClass
    构造方法BaseClass
    构造代码块SonClass
    构造方法SonClass
     
  • 相关阅读:
    TensorFlow 基础 (04)
    面向对象编程思想的介绍
    B2B、B2C、C2C、O2O的概念
    为什么我们需要域
    如何在阿里云服务器上搭建wordpress个人网站
    Ghost手动备份、还原系统详细图文教程
    IE浏览器下载文件保存时提示:“你没有权限在此位置中保存文件”解决办法
    电脑经常自动重启的一些解决办法
    ERP系统到底能做什么?
    SQL实用技巧:如何分割字符串
  • 原文地址:https://www.cnblogs.com/yangyquin/p/4924184.html
Copyright © 2020-2023  润新知