JavaRush /Java 博客 /Random-ZH /对象生命周期

对象生命周期

已在 Random-ZH 群组中发布
你好!我想如果我们告诉您计算机上的内存大小是有限的,您不会太惊讶:)即使是比 RAM 大很多倍的硬盘,也可以装满您最喜欢的游戏、电视剧、等等。为了防止这种情况发生,您需要监视内存的当前状态并从计算机中删除不必要的文件。Java 编程与这一切有什么关系?直接的!毕竟,当 Java 机器创建任何对象时,都会为其分配内存。在一个真正的大型程序中,会创建数以万计的对象,每个对象都分配有自己的一块内存。对象生命周期 - 1但你认为所有这些物体存在多久了?它们在我们的程序运行的整个过程中都“存在”吗?当然不。尽管具有 Java 对象的所有优点,但它们并不是不朽的:) 对象有自己的生命周期。今天我们就写代码休息一下,看看这个过程:)而且,它对于理解程序的运行和管理资源非常重要。那么,物体的生命从哪里开始呢?喜欢一个人——从他出生,也就是创造开始。
Cat cat = new Cat();//вот сейчас и начался vital цикл нашего an object Cat!
首先,Java 虚拟机分配必要的内存量来创建对象。然后她创建了一个指向它的链接,在我们的例子中 -cat以便能够跟踪它。之后,所有变量都被初始化,构造函数被调用,你瞧,我们的新对象已经有了自己的生命:) 对象的寿命是不同的,这里没有确切的数字。无论如何,它都会在程序中存在一段时间并执行其功能。准确地说,只要存在对某个对象的引用,该对象就是“活着的”。一旦不再有任何链接,该对象就会“死亡”。例如:
public class Car {

   String model;

   public Car(String model) {
       this.model = model;
   }

   public static void main(String[] args) {
       Car lamborghini  = new Car("Lamborghini Diablo");
       lamborghini = null;

   }

}
在该方法中,main()兰博基尼暗黑破坏神汽车对象已经在第二行不再存在。原来只有一个链接,现在这个链接已经被分配了null。由于没有留下任何关于兰博基尼暗黑破坏神的参考资料,它变成了“垃圾”。无需重置链接:
public class Car {

   String model;

   public Car(String model) {
       this.model = model;
   }

   public static void main(String[] args) {
       Car lamborghini  = new Car("Lamborghini Diablo");

       Car lamborghiniGallardo = new Car("Lamborghini Gallardo");
       lamborghini = lamborghiniGallardo;
   }

}
这里我们创建了第二个对象,之后我们获取引用lamborghini并将其分配给这个新对象。现在Lamborghini Gallardo有两个引用指向该对象,但Lamborghini Diablo没有一个引用指向该对象。因此该对象Diablo就变成了垃圾。而这时候,Java内置的机制——垃圾收集器,或者说——垃圾收集器,GC就开始运作了。
对象生命周期 - 2
垃圾收集器是 Java 的一种内部机制,负责释放内存,即从中删除不需要的对象。我们选择一张带有机器人吸尘器的图片来描绘它并不是没有原因的。毕竟,垃圾收集器的工作方式大致相同:在后台,它“遍历”您的程序,收集垃圾,同时您实际上不与它交互。它的工作是删除程序中不再使用的对象。因此,它为其他对象释放了计算机中的内存。您还记得在讲座开始时我们说过,在日常生活中您必须监控计算机的状态并删除旧文件吗?因此,对于 Java 对象,垃圾收集器会为您执行此操作。垃圾收集器在程序运行期间会启动多次:不需要专门调用它并给出命令,尽管这在技术上是可行的。稍后我们会详细讨论它并更详细地分析它的工作过程。当垃圾收集器到达该对象时,就在其销毁之前,会在该对象上调用一个特殊方法 - finalize()。它可用于释放对象正在使用的一些额外资源。该方法finalize()属于该类Object。也就是说,除了您之前已经见过的equals()hashCode()和 之外,任何对象都具有它。toString()它与其他方法的不同之处在于,它……怎么说呢……非常任性。也就是说,在销毁对象之前并不总是调用它。编程是一件精确的事情。程序员告诉计算机做某事,计算机就会做。您可能已经习惯了这种行为,一开始您可能很难接受这个想法:“在对象被销毁之前,调用finalize()类方法Object。” 或者它没有被调用。如果我们运气好的话!” 然而,这是事实。Java 机器本身决定是否finalize()在每种特定情况下调用该方法。例如,为了进行实验,我们尝试运行以下代码:
public class Cat {

   private String name;

   public Cat(String name) {
       this.name = name;
   }

   public Cat() {
   }

   public static void main(String[] args) throws Throwable {

       for (int i = 0 ; i < 1000000; i++) {

           Cat cat = new Cat();
           cat = null;//вот здесь первый an object становится доступен сборщику мусора
       }
   }

   @Override
   protected void finalize() throws Throwable {
       System.out.println("Объект Cat уничтожен!");
   }
}
我们创建一个对象Cat,并在下一行代码中重置对它的唯一引用。如此——一百万次。我们已经明确地重写了该方法finalize(),并且它应该在每次销毁对象之前将字符串打印到控制台一百万次Cat。但不是!准确的说,它在我的电脑上只运行了37,346次!也就是说,我安装的 Java 机器在 27 种情况中只有 1 种决定调用某个方法finalize()- 在其他情况下,垃圾收集会在没有这种情况下继续进行。尝试自己运行此代码:结果很可能会有所不同。正如你所看到的,finalize()很难称其为可靠的合作伙伴:) 因此,对未来的一点建议:finalize()在释放一些关键资源的情况下,你不应该依赖该方法。也许 JVM 会调用它,也许不会。谁知道?如果您的对象在其生命周期内占用了一些对性能非常重要的资源,例如,它保持与数据库的开放连接,那么最好在您的类中创建一个特殊的方法来释放它们,并在对象被释放时显式调用它。不再需要。这样您就可以确定程序的性能不会受到影响。一开始我们就说过内存管理和垃圾清除非常重要,确实如此。对资源的不当处理以及对组装不必要对象的过程缺乏了解可能会导致内存泄漏。这是最著名的编程错误之一。程序员错误编写的代码可能会导致每次为新创建的对象分配新的内存,而垃圾收集器无法删除旧的、不必要的对象。既然我们用机器人吸尘器做了类比,想象一下,如果在启动机器人之前,你把袜子散落在房子周围,打碎了一个玻璃花瓶,并将拆解后的乐高积木留在地板上,会发生什么。当然,机器人会尝试做某事,但在某一时刻它会卡住。
对象生命周期 - 3
为了使其正常工作,您需要保持地板状况良好,并清除吸尘器无法处理的所有物品。垃圾收集器的工作原理相同。如果程序中存在大量无法收集的对象(例如袜子或机器人吸尘器的乐高积木),那么内存将在某一时刻耗尽。不仅你编写的程序会冻结,此时计算机上运行的所有其他程序也会冻结。他们也没有足够的内存。这就是 Java 中对象生命周期和垃圾收集器的样子。无需记住这一点:只需了解操作原理即可。在下一讲中,我们将更详细地讨论这些过程,但现在您可以返回解决 JavaRush 问题:) 祝您好运!
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION