int和Integer的区别与联系:包装类、自动拆箱装箱、享元模式
1、基本数据类型和引用数据类型
1.1、 基本数据类型:
java提供了8种基本数据类型:
boolean、byte、int、char、long、short、double、float;
java提供诸如:类、接口等引用数据类型,其中Integer就是一种引用数据类型,常被称为包装类。
1.2、int和Integer的区别
int是基本数据类型,Integer是int包装类。
Integer变量必须实例化后才能使用,int可以直接使用
Integer的默认值是null,int默认值是0
Integer变量实际上是对象的引用,指向new的Integer对象,int是直接存储数据。
2、包装类的自动拆箱装箱
2.1、什么是包装类
Java中的基本数据类型没有方法和属性,而包装类就是为了让这些拥有方法和属性,实现对象化交互
数值型包装类都继承至Number,而字符型和布尔型继承至Object。
2.2、什么是拆箱装箱
装箱:基本数据类型转换为包装类;
拆箱:包装类转换为基本数据类型。
3、享元模式
对于两个非new生成的Integer对象,进行比较时,如果两个变量的值在区间-128到127之间,则比较结果为true,如果两个变量的值不在此区间,则比较结果为false。
解析原因:归结于java对于Integer与int的自动装箱与拆箱的设计,是一种模式:叫享元模式(flyweight)。
(1)加大对简单数字的重利用,Java定义在自动装箱时对于在-128~127之内的数值,它们被装箱为Integer对象后,会存在内存中被重用,始终只存在一个对象。
(2)而如果在-128~127之外的数,被装箱后的Integer对象并不会被重用,即相当于每次装箱时都新建一个 Integer对象。
享元模式(Flyweight)又称为 轻量级模式,它是一种对象结构型模式。
面向对象技术可以很好地解决一些灵活性或可扩展性问题,但在很多情况下需要在系统中增加类和对象的个数。当对象数量太多时,将导致运行代价过高,带来性能下降等问题。享元模式 正是为解决这一类问题而诞生的。
享元模式 是对象池的一种实现。类似于线程池,线程池可以避免不停的创建和销毁多个对象,消耗性能。享元模式 也是为了减少内存的使用,避免出现大量重复的创建销毁对象的场景。
享元模式 的宗旨是共享细粒度对象,将多个对同一对象的访问集中起来,不必为每个访问者创建一个单独的对象,以此来降低内存的消耗。
享元模式 把一个对象的状态分成内部状态和外部状态,内部状态即是不变的,外部状态是变化的;然后通过共享不变的部分,达到减少对象数量并节约内存的目的。
享元模式 本质:缓存共享对象,降低内存消耗
主要解决
当系统中多处需要同一组信息时,可以把这些信息封装到一个对象中,然后对该对象进行缓存,这样,一个对象就可以提供给多处需要使用的地方,避免大量同一对象的多次创建,消耗大量内存空间。
享元模式 其实就是 工厂模式 的一个改进机制,享元模式 同样要求创建一个或一组对象,并且就是通过工厂方法生成对象的,只不过 享元模式 中为工厂方法增加了缓存这一功能。
优缺点
优点
享元模式 可以极大减少内存中对象的数量,使得相同对象或相似对象在内存中只保存一份,降低内存占用,增强程序的性能;
享元模式 的外部状态相对独立,而且不会影响其内部状态,从而使得享元对象可以在不同的环境中被共享;
缺点
享元模式 使得系统更加复杂,需要分离出内部状态和外部状态,这使得程序的逻辑复杂化;
为了使对象可以共享,享元模式 需要将享元对象的状态外部化,而且外部状态必须具备固化特性,不应该随内部状态改变而改变,否则会导致系统的逻辑混乱;
使用场景
系统中存在大量的相似对象;
细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关,也就是说对象没有特定身份;
需要缓冲池的场景;
code:
/**
* @author ypy
*/
public class Demo1 {
public static void main(String[] args) {
Integer i = 100;
Integer j = 100;
if(i.equals(j)){
System.out.println("i.equals(j) = "+i.equals(j));
}else {
System.out.println("i.equals(j) != "+i.equals(j));
}
/**
* 非new生成的Integer变量和new Integer()生成的变量比较时,结果为false。
* 因为非new生成的Integer变量指向的是静态常量池中cache数组,而cache数组中存储的指向了堆中的Integer对象,
* 而new Integer()生成的变量指向堆中新建的对象,两者在内存中的对象引用(地址)不同。
*/
Integer m = new Integer(5);
int n = 5;
System.out.println(m == n);
/**
* 对于两个非new生成的Integer对象,
* 进行比较时,如果两个变量的值在区间-128到127之间,则比较结果为true,
* 如果两个变量的值不在此区间,则比较结果为false
*
* 解析原因:归结于java对于Integer与int的自动装箱与拆箱的设计,是一种模式:叫享元模式(flyweight)。
* (1)加大对简单数字的重利用,Java定义在自动装箱时对于在-128~127之内的数值,
* 它们被装箱为Integer对象后,会存在内存中被重用,始终只存在一个对象。
* (2)而如果在-128~127之外的数,被装箱后的Integer对象并不会被重用,即相当于每次装箱时都新建一个 Integer对象。
*/
Integer i1 = 127;
Integer j1 = 127;
if(i1 == j1){
System.out.println("i1 == j1");
}else {
System.out.println("i1 != j1");
}
Integer i2 = 128;
Integer j2 = 128;
if(i2 == j2){
System.out.println("i2 == j2");
}else {
System.out.println("i2 != j2");
}
// 声明一个Integer对象,用到了自动的装箱:解析为:Integer num = Integer.valueOf(10);
Integer num = 10;
System.out.println("num = "+num);
//声明一个Integer对象
Integer num1 = 10;
// 进行计算时隐含的有自动拆箱
System.out.print(num1--);
}
}
执行结果: