[学习笔记]Java面向对象思想和内存模型

概念

面向对象的程序由对象组成,每个对象包含对用户公开的特定功能部分和隐藏的实现部分。 一般来说,算法加上数据结构组成程序,在以往的面向过程的程序设计中,算法是第一位的,数据结构是第二位的,整体实现注重过程实现。而面向对象程序设计在思维上完全不同,他调换了这个次序,将数据放在第一位,然后再考虑操作数据的算法。

注意

1. 数据和其行为的打包封装。 2. 程序的接口和实现的解耦。 这样做的好处就是提高软件的重用性、灵活性和扩展性。

举例

比如:从饮水机接水喝
以往的面向过程思想是: 1. 我拿着我的杯子放到饮水机出水口。 2. 按下饮水机开关。 3. 开关带动饮水机阀门,如果桶里有水就会流到杯子里。 4. 杯子接满水,关闭开关。 如果换成其他人,那么又得重新设计一套这样的行为。

面向对象的思想是: 我和饮水机都是对象。 1. 我这个对象将杯子递给饮水机,并让饮水机帮我接水 2. 水接满后饮水机将杯子还给我 中间的开关,桶里有没有水的判断,将水接杯子里就不是我关心的问题了,这些行为全部交给饮水机这个对象实现,如果换成其他人,同样可以将他们的杯子递给饮水机来实现这一动作,这里饮水机的重用性就体现出来了。而如果饮水机升级了,有了加热净水功能,也很方便,只需要添加饮水机对象所具有的行为即可,也就是提高了灵活性。以后出现了带有空气净化功能甚至可扩展插件的高级饮水机,可以从饮水机继承创建新的对象,也可以向上抽取定义接口等,也就是提高了扩展性。

这里我们将视角从动作的执行者转换为领导者,将软件设计的重心从算法转移到数据上来,将复杂的问题简单化,就是面向对象的思维。

面向对象的特征

封装 继承 多态 封装使得面向对象程序具有更佳的复用性 继承使得面向对象程序具有更佳的扩展性 多态使得面向对象程序具有更佳的扩展性和灵活性

类和对象

概述

类是构造对象的模板或蓝图,由类构造对象的过程称为创建类的实例。类中描述了事物的属性和行为,其属性对应于类的实例域(或称之为成员变量),行为对应于类的方法(或称之为成员函数)。 Java中,所有的类都源自于“上帝”Object类。 使用面向对象思想设计程序时,先查找具有所需功能的对象来用,如果没有就自己创建一个具有所需功能的对象,提高软件复用性。 当使用构造器创建对象时,对象变量和对象是不同的,例如: Date birthday = new Date(); 这里birthday是个对象变量,指向一个Date对象的引用,这时可以通过对象变量birthday调用该对象的方法。但是如果对象变量没有指向任何对象的引用,比如: Date birthday = null;则必须先初始化这个变量才可以调用方法: birthday = new Date();。

实例域和局部变量的区别

实例域: 1. 实例域定义在类中,在整个类中都可以被访问。 2. 实例域随着对象的建立而建立,存在于对象所在的堆内存中。 3. 实例域有默认初始化值。

局部变量: 1. 局部变量只定义在局部范围内,如:函数内,语句内等。 2. 局部变量存在于栈内存中。 3. 作用的范围结束,变量空间会自动释放。 4. 局部变量没有默认初始化值。

匿名对象

匿名对象是一般对象的简化形式,一般用于: 1. 当对对象方法仅进行一次调用时使用。 2. 匿名对象可以作为实际参数进行传递。

封装

封装就是隐藏对象的属性和实现细节,仅对外提供公共访问方式。 实现封装的关键在于: 1. 绝对不能让类中的方法直接访问其他类的实例域(使用 private 关键字修饰实例域)。 2. 程序仅能通过对对象的方法与对象数据进行交互。 这是提高复用性和可靠性的关键。 其好处是显而易见的: 1. 将变化隔离。 2. 便于使用。 3. 提高重用性。 4. 提高安全性。

示例

public class Person {
// 实例域用private修饰,隐藏属性
private String name;
private int age;
 
// 通过一系列set和get方法,实现和实例域数据的交互
public String getName() {
return name;
}
 
public void setName(String name) {
this.name = name;
}
 
public int getAge() {
return age;
}
 
public void setAge(int age) {
this.age = age;
}
}

内存模型

《[学习笔记]Java面向对象思想和内存模型》

堆区

1. 存储的全部是对象,每个对象都包含一个与之对应的class的信息(class的目的是得到操作指令)。 2. JVM只有一个堆区(heap),且被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身。

栈区

1. 每个线程包含一个栈区,栈中只保存基础数据类型的变量和自定义对象的引用(不是对象本身),对象都存放在堆区中。 2. 每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。 3. 栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。

方法区

1.又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。 2.方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量,常量池等。

示例

public class Memory {
 
public static void main(String[] args) {
Demo d = new Demo();
d.run();
}
}
 
class Demo {

void run() {
System.out.println("Hello Java");
}
}
《[学习笔记]Java面向对象思想和内存模型》

  1. 首先启动JVM,读取 Memory.class 文件,将Memory类的类信息(包括实例域数据类型,静态变量,方法等)存放到运行时数据区的方法区中,称之为类的加载。
    执行main()方法: Demo d = new Demo();
  2. 在方法区中查找 Demo 类信息,没找到,读取 Demo.class ,将Demo类的类信息存放到运行时数据区的方法区中。
  3. 在堆区为一个新的 Demo 实例分配内存,这个 Demo 实例持有指向方法区的 Demo 类类信息的引用。
  4. 创建变量d,将其添加入main线程的栈区,并将其指向上一步堆区中创建的 Demo 实例地址。也就是说,变量d持有指向Demo实例的引用
    d.run();
  5. 执行run();方法时,JVM根据局部变量d持有的引用,找到堆区的Demo实例,再根据Demo实例持有的引用,找到方法区中Demo类的类信息,从而获得run()方法的字节码,接着执行该方法包含的指令。

    原文作者:java内存模型
    原文地址: https://blog.csdn.net/jacobvv/article/details/41797849
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞