1. 属性:getters 和 setters
当数十名程序员同时开发一个大型项目时,如果他们以不同方式处理存储在类字段中的数据,问题往往会突然出现。
也许人们没有详细研究类文档,或者它没有描述每个案例。因此,经常会出现对象的内部数据“损坏”,从而使对象无效的情况。
为了避免这些情况,习惯上在 Java 中将所有类字段设为私有。只有类的方法可以修改类的变量。其他类的任何方法都不能直接访问变量。
如果您希望其他类能够获取或更改您的类对象中的数据,您需要向您的类添加两个方法——get 方法和 set 方法。例子:
代码 | 笔记 |
---|---|
|
private name field通过构造函数初始化字段 getName() — 此方法返回 name 字段的值setName() — 此方法更改 name 字段的值 |
没有其他类可以直接更改名称字段的值。如果有人需要获取 name 字段的值,他们将不得不调用对象getName()
上的方法Person
。如果某些代码想要更改名称字段的值,则需要调用对象setName()
上的方法Person
。
该getName()
方法也称为“名称字段的获取器setName()
”,该方法称为“名称字段的设置器”。
这是一种非常常见的方法。在 80-90% 的所有 Java 代码中,您永远不会在类中看到公共变量。相反,它们将被声明private
(或protected
),并且每个变量都有公共的 getter 和 setter。
这种方法使代码更长,但更可靠。
直接访问一个类变量就像让你的车通过双黄线转弯:它更容易也更快,但如果每个人都这样做,那么每个人的情况都会变得更糟。
假设您要创建一个描述点 ( x
, y
) 的类。以下是新手程序员的做法:
class Point
{
public int x;
public int y;
}
经验丰富的 Java 程序员会这样做:
代码 |
---|
|
代码更长吗?无疑。
但是您可以向 getter 和 setter 添加参数验证。例如,您可以确保 和x
始终y
大于零(或不小于零)。例子:
代码 | 笔记 |
---|---|
|
2. 对象生命周期
您已经知道对象是使用new
运算符创建的,但是如何删除对象呢?它们不会永远存在。内存不足。
在许多编程语言中,例如 C++,都有一个专门delete
用于删除对象的运算符。但是这在 Java 中是如何工作的呢?
在 Java 中,一切的安排都略有不同。Java 没有删除运算符。这是否意味着在 Java 中对象不会被删除?不,它们当然被删除了。否则,Java 应用程序会很快耗尽内存,而且不会有几个月不间断运行的程序。
在 Java 中,对象的删除是完全自动化的。Java 机器本身处理对象的删除。这个过程称为垃圾收集,收集垃圾的机制称为垃圾收集器( GC )。
那么 Java 机器如何知道何时删除一个对象呢?
垃圾收集器将所有对象分为“可达”和“不可达”。如果至少有一个对象的引用,则认为它是可达的。如果没有引用某个对象的变量,则该对象被认为是不可访问的,并被声明为垃圾,这意味着它可以被删除。
在 Java 中,您不能创建对现有对象的引用——您只能分配您已有的引用。如果我们删除对一个对象的所有引用,那么它就永远丢失了。
循环引用
在我们遇到一个简单的反例之前,这个逻辑听起来很棒:假设我们有两个相互引用的对象(存储对彼此的引用)。没有其他对象存储对这些对象的引用。
这些对象不能从代码中访问,但它们仍然被引用。
这就是垃圾收集器将对象分为可达和不可达,而不是“已引用”和“未引用”的原因。
可达对象
首先,将 100% 存活的对象添加到可达列表中。例如,当前线程 ( Thread.current()
) 或控制台 InputStream ( System.in
)。
然后,可达对象列表会扩展,以包括由初始可达对象集引用的对象。然后再次扩展以包含此扩展集引用的对象,依此类推。
这意味着如果有一些对象只相互引用,但是没有办法从可达对象中到达它们,那么这些对象将被认为是垃圾,将被删除。
3.垃圾收集
内存碎片
与对象删除相关的另一个重点是内存碎片。如果你不断地创建和删除对象,很快内存就会严重碎片化:占用的内存区域将散布在未占用的内存区域中。
结果,我们很容易陷入无法创建大对象(例如,具有一百万个元素的数组)的情况,因为没有大块的空闲内存。换句话说,可能有空闲内存,甚至很多,但可能没有大的连续空闲内存块
内存优化(碎片整理)
Java 机器以特定的方式解决了这个问题。它看起来像这样:
内存分为两部分。所有对象的创建(和删除)仅占内存的一半。当需要清理内存中的漏洞时,前半部分的所有对象都被复制到后半部分。但是它们是紧挨着复制的,所以没有孔。
该过程大致如下所示:
第 1 步:创建对象后
第二步:“洞”的出现
第三步:消除“洞”
这就是您不需要删除对象的原因。Java 机器只是将所有可到达的对象复制到一个新位置,并释放用于存储对象的整个内存区域。
GO TO FULL VERSION