您的位置 首页 java

怎么理解java中的“一切都是对象”?

今天我们来聊一聊 java 中的“对象”

前言

无论 C++还是 Java 都属于杂合语言, 尽管以 C++为基础,但 Java 是一种更纯粹的面向对象程序设计语言。 本文我们将一起来探讨Java 程序的基本 组件,深入体会“ java程序内的一切皆对象

一、对象的创建过程

创建句柄

在java中,我们实际操作的不是对象,而是指向对象的一个 句柄, 例如:

 String s;  

创建的只是句柄,并不是对象;若此时向 s 发送一条消息,就会获得 一个错误(运行期)。这是由于 s 实际并未与任何东西连接;因此创建一个 句柄 时,记住无论如何都进行初始化,例如:

 String s = "hello";  

创建对象

创建句柄时,我们希望它同一个新对象连接。通常用 new 关键字 达到这一目 的。new 的意思是:“把我变成这些对象的一种新类型”。例如:

 String s = new String("asdf");  

保存对象

程序运行时,我们最好对数据保存到什么地方做到心中有数。特别要注意的 是内存的分配。有六个地方都可以保存数据:

  1. 寄存器 :这是 最快的保存区域 因为它位于和其他所有保存方式不同的地方: 处理器内部 。然而, 寄存器的数量十分有限 ,所以寄存器是根据需要 由编译器分配 。我们对此 没有直接的控制权 ,也不可能在自己的程序里找到寄存器存在的任何踪迹。
  2. 堆栈: 驻留于常规 RAM(随机访问存储器)区域,但可通过它的“堆栈指针”获得处理的直接支持。堆栈指针若向下移,会创建新的内存;若向上移, 则会释放那些内存。这是一种特别快、特别有效的数据保存方式,仅次于寄存器。 创建程序时, Java 编译器 必须准确地知道堆栈内保存的所有 数据的“长度”以 及“存在时间 ”。这是由于它必须生成相应的代码,以便向上和向下移动指针。 这一限制无疑影响了程序的灵活性,所以尽管有些 Java 数据要保存在堆栈里——特别是对象句柄,但 Java 对象并不放到其中。
  3. 堆: 一种常规用途的内存池(也在 RAM 区域),其中保存了 Java 对象。
  4. 和堆栈不同,“内存堆”或“堆”(Heap)最吸引人的地方 在于编译器不必知道 要从堆里分配多少存储空间 ,也不必知道存储的数据要在堆里停留多长的时间。 因此,用堆保存数据时会得到更大的灵活性。要求创建一个对象时,只需用 new 命令编制相关的代码即可。执行这些代码时,会在堆里自动进行数据的保存。当 然,为达到这种灵活性,必然会付出一定的代价:在堆里分配存储空间时会花掉 更长的时间!
  5. 静态存储: 这儿的“静态”( static )是指“位于固定位置”(尽管也在RAM 里)。 类中的静态成员会随着类的加载而加载 程序运行期间,静态存储的数据将随时等候调用。可用 static 关键字 指出一个对象的特定元素是静态的。但 Java 对象本身永远都不会置入静态存储 空间。
  6. 常数存储: 常数值通常直接置于程序代码内部。这样做是安全的,因为它们永远都不会改变。有的常数需要严格地保护,所以可考虑将它们置入 只读存储器 (ROM)。
  7. 非 RAM 存储: 若数据完全独立于一个程序之外,则程序不运行时仍可存在,并在程序的控制范围之外。 其中两个最主要的例子便是“流式对象”和“固 定对象”。对于流式对象,对象会变成字节流,通常会发给另一台机器。而对于 固定对象,对象保存在磁盘中。即使程序中止运行,它们仍可保持自己的状态不 变。对于这些类型的数据存储,一个特别有用的技巧就是它们能存在于其他媒体 中。一旦需要,甚至能将它们恢复成普通的、基于 RAM 的对象。

说到这里,建议大家了解一下类的加载机制

Java中的主类型有哪些?

清除对象

本节将阐示 Java 如何帮助我们完成所有清除工作,从而极大了简化了 变量的“存在时间”(Lifetime)问题

主类型的作用域

作用域同时决定了java变量的“可见性”以及“存在时间”。作为在作用域里定义的一个变量,它只有在那个作用域结束之前才可使用。

注意尽管在 C 和 C++里是合法的,但在 Java 里不能象下面这样书写代码:

 {
int x = 12;
{
int x = 96; /* illegal */}
}  

编译器会认为变量 x 已被定义。所以 C 和 C++能将一个变量“隐藏”在一 个更大的作用域里。 但这种做法在 Java 里是不允许的,因为 Java 的设计者认 为这样做使程序产生了混淆

对象的作用域

Java 对象不具备与主类型一样的存在时间。用 new 关键字创建一个 Java 对象的时候,它会超出作用域的范围之外。所以假若使用下面这段代码:

 {
String s = new String("a  String ");
} /* 作用域的终点 */  

那么 句柄 s 会在作用域的终点处消失 。然而, s 指向的 String 对象依然占据着内存空间 。在上面这段代码里,我们没有办法访问对象,因为指向它的唯一一个句柄已超出了作用域的边界。

垃圾收集器

Java 有一个特别的“垃圾收集器”,它会查找用 new 创建的所有对象,并辨别其中哪些不再被引用。随后,它 会自动释放由那些闲置对象占据的内存,以便能由新对象使用。这意味着我们根 本不必操心内存的回收问题。只需简单地创建对象,一旦不再需要它们,它们就 会自动离去。 这样做可防止在 C++里很常见的一个编程问题:由于程序员忘记 释放内存造成的“内存溢出”。

文章来源:智云一二三科技

文章标题:怎么理解java中的“一切都是对象”?

文章地址:https://www.zhihuclub.com/180701.shtml

关于作者: 智云科技

热门文章

网站地图