Java面向对象的内存分析
小伙伴们大家好,鸽了一周,不是偷懒,最近在开发刷题小程序,所以文章就来不及更新。不过小程序基本功能已完成,今天开始继续更新java系列,之前讲完了java的数组,那么今天就来看下java中的面向对象。
谈到面向对象就不得不想到封装、继承和多态的概念了,今天不讲这三个,先来简单介绍下面向对象和分析下对象的内存。
# 面向对象概述
面向对象是软件开发中的一类编程风格、开发范式。除了面向对象
,还有面向过程
、指令式编程
和函数式编程
。在所有的编程范式中,接触最多的还是面向过程和面向对象两种。
早期先有面向过程思想,随着软件规模的扩大问题复杂性的提高,面向过程的弊端越来越明显,出现了面向对象思想并成为目前主流的方式。
面向过程:
- 关注的焦点是过程,就是操作数据的步骤,如果某个过程的实现代码重复出现,那么就可以把这个过程抽取为一个函数
- 典型的语言为C语言,以函数为组织单位
- 是一种执行者思维,适合解决简单问题,扩展能力差、后期维护难度较大
面向对象:
- 关注的焦点是类,在计算机程序设计过程中,参照现实中的事物,将事物的属性特征、行为特征抽象出来用类表示
- 典型的语言有java、c++、c#、python和php等
- 是一种设计者思维,适合解决复杂问题,代码扩展性强、可维护性高
举例:人把东西装进冰箱。
# 面向过程
打开冰箱
把东西装进冰箱
把冰箱门关闭
# 面向对象
人{
打开(冰箱){
冰箱.开门();
}
操作(大象){
大象.进入(冰箱);
}
关闭(冰箱){
冰箱.关门();
}
}
冰箱{
开门(){}
关门(){}
}
大象{
进入(冰箱){}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 类和对象
类和对象都是面向对象的核心概念。
# 概述
类:具有相同特征的事物的抽象描述,是抽象的、概念上的定义。
对象:实际存在的该类事物的每个个体,是具体的,因而也称为实例。
可以理解为:类=>抽象概念的人,对象=>实实在在的某个人。
# 类的成员的概述
面向对象程序设计的重点是类的设计,类的设计其实就是成员的设计。
类是一组相关属性和行为的集合,这也是类最基本的两个成员。 属性:该类事物的状态信息,对应类中的成员变量。 行为:该类事物要做什么操作,或者基于事物的状态能做什么,对应类中的成员方法。
# 面向对象的步骤
要完成面向对象的功能,分为三个步骤,分别是类的定义、对象的创建、对象调用属性或方法。
类的定义: 类的定义使用关键字class,格式如下。
[修饰符] class 类名{
属性声明;
方法声明;
}
2
3
4
对象的创建: Java类的实例化即是创建类的对象,创建对象使用关键字new,语法如下:
//方式1:给创建的对象命名
类名 对象名 = new 类名();
//方式2:创建匿名对象
new 类名()
2
3
4
注:如果一个对象只需要调用一次就可以使用匿名对象,通常将匿名对象作为实参传递给一个方法调用。
对象调用属性或方法: 对象是类的一个实例必然具备该类事物的属性和方法,使用对象名.属性或对象名.方法的方式访问对象成员,如下:
//声明Animal类
public class Animal {
public int legs;
public void eat() {
System.out.println("Eating");
}
public void move() {
System.out.println("Move");
}
}
//声明测试类
public class AnimalTest {
public static void main(String args[]) {
//创建对象
Animal dog = new Animal();
dog.legs = 4; //访问属性
System.out.println(xb.legs);
dog.eat(); //访问方法
dog.move(); //访问方法
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 对象的内存解析
先来复习下之前说过的JVM的内存划分。
# JVM内存结构划分
HotSpot Java虚拟机的架构图如下,其中主要关心的是运行时数据区部分(Runtime Data Area)。
下面介绍下堆、栈和方法区:
- 堆(Heap):此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。这一点在Java虚拟机规范中的描述是,所有的对象实例以及数组都要在堆上分配。
- 栈(Stack):是指虚拟机栈,虚拟机栈用于存储局部变量等。局部变量表存放了编译期可知长度的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型,它不等同于对象本身,是对象在堆内存的首地址),方法执行完会自动释放。
- 方法区(Method Area):用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
# 对象的内存
在HotSpot虚拟机中,对象在堆内存中的存储布局可以划分为三个部分:对象头、实例数据和对齐填充,如下。
这里看下java对象和数组对象的内部结构:
其中对象头分为对象标记和类元信息,类元信息存储的是指向该对象类元数据的首地址。
下面写个示例代码看下内存解析:
class Person {
String name;
int age;
boolean isMale;
}
public class PersonTest {
public static void main(String[] args) {
Person p1 = new Person();
p1.name = "张三";
p1.age = 20;
p1.isMale = true;
Person p2 = new Person();
p2.age = 10;
Person p3 = p1;
p3.name = "李四";
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
内存解析图如下:
总之,凡是new出来的结构(对象、数组)都放在堆空间中,对象的属性也存放在堆空间中。创建一个类的多个对象(比如p1、p2),则每个对象都拥有当前类的一套"副本"(即属性),当通过一个对象修改其属性时不会影响其它对象此属性的值。当声明一个新的变量使用现有的对象进行赋值时(比如p3 = p1),此时并没有在堆空间中创建新的对象,而是两个变量共同指向了堆空间中同一个对象。当通过一个对象修改属性时,会影响另外一个对象对此属性的调用。
那么对象名中存储的是什么呢,先说结论:对象地址。下面举例:
public class StudentTest{
public static void main(String[] args){
System.out.println(new Student()); //Student@7856e922
Student stu = new Student();
System.out.println(stu); //Student@7e29154f
int[] arr = new int[5];
System.out.println(arr); //[I@893ea4e
}
}
2
3
4
5
6
7
8
9
直接打印对象名和数组名都是显示“类型@对象的hashCode值",所以说类、数组都是引用数据类型,引用数据类型的变量中存储的是对象的地址,或者说指向堆中对象的首地址。
今天的内容就到这里,关于类的成员下篇再做介绍,另外刷题小程序即将上线,届时刷题就方便多了,喜欢的话点个关注吧,下篇见!
🎁 公众号
小伙伴们大家好,上方扫码关注公众号「大数据技术开发」,与你分享我的成长历程与技术感悟~