Java面试Day05-Integer a = 100,Integer b = 100,a == b的结果是?

经过昨天的学习,我们了解了关于"=="的一些知识:

== 的作用:
  基本类型:比较的就是值是否相同
  引用类型:比较的就是地址值是否相同

根据,昨天的学习,我们会觉得 a和b是引用类型,那么 a==b 肯定是false呀,但是结果如下:

诶?这是为什么呢?明明a和b是两个不同的对象,但是为什么a==b是true呢?解释如下:

Integer内部使用了享元模式的设计,什么是享元模式呢?

享元模式是一种结构型设计模式,它旨在通过共享相似对象的部分状态来节省内存和提高性能。在 Java 中,享元模式通常通过使用工厂模式来实现。

在享元模式中,有两种类型的对象:内部状态和外部状态。内部状态是不会改变的,可以被多个对象共享。外部状态是会变化的,每个对象都具有自己的外部状态。

下面是一个简单的 Java 代码示例,展示了如何使用享元模式:

// 创建一个接口定义享元对象的操作
interface Flyweight {
    void operation();
}

// 创建具体的享元对象实现接口
class ConcreteFlyweight implements Flyweight {
    private String intrinsicState;
    
    public ConcreteFlyweight(String intrinsicState) {
        this.intrinsicState = intrinsicState;
    }
    
    public void operation() {
        System.out.println("具体享元对象的操作,内部状态为:" + intrinsicState);
    }
}

// 创建享元工厂类用于创建和管理享元对象
class FlyweightFactory {
    private Map<String, Flyweight> flyweights = new HashMap<>();
    
    public Flyweight getFlyweight(String key) {
        if (flyweights.containsKey(key)) {
            return flyweights.get(key);
        } else {
            Flyweight flyweight = new ConcreteFlyweight(key);
            flyweights.put(key, flyweight);
            return flyweight;
        }
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        FlyweightFactory factory = new FlyweightFactory();
        
        // 获取享元对象并调用操作
        Flyweight fw1 = factory.getFlyweight("key1");
        fw1.operation();
        
        Flyweight fw2 = factory.getFlyweight("key2");
        fw2.operation();
        
        Flyweight fw3 = factory.getFlyweight("key1"); // 已存在的享元对象
        fw3.operation();
    }
}

在上面的示例中,ConcreteFlyweight 类表示具体的享元对象,FlyweightFactory 类充当享元工厂。客户端通过工厂类获取享元对象,并调用其操作。

通过使用享元模式,可以避免创建大量相似的对象,节省内存空间,并提高性能。

Integer中的享元模式,针对-128到127之间的数字做了一个缓存,使用Integer a = 100这个方式赋值的时候,java默认会通过valueOf这个方法对100这个数字进行一个装箱操作,从而触发了缓存机制,使得a和b指向了同一个Integer的内存地址。

在 Java 中,整型包装类 java.lang.Integer 使用了享元模式来缓存和重用整数对象。这个缓存的整数范围是 -128 到 127。

java.lang.Integer 类有一个静态内部类 IntegerCache,它作为整数缓存的实现。下面是 IntegerCache 类的源代码:

private static class IntegerCache {
    static final int low = -128;  // 缓存的最小整数值
    static final int high;        // 缓存的最大整数值,默认是 127
    static final Integer cache[]; // 整数对象缓存数组

    static {
        int h = 127;
        String integerCacheHighPropValue =
            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
            }
            catch( NumberFormatException nfe) {
                // 如果解析整数失败,使用默认值127
                throw new RuntimeException("Illegal value for property 'java.lang.Integer.IntegerCache.high': " + integerCacheHighPropValue);
            }
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);

        // 如果设置了 `-XX:AutoBoxCacheMax=n` JVM 参数,可以增加缓存容量
        if (high >= 127) {
            int size = Math.min(8192, high - low + 1);
            Integer[] newCache = new Integer[size];
            System.arraycopy(cache, 0, newCache, 0, cache.length);
            cache = newCache;
        }

        // 在需要的整数范围内,其他整数将不会被缓存,会通过 new Integer() 创建新的对象
    }

    private IntegerCache() {}
}

从上面的代码可以看出,IntegerCache 类首先根据系统属性 java.lang.Integer.IntegerCache.high 来确定缓存的最大整数值。如果没有设置该系统属性或解析失败,将使用默认值 127。然后,根据最小整数值和最大整数值初始化一个整数对象缓存数组。

缓存数组的大小默认为 high - low + 1,即缓存范围内的整数个数。如果缓存范围超过了 127,也就是超过了默认的缓存容量,会根据 -XX:AutoBoxCacheMax=n JVM 参数来增加缓存容量。

通过缓存数组,Integer 类能够重用并共享整数对象,避免通过 new Integer() 创建新的对象。

山的那边会是海吗?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值