Java单例模式详解:饿汉式与懒汉式的代码实现及区别

唐可
唐可
发布时间:2026-10-15 | 6人浏览过
原创

单例模式是Java中最常用的设计模式之一,旨在确保一个类只有一个实例,并提供全局访问点。本文将通过Java代码深入解析"饿汉式"与"懒汉式"两种核心实现方式,对比它们在对象创建时机、资源消耗及线程安全性上的差异,帮助开发者选择合适的实现方案。

单例模式的核心概念

单例设计模式的目的是保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。要实现这一目标,通常遵循以下四个步骤:

  • 构造器私有化:防止外部直接通过new关键字创建对象。
  • 内部创建对象:在类的内部静态初始化或按需实例化该唯一对象。
  • 暴露公共方法:提供一个静态的公共方法(通常命名为getInstance),供外部获取该实例。
  • 代码实现:根据需求选择具体的实现策略。

第一种实现:饿汉式(Eager Initialization)

饿汉式是在类被加载到JVM时就完成对象的创建。这种方式简单直接,不存在线程安全问题,但可能会造成资源浪费(如果对象非常庞大且可能从未被使用)。

第1步:编写饿汉式代码

以下代码演示了经典的饿汉式单例实现。我们在声明静态变量时直接实例化了对象。

package com.demo.single_;

public class test01 {
    public static void main(String[] args) {
        // 尝试直接new会被编译阻止,因为构造器已私有化
        // girlfriend g01=new girlfriend("小红"); 
        
        // 通过静态方法获取唯一实例
        girlfriend t01=girlfriend.getInstance();
        System.out.println(t01);
        
        girlfriend t02=girlfriend.getInstance();
        System.out.println(t02);
        
        // 验证是否为同一对象
        if(t01==t02)
            System.out.println("true");
    }
}

// 单例类
class girlfriend{
    private String name;
    
    // 1. 构造器私有化
    private girlfriend(String name){
        this.name=name;
    }
    
    // 2. 在类的内部直接创建实例(类加载时即完成)
    private static girlfriend g=new girlfriend("小红");
    
    // 3. 提供公共静态方法返回实例
    public static girlfriend getInstance(){
        return g;
    }
    
    @Override
    public String toString() {
        return "girlfriend{" +
                "name='" + name + '\'' +
                '}';
    }
}

注意:由于对象在类加载时就被创建,如果该对象是“重量级”资源(如占用大量内存或数据库连接),而程序运行过程中并未使用它,则会造成不必要的资源浪费。

第二种实现:懒汉式(Lazy Initialization)

懒汉式是在第一次调用getInstance方法时才创建对象实例。这种方式节省内存资源,但在多线程环境下需要注意线程安全问题。

第1步:编写懒汉式代码

以下代码展示了懒汉式的实现逻辑:先定义一个null引用的静态变量,在使用时判断是否为空,为空则创建。

package com.demo.single_;

public class test02 {
    public static void main(String[] args) {
        // new cat("大飞"); 错误:构造器私有
        
        System.out.println(cat.n); // 可访问静态变量
        
        // 第一次调用,触发实例创建
        cat instance=cat.getInstance();
        System.out.println(instance);
        
        // 第二次调用,直接返回已有实例
        cat instance2=cat.getInstance();
        System.out.println(instance2);
    }
}

// 懒汉式单例类
class cat{
    private String name;
    
    // 1. 构造器私有化
    private cat(String name) {
        System.out.println("构造器被调用");
        this.name = name;
    }
    
    // 2. 定义一个静态属性对象,初始为null
    private static cat c1;
    public static int n=999;
    
    // 3. 提供public的static方法,检查并返回对象
    public static cat getInstance(){
        if(c1==null){
            c1=new cat("大黄");
        }
        return c1;
    }
    
    @Override
    public String toString() {
        return "cat{" +
                "name='" + name + '\'' +
                '}';
    }
}

如上所示,只有当用户使用getInstance()且对象尚未存在时,才会执行new操作。后续再次调用时,将直接返回上次创建的c1对象。

饿汉式与懒汉式的关键区别

在实际开发中,理解两者的差异有助于做出正确的技术选型:

  1. 创建时机不同:饿汉式在类加载阶段就创建实例;懒汉式在首次调用getInstance方法时(使用时)才创建。
  2. 线程安全性:饿汉式天生安全,因为类加载过程由JVM保证线程安全;基础版懒汉式存在线程安全问题(多线程可能同时进入if(c1==null)块从而创建多个实例)。
  3. 资源利用:饿汉式可能存在资源浪费(创建了但未使用);懒汉式实现了延迟加载,节省了内存空间。
  4. 经典案例:Java SE标准类库中的java.lang.Runtime就是典型的单例模式应用。

以上就是Java单例模式中饿汉式与懒汉式代码实现及区别的详细内容,更多关于Java设计模式单例模式的资料请关注本站其它相关文章!

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表