You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否确保JVM中不存在两个相同的对象?类比RDBMS主键机制

如何让Java确保JVM堆中不存在重复的Book对象?

先看数据库模型:

Book
isbn primary key
title

在RDBMS中,数据库会通过主键isbn的唯一约束,确保不会存在两条相同的记录。

对应的Java对象模型如下:

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

当我们执行以下代码时:

Book b = new Book(123456);
Book c = new Book(123456);

JVM堆中会生成两个独立的Book实例,即便它们的isbn完全相同。那能不能像RDBMS那样,让Java保证堆中不会存在重复的对象?


可行方案

1. 带缓存的工厂模式(推荐,彻底控制实例唯一性)

通过工厂类封装对象创建逻辑,用缓存容器存储已创建的实例,确保相同isbn的对象只被实例化一次:

import java.util.HashMap;
import java.util.Map;

public class BookFactory {
    private static final Map<Integer, Book> bookCache = new HashMap<>();

    public static Book getBook(int isbn) {
        Book existingBook = bookCache.get(isbn);
        if (existingBook != null) {
            return existingBook;
        }
        Book newBook = new Book(isbn);
        bookCache.put(isbn, newBook);
        return newBook;
    }

    // 将Book设为内部类,构造方法私有,禁止外部直接实例化
    private static class Book {
        private int isbn;
        private String title;

        private Book(int isbn) {
            this.isbn = isbn;
        }

        // 必要的getter/setter
        public int getIsbn() { return isbn; }
        public String getTitle() { return title; }
        public void setTitle(String title) { this.title = title; }
    }
}

使用方式:

Book b = BookFactory.getBook(123456);
Book c = BookFactory.getBook(123456);
// b和c指向同一个对象,b == c结果为true

2. 重写equals()+hashCode()(逻辑去重)

如果无法限制外部直接new对象,可以通过重写Book的equals()和hashCode()方法,让isbn相同的对象被视为逻辑相等,再配合HashSet等集合实现去重:

public class Book {
    private int isbn;
    private String title;

    public Book(int isbn) {
        this.isbn = isbn;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Book book = (Book) o;
        return isbn == book.isbn;
    }

    @Override
    public int hashCode() {
        return Integer.hashCode(isbn);
    }

    // getter/setter
}

使用方式:

Set<Book> bookSet = new HashSet<>();
bookSet.add(new Book(123456));
bookSet.add(new Book(123456));
// bookSet的size为1,仅保留一个逻辑相同的对象

注意:这种方式只是逻辑层面的去重,如果外部直接创建两个isbn相同的实例,堆中依然会存在两个对象,只是集合会过滤掉重复项。如果要彻底确保堆中只有一个实例,优先选择工厂模式。


内容的提问来源于stack exchange,提问作者Faisal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 04:45:29