gpt4 book ai didi

java - 是否可以确保 JVM 中不存在两个相同的对象?

转载 作者:行者123 更新时间:2023-12-05 08:24:36 24 4
gpt4 key购买 nike

考虑这个数据库模型:

Book
isbn primary key
title

在 RDBMS 中,数据库确保上述模型不存在两个相同的行。

类似地,在 Java 中考虑这个对象模型:

Book
- isbn: int
- title: String
+ Book(isbn)

假设我们正在创建一个 Book 对象:

Book b = new Book(123456);

稍后,在代码的其他部分,我们再次创建一个相同的 Book 对象:

Book c = new Book(123456);

如果两个对象相同,Java 能否确保 JVM 堆中不存在两个对象?就像 RDBMS 一样?

最佳答案

Java 中没有自动为您执行此操作的内置机制。您可以为此构建一些东西,但可能不应该。如果你这样做,那么可能不会以你在问题中展示的方式出现。

首先:假设这些对象是不可变的,那么问题就简化为“不允许构造两个具有相同属性的对象”。这不是必要的限制,但通过这种方式我已经可以证明这种方法存在的问题。

第一个问题是它要求您在一个中央位置跟踪程序中的每个Book 实例。您可以很容易地做到这一点,方法是拥有一个在构造对象时填充的集合。

但是,这基本上会在您的程序中造成大量内存泄漏,因为如果没有其他东西卡在这个 Book 对象上,该集合仍然会引用它,从而防止它被垃圾收集。

您可以使用 WeakReference 解决该问题对象以保留您的 Book 对象。

接下来,如果您想避免重复,您几乎肯定需要一种方法来获取 Book 的“原始”实例(如果您无法创建新实例)。如果您只是使用构造函数,则无法做到这一点,因为构造函数不能“返回另一个对象”,它总是会创建并返回一个新对象。

因此,您需要的不是 new Book(12345),而是 BookFactory.getOrCreateBook(12345)。然后,该工厂可以根据需要获取具有给定 ID 的现有 Book 对象创建一个新对象。

一种使内存泄漏问题更易于处理的方法(并且还可能允许多个并行 session ,每个 session 都有其自己的组独特的Book对象)是使BookFactory 是一个 BookSession:即您实例化一个,它会跟踪它的书籍。现在 BookSession 是所有书籍的“根”,如果不再引用它(以及它创建的所有书籍)可能会被垃圾收集。

所有这些甚至都没有涉及线程安全,线程安全对于不可变对象(immutable对象)来说相当容易解决,但如果您希望在允许修改的同时仍保持唯一性,则可能会变得非常复杂。

一个简单的 BookSession 可能看起来有点像这样(请注意,我使用 record 只是为了简化此示例代码,这将使构造函数可见。在“真实”代码中,我会使用一个等效的普通类,其中构造函数对其他人来说是不可访问的):

record Book(int isbn, String title) {}

class BookSession {
private final ConcurrentHashMap<Integer, Book> books = new ConcurrentHashMap<>();

public Optional<Book> get(int isbn) {
return Optional.ofNullable(books.get(isbn));
}

public Book getOrCreate(int isbn, String title) {
return books.computeIfAbsent(isbn, (i) -> new Book(i, title));
}
}

您可以轻松地向 session 添加其他方法(例如 findByTitle 或类似的东西)。

并且如果您只想要一个BookSession,您甚至可以在某个地方拥有一个public static final BookSession BOOKS,如果您愿意的话(但是那时你已经重新创建了内存泄漏)

关于java - 是否可以确保 JVM 中不存在两个相同的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74611478/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com