静态什么时候用?

/*

 静态什么时候使用?
 1,静态变量。
    当分析对象中所具备的成员变量值都是相同的,这时这个成员就可以用静态修饰。
    注意点:只要数据在对象中是不同的,就是对象的特有数据,必须存储在对象中,是非静态的。

 2,静态函数。
    函数是否用静态修饰就参考一点,就是该函数功能是否有访问到对象中的特有数据。
    从源代码看,该功能是否需要访问非静态的成员变量。如果需要,该功能就是非静态的,反之,则可以定义成静态的。

    注意点:对象是用来封装特有数据的,你没有使用到特有数据,创建对象就没有意义,只会浪费空间。
            因此,函数功能不需要访问对象的特有数据时,建议定义成静态。
 */

class Demo
{
    int age;
    static int num = 9;

    public void speak() {
        System.out.println(age);
    }
}
public class Demo_14 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

    }

}
<think>单例模式(SingletonPattern)是一种常用的设计模式,它确保一个类只有一个实例,并提供一个全局访问点。**作用:** 1.控制资源的使用:例如线程池、缓存、日志对象等,这些资源通常只需要一个实例。2.避免状态不一致:如果多个实例可能导致状态不一致,使用单例可以避免。 3.节省资源:频繁创建和销毁对象会带来性能开销,单例可以减少这种开销。**什么时候使用:** -当需要控制实例数目,节省系统资源时。 -当类需要被频繁实例化,而创建的对象又频繁被销毁时(如管理线程池)。-当对象需要被共享的场合,如配置管理器、连接池等。**为什么不使用静态方法?** 静态方法也可以实现类似的功能,但两者有区别: 1. **面向对象特性**:单例是一个对象,可以继承和多态,而静态方法不行。 2. **可扩展性**:单例可以实现接口,可以被继承,而静态方法不行。3.**测试**:单例更容易进行单元测试,因为可以通过模拟对象进行测试,而静态方法则难以模拟。 4. **生命周期管理**:单例可以延迟初始化(LazyInitialization),在需要时才创建,而静态类通常在加载时就初始化。 5. **状态保持**:单例可以保持状态(虽然需要谨慎使用),而静态方法通常是无状态的(静态变量有全局状态,但难以控制)。 **示例代码(Java):** 以下是一个线程安全的懒汉式单例模式实现(双重检查锁定):```javapublicclass Singleton{// volatile确保多线程环境下变量的可见性和禁止指令重排序private volatilestatic Singletoninstance;//私有构造方法,防止外部实例化privateSingleton(){}public staticSingleton getInstance(){if (instance ==null){ //第一次检查synchronized(Singleton.class){ //加锁if(instance== null) {//第二次检查instance =new Singleton();}}}return instance;} }``` **解释:** -私有构造函数:防止外部通过`new`创建实例。 -`volatile`关键字:确保`instance`变量的可见性和有序性(防止指令重排序)。-双重检查锁定:第一次检查避免不必要的同步,第二次检查确保在同步块内只有一个线程创建实例。 另一种实现(静态内部类,推荐): ```javapublic classSingleton {privateSingleton(){}private staticclass SingletonHolder {privatestatic finalSingleton INSTANCE =new Singleton();}public staticSingleton getInstance(){return SingletonHolder.INSTANCE;} }``` **解释:** -静态内部类在第一次使用时才会加载,实现了懒加载。 -由JVM保证线程安全,因为类加载过程是线程安全的。**相关问题:**§§相关问题§§:1.单例模式在哪些场景下可能不适用?2.如何防止通过反射破坏单例模式?3.单例模式在分布式系统中如何保证唯一性?4.除了双重检查锁定和静态内部类,还有哪些实现单例模式的方式?</think>### 单例模式详解 #### 作用 1. **全局唯一实例**:确保类只有一个实例存在 2. **全局访问点**:提供统一访问入口(如 `getInstance()`) 3. **资源复用**:避免重复创建消耗资源的对象(如数据库连接池) 4. **状态共享**:保证全局状态一致性(如配置管理器) #### 使用场景 1. 需要频繁创建销毁的对象(线程池、缓存) 2. 需要全局访问点的核心服务(日志系统、配置管理器) 3. 资源敏感型对象(数据库连接池、文件系统) 4. 需要控制实例数量的场景(打印机服务) #### 与静态方法的区别 | 特性 | 单例模式 | 静态方法 | |------------------|-----------------------------|-------------------------| | 面向对象特性 | 支持继承/多态/接口实现 | 不支持 | | 生命周期控制 | 支持延迟初始化/销毁 | 类加载即初始化 | | 状态管理 | 可维护实例状态 | 只能通过静态变量 | | 测试难度 | 易模拟(通过接口) | 难模拟(硬编码依赖) | | 内存占用 | 按需实例化 | 类加载即占用内存 | #### Java 实现示例(线程安全) ```java public class DatabasePool { // volatile 保证多线程可见性 private volatile static DatabasePool instance; // 私有构造器阻止外部实例化 private DatabasePool() { // 初始化数据库连接 System.out.println("Initializing database pool..."); } // 双重检查锁定实现线程安全 public static DatabasePool getInstance() { if (instance == null) { // 第一次检查(避免不必要的同步) synchronized (DatabasePool.class) { if (instance == null) { // 第二次检查(确保单例) instance = new DatabasePool(); } } } return instance; } // 示例方法 public void query(String sql) { System.out.println("Executing: " + sql); } } // 使用示例 public class Main { public static void main(String[] args) { DatabasePool pool1 = DatabasePool.getInstance(); DatabasePool pool2 = DatabasePool.getInstance(); pool1.query("SELECT * FROM users"); System.out.println(pool1 == pool2); // 输出 true } } ``` #### 关键解释 1. **双重检查锁定**: - 第一次检查:避免每次调用都进入同步块 - 同步块:防止多线程同时创建实例 - 第二次检查:确保只有一个线程能创建实例 2. **volatile 关键字**: - 禁止指令重排序(防止返回未初始化完成的实例) - 保证多线程环境下变量的可见性 3. **私有构造器**: - 阻止外部通过 `new` 创建实例 - 防止反射攻击(可额外添加防护代码) #### 何时不用静态方法 1. 需要实现接口或继承父类时 2. 需要延迟初始化(特别是资源消耗大的对象) 3. 需要维护对象状态(如连接池的连接数统计) 4. 需要支持多态特性(如不同环境返回不同子类实例)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值