[Java source code series] Buffer pool principle of packaging class: Long source code analysis

This article takes Long as an example to take a look at the design of the buffer pool in the packaging class.

1. Structure

Buffer pool related code in Long:

public final class Long extends Number implements Comparable<Long> {
    
    
    // 用来保存具体long值
    private final long value;
    
    // 在构造时传入要封装的long值
    public Long(long value) {
    
    
        this.value = value;
    }
    
    // 注:这里需要静态成员(缓存数组:cache)所以是静态内部类
    private static class LongCache {
    
    
        // 私有构造函数,不能被new出来
    	private LongCache(){
    
    }
    	// 缓存(本质是一个数组)范围从 -128 到 127,+1 是因为有个 0
    	static final Long cache[] = new Long[-(-128) + 127 + 1];

    	// 容器初始化时,进行加载
    	static {
    
    
        	// 缓存 Long 值,注意这里是 i - 128 ,所以再拿的时候就需要 + 128
        	for(int i = 0; i < cache.length; i++)
            	cache[i] = new Long(i - 128);
    	}
	}
    
}

1.1 Packaging core one: packaging

Long is to encapsulate and extend the value of type long

1.2 Packaging core two: cache

Long implements a caching mechanism by itself, which caches all Long values ​​from -128 to 127. If it is a Long value in this range, it will not be initialized, but taken from the cache; the cache is loaded into the virtual Machine-time execution

As you can see, the idea of ​​designing the cache pool of the class: static container + static initialization ==> encapsulated into a static inner class . Then there is a question, why use static inner classes instead of static inner classes? Or the difference between static inner classes and non-static inner classes:

  1. Can there be static members
    • Static inner classes can have static members (attributes, methods), such as the above static final Long cache[]
    • Non-static inner classes cannot have static members (attributes, methods)
  2. Access members of external classes
    • Static inner classes can only refer to static members of outer classes
    • Non-static inner classes can access all members (attributes, methods) of outer classes
  3. Creation method
    Assuming that class A has static inner class B and non-static inner class C, the difference between creation B and C is:
    • Static inner class: AB b= new AB()
    • Non-static inner class: AC c = a.new C()

2. Method analysis & api

2.1 valueOf

 public static Long valueOf(long l) {
    
    
        final int offset = 128;
     	// 先在缓冲池中取
        if (l >= -128 && l <= 127) {
    
    
            // 这里+offest是要计算出索引,因为cache[0]=-127
            return LongCache.cache[(int)l + offset];
        }
        return new Long(l);
}

2.2 longValue & intValue

public long longValue() {
    
    
    	// 直接返回value
        return value;
}

intValue, in addition to floatValue, doubleValue

 public int intValue() {
    
    
    		// 直接强制类型装换
            return (int)value;
    }

3. Two questions

  1. Automatic boxing and automatic unboxing?

    Each basic type has its own packaging class, and also has its own buffer pool. Take long as an example

    long –作为函参(装箱)–> Long –参加运算(拆箱)–> long

    • Autoboxing will automatically call the valueOf method at compile time
    • Automatic unboxing will call the longValue method
  2. Why is it recommended to use the valueOf method more and the parseLong method less when using Long?
    Because Long itself has a caching mechanism that caches Longs in the range of -128 to 127, the valueOf method will get the value from the cache. If the cache is hit, it will reduce resource overhead. The parseLong method does not have this mechanism.

Guess you like

Origin blog.csdn.net/weixin_43935927/article/details/108540524