温故而知新---
1. 用句柄操作对象
现实生活中,我们可以把遥控器当作句柄,电视机当作对象。当我们拿到句柄(遥控器)的时候,我们是可以控制对象的(电视机)。比如说调节音量大小,色彩等。那么在程序里,也是一样的道理,因为程序源于生活嘛!
public class Tv { /** * 调节电视音量大小 */ public void setSound(){ System.out.println("调节音量大小"); } public void setChannel(){ System.out.println("调电视频道"); } public static void main(String[] args) { // 通过new获取到句柄t Tv t = new Tv(); // 通过句柄t去操作电视机 // 调频道 t.setChannel(); // 调音量 t.setSound(); } }
以上代码就是通过句柄去操作对象的一个实例,假设有一个电视Tv的类,它有两个方法(行为,我们能换电视频道,调音量)。我们通过new Tv()获取到句柄。然后通过句柄去操作Tv类(遥控去操作电视)。
2. 所有对象都必须创建(new)
当我们用new创建一个对象得到对象的句柄之后,我们才能去操作对象的方法。如果不用new去创建的话,即使得到句柄(遥控器),但是并没有对象(电视机)。这个时候去用句柄去操作对象的话就会报错。
从上面图片我们可以看到,当没有用new去创建对象而直接去调用对象方法的时候,就会报一个句柄没有初始化。
2.1 对象保存到什么地方(图片来源https://blog.csdn.net/aijiudu/article/details/72991993)
寄存器:是最快的保存区域,位于处理器内部,但是因为数量十分有限,所以寄存器是根据需要又编译器分配,我们对它没有直接的控制权,也不可能在自己的程序里找到寄存器存在的任何痕迹。
方法区(静态存储):所有类级别数据将被存储在这里(包括类的名称、方法信息、字段信息)、静态变量、常量以及编译器编译后的代码等,每个JVM只有一个方法区,它是一个共享的资源。
堆:(在堆里分配存储空间时会花掉更长的时间)所有的对象和它们相应的实例变量以及数组将被存储在这里,每个JVM同样只有一个堆区。由于方法区和堆区的内存由多个线程共享,所以存储的数据不是线程安全的。
栈区:对每个线程会单独创建一个运行时栈。对每个函数呼叫会在栈内存生成一个栈帧(Stack Frame)。所有的局部变量将在栈内存中创建。栈区是线程安全的,因为它不是一个共享资源。所以句柄存在栈区里,而java对象并不放在其中。
本地方法栈:本地方法栈与Java栈的作用和原理非常相似。区别只不过是Java栈是为执行Java方法服务的,而本地方法栈则是为执行本地方法(Native Method)服务的。在JVM规范中,并没有对本地方发展的具体实现方法以及数据结构作强制规定,虚拟机可以自由实现它。在HotSopt虚拟机中直接就把本地方法栈和Java栈合二为一。