Java对象创建过程详解

概述

Java对象创建分为两个过程:声明对象和创建对象实体。类信息,对象引用,对象实体均在内存的不同区域。

内存结构

每一个Java引用程序均会唯一的对应一个JVM实例,而这个JVM实例将会完成对象内存分配,程序运行,垃圾回收等工作。JVM将其内存大致分类三个区域:方法区,栈区,堆区。

  • 方法区:是JVM在装载类文件时,用于存储类的所有描述信息的,这些信息主要包括,类的基本信息(访问修饰符,类名),字段信息(修饰符,类型,字段名),方法信息(修饰符,返回值类型,方法名,参数列表类型,异常,方法体字节码等等),常量池,静态区,classloader以及class引用。
  • 栈区:存放局部变量,基本数据类型和对象引用类型
  • 堆区:用于存放new产生对象的实体,每一个对象实体均会有自己的内存地址,一旦这个内存地址不被任何栈区对象引用,就会成为垃圾,随时会被GC回收。

成员变量和局部变量

  • 成员变量:在类中方法外,存储在堆内存中,随着对象的存在而存在,随着对象的消失而消失。有默认的初始化值。
  • 局部变量:在方法体中,存储在栈内存中,随着方法的调用而存在,随着方法的调用完毕而消失。没有默认的初始化值,所以必须先定义,赋值后才可以被使用。

对象创建过程

package combendy;

public class Demo_04 {
    static{
        System.out.println("Hello");
    }

    public static void main(String[] args) {
        Inner inner1 = new Inner();
        Inner inner2 = new Inner(30);
        System.out.println((inner1.ii==inner2.ii)+" "+Inner.ii);
        System.out.println(inner1.str==inner2.str);
    }
    static class Inner{
        private String str="hello";     //成员变量 存储在堆内存中
        private int i;
        private static int ii=10;    //静态变量,存储在方法区中(这也是为什么静态变量能在多个对象共享的原因)
        private static int iii;
//        静态代码块
        static{
            System.out.println("ii="+ii+",iii="+iii);
        }
//
        {
            System.out.println("str="+str+",i="+i+",ii="+ii+",iii="+iii);
        }

        public Inner(){
            ii=20;
            System.out.println("non-arguments");
        }
        public Inner(int i){
            this.i=i;
            System.out.println("one-arguments");
        }
    }
}

运行结果

Hello
ii=10,iii=0
str=hello,i=0,ii=10,iii=0
non-arguments
str=hello,i=0,ii=20,iii=0
one-arguments
true 20
true

步骤

  1. 将JVM加载进内存中
  2. JVM首先检查public类是否存在,存在就会将他加载进内存方法去中,否者抛出异常,结束进程
  3. 对类中静态字段进行初始化(若无显示初始化,就会被赋值为默认值),接着执行静态代码块
  4. 在栈中创建局部变量,堆中创建对象实体,为堆对象实体的成员变量(非静态)初始化,对于静态字段只需要从方法区的静态区中引用其值即可,执行构造代码块,接着执行构造函数(这里调用顺序会一直上溯到Object类,每一个构造方法的第一行为super()语句),最后将对象实体堆地址赋值给栈中引用变量。

要注意的是,实例字段包括自身定义的和从父类继承下来的(即使父类的实例字段被子类覆盖或者被private修饰,都照样为其分配内存)

C++中的引用和JAVA的引用作对比,其实他们两个只是“名称”一样,本质并没什么关系,C++中的引用只是给现存变量起了一个别名(引用变量只是一个符号引用而已,编译器并不会给引用分配新的内存),而JAVA中的引用变量却是真真正正的变量,具有自己的内存空间,只是不同的引用变量可以“指向”同一个对象而已。因此,如果要拿C++和JAVA引用对象的方式相对比,C++中的指针倒和JAVA中的引用如出一辙,毕竟,JAVA中的引用其实就是对指针的封装

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值