发表时间:2022-03-25来源:网络
在面像对象的编程语言中,对象是一个很重要的概念,对象是面向对象语言编程中最基本的单元,面向对象编程语言的三大特点为继承、封装、多态;
继承:是指可以让某个类型的对象获得另一个类型的对象的属性的方法。
封装:也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
多态:就是指一个类实例的相同方法在不同情形有不同表现形式。
在java编程语言中,一切皆对象。所有的数据、文件、通信等都封装在一个对象里,而程序就是将这些对象组合起来调用其特有的数据处理逻辑构成的,所以面向对象编程语言比面向过程语言更为简洁易懂,可扩展性更好;
对象是java语言程序中最基本的单元,那一个对象是如何创建的?
在java语言中,对象是根据类中包含的构造方法来创建出来的,也就是说对象的创建直接是跟类相关的。
对象跟类的关系类似于这样的,一个类就相当于一个钞票刻板,通过钞票的刻板,可以生产出源源不断的钞票,而每一张钞票就相当于一个实例对象,每一张钞票不同的编号相当于实例对象有不同属性值。
获得一个对象的方法很多,最常用的是通过构造方法,即java中的内置关键字new创建对象,除此之外,还可以通过反射、克隆、反序列化的方式获得,本文介绍的基于new关键字创建的过程。
在JVM中,创建对象实例简单分为如下两步(第一步只会加载一次):
1、类构造器完成类初始化(分配内存、赋予默认值)
2、类实例化(赋予给定值)
首先,Jvm在执行时,遇到一个新的类时,会到内存中的方法区去找class的信息,如果找到就直接拿来用,如果没有找到,就会去将类文件加载到方法区。在类加载时,会经过验证准备解析等阶段,然后静态成员变量加载到方法区的静态区域,非静态成员变量加载到方法区的非静态区域。
静态代码块是在类加载时自动执行的代码,非静态代码块是在创建对象时自动执行的代码,不创建对象不执行该类的非静态代码块。
加载过程:
1、JVM会先去方法区中找有没有相应类的.class存在。如果有,就直接使用;如果没有,则把相关类的.class加载到方法区。
2、在.class加载到方法区时,先加载父类再加载子类;先加载静态内容,再加载非静态内容
3、加载静态内容:
把.class中的所有静态内容加载到方法区下的静态区域内
静态内容加载完成之后,对所有的静态变量进行默认初始化
所有的静态变量默认初始化完成之后,再进行显式初始化
当静态区域下的所有静态变量显式初始化完后,执行静态代码块
4、加载非静态内容:把.class中的所有非静态变量及非静态代码块加载到方法区下的非静态区域内。
5、执行完之后,整个类的加载就完成了。
对于静态方法和非静态方法都是被动调用,即系统不会自动调用执行,所以用户没有调用时都不执行,主要区别在于静态方法可以直接用类名直接调用(实例化对象也可以),而非静态方法只能先实例化对象后才能调用。
1、new一个对象时,在堆内存中开辟一块空间,分配地址。为新建对象分配内存实际上是从堆内存从划分出一块确定大小的内存,而分配的方式有两种:指针碰撞和空闲列表。
指针碰撞,指针碰撞就比较简单,如果堆中的内存是规整的,则直接将已使用的内存空间指针往空闲内存空间挪动与对象大小相等的距离;如图:
空闲列表,碰撞指针分配方式的前提是堆内存是规整的,而堆内存不规整时已使用堆内存和空闲内存会交叉容错一起,这个时候就不能靠简单地移动指针分配内存,而需要维护一个列表,去记录哪些内存是空闲可用的,分配内存时会从空闲列表上进行查找分配。
具体使用哪种内存分配方式,是根据垃圾收集器完成GC后,是否堆内存区域进行压缩整理决定的,指针碰撞相比于空闲列表法更简单和高效。
创建对象内存分配是一个非常频繁的行为,所以在很容易引发多线程并发的安全问题;HotSpot JVM虚拟机提供了两种解决方案,一种是使用CAS方式进行分配,CAS即比较并交换,一种安全的同步方式,JVM默认使用的就是这种方式。
还有另一种方式是TLAB(本地线程分配缓冲),这种方式是预先给每条申请的内存的线程分配一小块内存,这一小块内存就叫本地线程分配缓冲,当申请内存时,先从每条线程的分配缓冲区中进行各自分配,如果线程本地的缓冲区用完了,要申请新的缓冲区,才会进行同步锁定申请;虚拟机是否使用TLAB,可以通过-XX:+/-UseTLAB参数来设定;
2、把对象的所有非静态成员加载到所开辟的空间下,并赋予默认的零值(引用类型为null)。
3、所有的非静态成员加载完成之后,对所有非静态成员变量进行默认初始化。
4、所有非静态成员变量默认初始化完成之后,调用构造函数。
5、在构造函数入栈执行时,分为两部分:先执行构造函数中的隐式三步,三步分别为
① 执行super()语句
② 对开辟空间下的所有非静态成员变量进行显示初始化
③ 执行构造代码块
然后再执行构造函数中自定义的代码。
注意:执行 super语句时,可能出现以下三种情况:
1)构造方法体的第一行是this()语句,则不会执行隐式三步,而是调用this()语句所对应的的构造方法,最终肯定会有第一行不是this语句的构造方法。
2)构造方法体的第一行是super()语句,则调用相应的父类的构造方法,
3)构造方法体的第一行既不是this()语句也不是super()语句,则隐式调用super(),即其父类的默认构造方法,这也是为什么一个父类通常要提供默认构造方法的原因。
6、在整个构造函数执行完并弹栈后,把空间分配的地址赋给引用对象。
代码验证一下上述流程:

运行结果:
最后的结果跟上述流程时一致的,在代码中分别new了两个Studentd的对象,会先加载父类Person,先执行父类的static方法再执行子类的static方法,而且只执行了一次,说明只加载了一次,而之后创建了两次对象,每次创建子类对象,父类也会随之创建。
关注vx公众号 “JAVA西西”,领取JAVA学习面试资料!
上一篇:Java(1)
下一篇:java实现执行流程图
皓盘云建最新版下载v9.0 安卓版
53.38MB |商务办公
ris云客移动销售系统最新版下载v1.1.25 安卓手机版
42.71M |商务办公
粤语翻译帮app下载v1.1.1 安卓版
60.01MB |生活服务
人生笔记app官方版下载v1.19.4 安卓版
125.88MB |系统工具
萝卜笔记app下载v1.1.6 安卓版
46.29MB |生活服务
贯联商户端app下载v6.1.8 安卓版
12.54MB |商务办公
jotmo笔记app下载v2.30.0 安卓版
50.06MB |系统工具
鑫钜出行共享汽车app下载v1.5.2
44.7M |生活服务
2022-03-26
2022-03-26
2022-03-26
2022-03-26
2022-03-26
2022-03-26
2022-03-26
2022-03-26
2022-02-15
2022-02-14