关于int和Integer缓存(一):以及设计构想(享元模式)
关于Integer的值缓存:
在介绍Integer的值缓存之前,我们需要了解的是,java中的包装类型,
我们都知道java中有包装类型
int Integer
double Double
char Character
boolean Boolean
...
为什么要使用包装?
包装类型源于java万物皆对象的思想
1.因为基本类型不具备对象的特性,所以就出现了包装类型(想象如果没有包装类型,Collection等集合中,就不能存放基本类型,泛型的使用就出现了尴尬点咯)
2.包装类提供的丰富的方法也简化和帮助我们完成了一些繁琐的操作(类型转化一系列parse操作)
3.假设一个业务需求,其中涉及到对多个值进行判断,最常见检测初始化,如果是int 类型等等基础类型,例如:
byte 0
short0
int 0
long 0L
float 0.0f
double0.0d
char '\u0000'
booleanfalse
这个时候,包装类型就难得可贵了,包装类型的默认值都是null!
但是为什么java不直接使用包装类型,同样保留了基础类型?
因为一些小的变量,通过对象的形式存储在堆中,就很浪费空间,而且操作也
没有那么高效了!
所以java中有了包装和基本类型
那么自动装箱和拆箱是怎么发生的呢?
因为包装类本质是引用类型,对象本身不能像基础类型一样进行操作,
例如:int、double、float的加减乘除(这里顺便一提,double有设计缺陷,进行减价乘除操作的时候,会出现精度错误和值错误的问题,需要使用:BigDecimal,请自行了解!)
所以在进行加减操作,把Integer的值赋给int类型的变量的时候,就会出现自动拆箱;
Integer n1 = new Integer(18);
n1 += 10;
n1++;
n1--;
int n2 = n1;
Integer i = new Integer(100);
int j = 100;
System.out.print(i == j); // 这里也会自动拆箱
在直接给Integer类型赋值时候(不通过new的方式进行赋值),就会出现自动装箱:
Integer n1 = 999;
首先我们做一个看似无关的测试,来巩固我们的思考:
如下运行:
Integer i = new Integer(100);
Integer j = new Integer(100);
System.out.print(i == j); //false
Integer i = new Integer(100);
int j = 100;
System.out.print(i == j); //true
Integer i = new Integer(100);
Integer j = 100;
System.out.print(i == j); //false
通过上面的例子,我们一一分析:
1.都是引用类型,对象比较堆空间中地址不同,肯定不相等!
2.第二个 一个是int类型,一个是Integer类型,因为Integer对应的是int的包装类,所以在进行比较之前要进行一次拆箱。
3.两个不同的Integer的声明方式一个是通过new对象的方式进行的,一个是通过直接赋值进行的,因为前一个肯定是引用类型,只要一边出现了引用类型,那肯定是不相等的!堆中地址不同。
Integer i = 100;
Integer j = 100;
System.out.print(i == j); //true
Integer i = 128;
Integer j = 128;
System.out.print(i == j); //false
注意上面,为什么我这里写的是128就不行,100就可以呢?
解释,分析以下源码片段(Integer):
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
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() {}
}
其中在第一个方法中有一个high和low,并且明确讲了,只有在low和hgih之间的数字才会进入内部类IntegerCache,
在IntergerCache中就做了一件事情:就是如果传入的数字是[-128, 127]之间数字,就直接存储进常量池中;如果不在这个范围内,就new Integer(xx)进行返回。
所以其实我们的一句 Integer n1 = 128 其实是通过了Integer内部进行new操作自动装箱的!
那为什么Integer要进行对-127到128之间的数据进行存入常量池中进行操作呢?
这里就涉及到java的23中设计模式中的享元模式了:这里简单介绍一下享元模式[享元模式就是把一些常用的常量等
共享出来,重复高效的去使用,以达到节约内存和提高效率的目的,JDK5.0之后的enum也是享元模式的一种体现]
学习参考,感谢:
https://www.zhihu.com/question/22775729
http://simon-c.iteye.com/blog/1016031
https://baike.baidu.com/item/%E4%BA%AB%E5%85%83%E6%A8%A1%E5%BC%8F/10541959
http://baijiahao.baidu.com/s?id=1584080745080984291&wfr=spider&for=pc
https://www.jianshu.com/p/9bd18eae9a1a
https://blog.csdn.net/chenliguan/article/details/53888018
关于int和Integer缓存(一):以及设计构想(享元模式)的更多相关文章
- php 23种设计模型 - 享元模式
享元模式 享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能.这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式. ...
- java设计优化-享元模式
享元模式是设计模式中少数几个以调高系统性能为目的的设计模式.它的核心思想是:如果在一个系统中存在多个相同的对象,那么只需共享一份对象的拷贝,而不必为每一次使用都创建新的对象.在享元模式中,由于需要构建 ...
- 设计模式(十二)——享元模式(Integer缓冲池源码分析)
1 展示网站项目需求 小型的外包项目,给客户 A 做一个产品展示网站,客户 A 的朋友感觉效果不错,也希望做这样的产品展示网站,但是要求都有些不同: 1) 有客户要求以新闻的形式发布 2) 有客户人要 ...
- 关于int和Integer缓存(二):修改缓存大小
续上文: java中的基础数据类型长度是否取决于操作系统? 在一些语言中,数据类型的长度是和操作系统有关系的,比如c和c++: 但是在java中,java的基础类型长度都是固定的,都是4个字节.因为j ...
- int 和 Integer 有什么区别
原文地址:https://blog.csdn.net/chenliguan/article/details/53888018 1 int与Integer的基本使用对比 (1)Integer是int的包 ...
- Java中 int和Integer的区别+包装类
--今天用Integer 和Integer 比较 发现有问题,于是去查了查. 1.Java 中的数据类型分为基本数据类型和引用数据类型 int是基本数据类型,Integer是引用数据类型: Inget ...
- 设计模式(含UML、设计原则、各种模式讲解链接)
一.统一建模语言UML UML是一种开放的方法,用于说明.可视化.构建和编写一个正在开发的.面向对象的.软件密集系统的制品的开放方法 UML展现了一系列最佳工程实践,这些最佳实践在对大规模,复杂系统进 ...
- java中int和Integer的区别?为什么有了int还要有设计Integer?
参考https://blog.csdn.net/chenliguan/article/details/53888018 https://blog.csdn.net/myme95/article/det ...
- 一、基础篇--1.1Java基础-int 和 Integer 有什么区别,Integer的值缓存范围
int和Integer的区别 int是基本数据类型,Integer是int的包装类. Integer必须实例化后才能使用,int变量不需要. Integer实际是对象的引用,生成一个新对象实际上是生成 ...
随机推荐
- 关于Xpath定位方法知道这些基本够用
一.写在前面 之前写过一些关于元素定位的文章,但是感觉都是很碎片,现在想做个整合,便有了这篇文章. 二.xpath的定位方法 关于xpath定位方法,网上写的已经很成熟了,现已百度首页为例,如下图: ...
- 《手把手教你》系列技巧篇(十)-java+ selenium自动化测试-元素定位大法之By class name(详细教程)
1.简介 按宏哥计划,本文继续介绍WebDriver关于元素定位大法,这篇介绍By ClassName.看到ID,NAME这些方法的讲解,小伙伴们和童鞋们应该知道,要做好Web自动化测试,最好是需要了 ...
- fatal error: all goroutines are asleep - deadlock!
一.问题截图 fatal error: all goroutines are asleep - deadlock! goroutine 1 [chan receive]: main.main() /U ...
- string子串匹配(用string自带函数,不涉及char数组转换)
using namespace std; #include <iostream> #include<string> //第1种,用string自带的s.subdtr()截取任意 ...
- 第二章 Vant的v-cell的v-for使用
遍历加载list数据,类似el-table 一.问题描述 由于VantUI中没有类似于el-table的table组件,看官网的范例,只找到了cell组件有v-for
- LinkedHashMap 的实现原理
LinkedHashMap 概述 HashMap 是无序的,HashMap 在 put 的时候是根据 key 的 hashcode 进行 hash 然后放入对应的地方.所以在按照一定顺序 put 进 ...
- PHP:字符串转数组,数组转字符串;字符串截取、替换、查找
字符串转数组$str = 'one|two|three|four'; print_r(explode('|', $str)); //explode 以字符串分割字符串到数组 $str = 'one t ...
- ES6新特征
1.块级作用域 { } 就是块级作用域,还包括if.else.for.while...下都属于块级作用域. let 声明的变量不存在变量的提升,不允许let反复声明同一个变量:块级作用域下let ...
- 3.python编程与计算机的关系,如何执行python文件
上一节预告了这一章想讲如何不停地和世界打招呼,这涉及到编程中一个重要的概念:循环. 但经过了两周断更后细想了一下,不行,我们得对上一章进行补充,而且这个补充非常关键!也印证了上一章所说的: 上一节章很 ...
- git 提代码时的相关命令,Mark一下
以前用命令提代码都是复制粘贴,现在换了工作后,特别是回退代码的命令又忘了,去网上查了好久,心累.特此Mark一下 1. 打patch: 1.1 git diff >> ljh.patch ...