关于Integer
的一系列问题
在学习设计模式的时候,学到享元模式的时候,介绍到了
Integer
(小声BB,看了半天也没发现有啥一样的地方,哈哈哈),但是发现了Integer
中一个比较有趣的地方
完整代码:IntegerCache
是一个静态内部类哟,像单例模式的静态内部类写法,但没有方法获取,无法让Integer类以外的类使用。
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
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);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
以前背八股文的时候,总会遇到一个问题,那就是
Integer s1 = Integer.valueOf(127);
Integer s2 = Integer.valueOf(127);
System.out.println(s1 == s2);
以上代码输出为?答案是true
,原因嘛,就是因为上述代码。
【简单说明,在设计Integer
的时候,将用的最多最频繁的片段-128到127进行缓存,放在一个数组中,所以每次取这个范围内的Integer
类型返回的都是同一个变量,内存地址也是相同的,所以用==
进行判断返回为true
】
突然我看见一个非常陌生的代码片段
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
百度了一下,我发现这是Integer
中获取的Integer
缓存池最大值的方法。【默认范围是-128到127】
而上述的方法是用来获取integerCacheHighPropValue
,根据代码上下文意思判断这个值是可以改变Integer
初始化缓存-128到127范围的。
那么这个值如果改变了大小,以下代码会不会输出为true
呢?
Integer val1 = Integer.valueOf(128);
Integer val2 = Integer.valueOf(128);
System.out.println(val1 == val2);
Talk is cheap. Show me the code.
为了方便测试,我在springboot
项目中添加了启动选项
-Djava.lang.Integer.IntegerCache.high=300// 缓存最大值设置为300
接着,启动类中测试一下
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
// -Djava.lang.Integer.IntegerCache.high=300
Integer s1 = Integer.valueOf(127);
Integer s2 = Integer.valueOf(127);
System.out.println(s1 == s2);
Integer val1 = Integer.valueOf(128);
Integer val2 = Integer.valueOf(128);
System.out.println(val1 == val2);
}
}
结果是
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.3.7.RELEASE)
省略。。。。
2022-08-26 22:23:42.765 INFO 27604 --- [ main] com.ljq.demo.DemoApplication : Started DemoApplication in 1.039 seconds (JVM running for 1.675)
true
true
哈哈哈~证实了我的想法。
结论
-Djava.lang.Integer.IntegerCache.high=300
可以改变Integer默认缓存的范围,参考代码
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
最后还有几个面试题~
问:两个new Integer 128
相等吗?
答:不。因为Integer
缓存池默认是-128-127
;【问题出处在最后,但出处中这个问题的答案有问题】
问:可以修改Integer
缓存池范围吗?如何修改?
答:可以。使用-Djava.lang.Integer.IntegerCache.high=300
设置Integer缓存池大小
问:Integer
缓存机制使用了哪种设计模式?
答:亨元模式;
问:Integer
是如何获取你设置的缓存池大小?
答:sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high")
问:sun.misc.VM.getSavedProperty
和System.getProperty
有啥区别?
答:唯一的区别是,System.getProperty
只能获取非内部的配置信息;例如java.lang.Integer.IntegerCache.high
、sun.zip.disableMemoryMapping
、sun.java.launcher.diag
、sun.cds.enableSharedLookupCache
等不能获取,这些只能使用sun.misc.VM.getSavedProperty
获取
问题来自于 https://www.cnblogs.com/hujinshui/p/11350435.html
虽然第一个问题他写的是-127到128,但还是感谢解惑~