Java中对象的实例化
基本概念
对象:内存上来说是分配在堆上面的一块内存区域
类:把一类具体事物相同特征,功能/行为抽象为属性与方法过程。
类是对象的模板,对象是类的具体表现。
构造函数:与类名同名的函数,用来实例化对象并初始化成员变量。
类的结构:
- 静态块:当对应的class文件被首次加载到虚拟机时执行。
- 代码块
- 构造函数
静态属性与变量首先加载。其次时静态块,之后是代码块,最后是构造函数。
在方法区中,存储了每个类的信息(包括类的名称、方法信息、字段信息)、静态变量、常量以及编译器编译后的代码等。【包括运行时常量池,在类和接口被加载到JVM后,对应的运行时常量池就被创建出来,存储编译期间生成的字面量和符号引用。】
堆数据区是用来存放对象和数组(特殊的对象)。堆内存由多个线程共享。堆内存随着JVM启动而创建。如果堆内存剩余的内存不足以满足于对象创建,JVM会抛出OutOfMemoryError错误。【堆区中不存放基本类型和对象引用,只存放对象本身。】
Java栈也称作虚拟机栈(Java Vitual Machine Stack),Java栈中存放的是一个个的栈帧,每个栈帧对应一个被调用的方法,完成压栈和出栈操作。Java栈是Java方法执行的内存模型。【栈帧:一个栈帧随着一个方法的调用开始而创建,这个方法调用完成而销毁。在栈帧中包括局部变量表(Local Variables)、操作数栈(Operand Stack)、指向当前方法所属的类的运行时常量池的引用(Reference to runtime constant pool)、方法返回地址(Return Address)和一些额外的附加信息。】
在JVM栈这个数据区可能会发生抛出两种错误:
1. StackOverflowError 出现在栈内存设置成固定值的时候,当程序执行需要的栈内存超过设定的固定值会抛出这个错误。
2. OutOfMemoryError 出现在栈内存设置成动态增长的时候,当JVM尝试申请的内存大小超过了其可用内存时会抛出这个错误。
对象实例化总述
当一个类被创建,并且这个类是首次被加载时(例如:A a=new A();),方法区会开辟出一块内存存放类的class文件并且将全部成员放入。之后会在堆中开辟一块内存,存储这个类并且将这个类的非静态的成员变量拷贝过来(静态成员不拷贝,所有实例共享),并持有对应的方法区的方法的句柄,这块内存有一个唯一内存地址,栈中的a对象指向的就是这个内存地址。
之后你为类的成员变量赋值时,堆中的变量的值会从默认值更改为设定值(方法区中变量无值)。
如果此时在实例化一个新的类(A a2=new A();),此时方法区中已经有一个A类的class,所以不会在创建一个A.class,但是此时会在堆中开辟一块新的空间并且将这个类的非静态成员拷贝并持有对应的方法区类的方法的句柄,这块内存空间标注一个新的内存地址。
此时,栈中a指向的是堆中第一个类的内存地址,a2指向的是堆中的第二个类的内存地址,而堆中这两块内存地址指向的是同一个方法区的class文件。
所以栈中对象要么存的是一个内存地址(引用)要么就是一个具体的值,存放的是一个具体值的话他就是一个基本变量。
对象实例化细节
对象实例化过程如下:
①加载类②为对象分配内存③对象属性的默认初始化④设置对象头⑤对象初始化(属性的显示初始化,代码块中的初始化,构造器中的初始化)
创建对象
创建对象的方式:
(1)new 的方式
(2)Class的newInstance()方法
(3)Constructor的newInstance()方法
(4)clone()的方式
(5)反序列化的方式
类加载
如果进行了类加载(包括已加载和未加载需要加载的情况),那么最终结果都是生成一个Class类对象。
Class类对象和对象实例
对象实例:Java中的一个类,由这个类的构造器 new
出来的对象就是对象实例。我们平常说的实例对象、对象实例,或者X类对象,都是同一个意思,都是指某个类实例化出来的对象。
Class类对象:Class类是一个实际存在的类,类名就叫Class(其含义不是我们常见的关键字class
)。这个类位于java.lang
包下,用于记录每一个类的类型信息。虚拟机会为每一个类(类或接口)都生成一个Class类对象,这个Class类对象就是Class这个类实例化出来的一个对象。每一个Class类对象都保存着虚拟机运行时,所对应的类的所有信息(比如类型,属性,方法,所在包名等等)。
Class类对象跟其他类对象一样都存放在堆区,但Class类的构造方法是私有的,所以我们在开发中不能显示的去调用并生成Class类对象,只有虚拟机才可以生成Class类的对象实例。Class类对象是在运行时提供某个对象的类型信息,故只在运行时才能通过Class类来获取对应的类的信息。一个类的所有实例对象共同拥有唯一的一个Class类对象。
为对象分配内存
首先计算对象占用空间的大小,接着就在堆中划分一块内存给新对象,如果实例成员变量是引用变量,仅分配引用变量空间即可(4个字节)。实际一个对象的大小在一步已经确定了。
内存是否规整:指针碰撞法/空闲列表法
处理并发安全问题:(堆空间是线程共享的)
- 采用CAS失败重试,区域加锁保证更新的原子性
- 为每一个线程预先分配一块TLAB(本地线程分配缓冲)
对象属性的初始化
在已经分配了的对象内存空间中,为对象的属性进行一个默认的初始化。即将对象的所有属性设为默认值(一般是零值),以保证对象实例字段在不赋值的情况下依然可以直接使用。
设置对象头
对象头分为两部分:Mark Word(运行时元数据)和类型指针。
①Mark Word:用于存储对象自身的运行时数据信息,如上述的哈希码、GC分代年龄、线程持有的锁等。
②类型指针:类型指针指向类的元数据,虚拟机通过这个指针确定该类在哪个变量中。
执行init方法进行对象的初始化
虚拟机执行init方法,以进行初始化成员变量,执行实例化代码块,调用类的构造方法,并把堆内对象的首地址赋值给引用变量。
执行完initi方法,把对象按照我们的意图进行初始化,这样一个真正可用的对象才算完全被创建出来。
< init >()方法中的代码顺序:
①静态变量②静态代码块③普通变量④普通代码块⑤构造器
父类和子类的初始化顺序:
①父类变量初始化②父类代码块③父类构造器④子类变量初始化⑤子类代码块⑥子类构造器
public class Customer {int id = 1001;String name;Account acct;{name = "匿名客户";}public Customer(){acct = new Account();}
}
class Account{
}
public class CustomerTest {public static void main(String[] args) {Customer customer = new Customer();}
}
参考:
java类实例化内存过程与面向对象特征_javarrr的博客-CSDN博客
【JVM第六篇--对象】对象的实例化、内存布局和访问定位 - 就行222 - 博客园
Java JVM 中 堆,栈,方法区 详解_张启露的博客-CSDN博客_java jvm 方法区
Java中对象的实例化相关推荐
- Java中对象的实例化顺序
文章目录 1 Java中对象的实例化顺序 1 Java中对象的实例化顺序 继承后的初始化顺序: 静态成员包括静态构造代码块,初始化顺序跟书写顺序有关.
- Java中创建(实例化)对象的五种方式
Java中创建(实例化)对象的五种方式 1.用new语句创建对象,这是最常见的创建对象的方法. 2.通过工厂方法返回对象,如:String str = String.valueOf(23); 3.运 ...
- java new 删除吗,java泛型对象初始化-java泛型对象会实例化吗T t=new T()
java泛型对象初始化--java泛型对象能实例化吗T t=new T() java中没法得到泛型参数化类型,因为在编译期没法确定泛型参数化类型,也就找不到对应的类字节码文件,自然就不行了 泛型反射的 ...
- 浅析Java中对象的创建与对象的数据类型转换
这篇文章主要介绍了Java中对象的创建与对象的数据类型转换,是Java入门学习中的基础知识,需要的朋友可以参考下 Java:对象创建和初始化过程 1.Java中的数据类型 Java中有3个数据 ...
- Java中对象的储存区
文章目录 1 两个重要的问题 2 C语言中数据的存储区 3 Java中对象的储存区 4 Java为什么采用动态内存分配? 4 为什么基本类型是特例? 1 两个重要的问题 对象的数据位于何处? 如何控制 ...
- Java中对象的三种状态
转载自 Java中对象的三种状态 Java中的对象的三种状态是和垃圾回收紧密相关的,因此有必要深究. 状态一:可触及态:从根节点开始,可以搜索到这个对象,也就是可以访问到这个对象,也有人将其称为可 ...
- Java中对象和引用的理解
2019独角兽企业重金招聘Python工程师标准>>> 偶然想起Java中对象和引用的基本概念,为了加深下对此的理解和认识,特地整理一下相关的知识点,通过具体实例从两者的概念和区别两 ...
- java中的的一些生命周期,Java中对象的生命周期
Java中对象的生命周期 (1) 对象生命周期的开始 对象生命周期开始时,需要为对象分配内存,并且初始化它的实例变量: 对象生命周期结束 Java虚拟机的垃圾回收线程回收对象的内存. (2) 创建一个 ...
- Java中对象的深复制(深克隆)和浅复制(浅克隆)介绍
1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. ⑵ ...
- [转载] java中对象作为参数传递给一个方法,到底是值传递,还是引用传递
参考链接: 用Java传递和返回对象 看完绝对清晰~ java中对象作为参数传递给一个方法,到底是值传递,还是引用传递? pdd:所谓java只有按值传递:基本类型 值传递:引用类型,地址值传递,所 ...
最新文章
- 华为等向联合国提议重构互联网:提议采用一种新的核心网络技术新标准,名为“New IP”...
- 将URL中的参数提取出来作为对象
- python3.8.2安装教程-在服务器上安装python3.8.2环境的教程详解
- 在Linux上如何安装Oracle数据库
- 计算机排版技能会操方案,实验九 Word的高级排版技巧.pdf
- 安装JDK以及配置Java运行环境
- 【Elasticsearch】elasticsearch 索引 详解 index
- 向上取整和向下取整(ceil、round)
- poj 3461 Oulipo kmp 预处理
- Spring Boot 2.3.3 正式发布!2.4.0 正式版即将发布!
- 磁盘位置_ORACLE RAC ASM磁盘组迁移到新的ASM磁盘组方法
- 数独游戏——数模处理(MATLAB整数规划)
- 数据分析——鸢尾花数据集
- Freeswitch+Sip.js实现软电话功能
- 麒麟桌面系统时间相关命令介绍
- 智慧养老平台推广文案列
- 正负图表,让数据展示更炫酷
- 怎么样关闭计算机的操作音,电脑报警音怎么关闭
- 媒体查询(media)-screen
- python使用ctypes调用c/c++函数