Java 包装类型和基本数据类型的区别及分别什么时候应用

Java是面向对象的编程语言,一切都是对象,但是为了编程的方便还是引入了基本数据类型,为了能够将这些基本数据类型当成对象操作,Java为每一个基本数据类型都引入了对应的包装类型(wrapper class),int的包装类就是Integer,从Java 5开始引入了自动装箱/拆箱机制,使得二者可以相互转换,对应如下:

原始类型:boolean,char,byte,short,int,long,float,double

包装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double

顺便一提,Java中的基本数据类型只有以上8个,除了基本类型(primitive type),剩下的都是引用类型(reference type)。

一.所以最基本的一点区别是:Ingeter是int的包装类,int的初值为0,Ingeter的初值为null。除此之外还有区别,请看代码:

public class TestInteger {
    public static void main(String[] args) {
        int i = 128;
        Integer i2 = 128;
        Integer i3 = new Integer(128);
        System.out.println(i == i2); //Integer会自动拆箱为int,所以为true
        System.out.println(i == i3); //true,理由同上
        Integer i4 = 127;//编译时被翻译成:Integer i4 = Integer.valueOf(127);
        Integer i5 = 127;
        System.out.println(i4 == i5);//true
        Integer i6 = 128;
        Integer i7 = 128;
        System.out.println(i6 == i7);//false
        Integer i8 = new Integer(127);
        System.out.println(i5 == i8); //false
        Integer i9 = new Integer(128);
        Integer i10 = new Integer(123);
        System.out.println(i9 == i10);  //false
    }
}

为什么i4和i5比是true,而i6和i7比是false呢?关键就是看valueOf()函数了,这个函数对于-128到127之间的数,会进行缓存, Integer i4 = 127时,会将127进行缓存,下次再写Integer i5 = 127时,就会直接从缓存中取,就不会new了。所以i4和i5比是true,而i6和i7比是false。

而对于后边的i5和i8,以及i9和i10,因为对象不一样,所以为false。

以上的情况总结如下:

1,无论如何,Integer与new Integer不会相等。不会经历拆箱过程,new出来的对象存放在堆,而非new的Integer常量则在常量池(在方法区),他们的内存地址不一样,所以为false。

2,两个都是非new出来的Integer,如果数在-128到127之间,则是true,否则为false。因为java在编译Integer i2 = 128的时候,被翻译成:Integer i2 = Integer.valueOf(128);而valueOf()函数会对-128到127之间的数进行缓存。

3,两个都是new出来的,都为false。还是内存地址不一样。

4,int和Integer(无论new否)比,都为true,因为会把Integer自动拆箱为int再去比。

Integer和int什么时候用

转载自面试题:Integer和int的区别?在什么时候用Integer和什么时候用int_绝地反击T的博客-CSDN博客_什么时候用integer什么时候用int
/*
 * int是java提供的8种原始数据类型之一。Java为每个原始类型提供了封装类,Integer是java为int提供的封装类。int的默认值为0,
 * 而Integer的默认值为null
 * ,即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况,例如,要想表达出没有参加考试和考试成绩为0的区别
 * ,则只能使用Integer
 * 。在JSP开发中,Integer的默认为null,所以用el表达式在文本框中显示时,值为空白字符串,而int默认的默认值为0,所以用el表达式在文本框中显示时
 * ,结果为0,所以,int不适合作为web层的表单数据的类型。
 * 在Hibernate中,如果将OID定义为Integer类型,那么Hibernate就可以根据其值是否为null而判断一个对象是否是临时的
 * ,如果将OID定义为了int类型,还需要在hbm映射文件中设置其unsaved-value属性为0。
 * 另外,Integer提供了多个与整数相关的操作方法,例如,将一个字符串转换成整数,Integer中还定义了表示整数的最大值和最小值的常量。
 */

还需参考:Java-int和Integer的区别_T-bright的博客-CSDN博客_int和integer的区别

介绍了valueOf等

package java基础题目;
 
/**
 * 问题:要想表达出没有参加考试和考试成绩为0的区别?我们应该用Integer表示还是用int表示?
 */
public class A2015年6月4日_Integer和int {
	private static int score;
	private static Integer score2;
//	private static boolean ss;
	public static void main(String[] args) {
 
		System.out.println("int类型的默认值score2:" + score);// 0
 
		System.out.println("Integer类型的默认值score:" + score2);// null
 
		/*
		 * if(score==null){//报错因为score是int类型的不能和null比较
		 * 
		 * }
		 */
//		if(ss==true)
//		score2 = 0;
		if (score2 == null) {
			System.out.println("没有参加考试!!!");
		} else if (score2 == 0) {
			System.out.println("考试成绩为0分!!!");
		} else {
			System.out.println("考试成绩为" + score2);
		}
		
		integer();
	}
 
	public static void integer() {
		String string = "12345";
		Integer i = Integer.parseInt(string);// 把字符串解析为Integer类型
		Integer max = Integer.MAX_VALUE;
		Integer min = Integer.MIN_VALUE;
		System.out.println("Integer.parseInt(string)=" + i);
		System.out.println("integer的最大值:"+max+",最小值:"+min);
	}
}
 

总之:

1.将Int值赋给Integer变量。

Integer对象除了可以通过new来创建,也可以直接将Int值赋给Integer变量,这是因为系统会自动将这个Int值封装成一个Integer对象。比如:Integer a = 100;实际上的操作是:Integer a = Integer.valueof(100);

这里有一个需要注意的地方:在上面Integer的valueof()方法里面,当Int值范围在-128—127之间时,会通过一个IntegerCache缓存来创建Integer对象;当Int值不在该范围时,直接调用new Integer()来创建对象。因此会产生以下情况:

(1)Integer a = 100;Integer b = 100;a == b为True。因为这两个Integer变量引用的是缓存中的同一个Integer对象。

(2)Integer a = 200; Integer b = 200;a == b为False。这似乎因为这两个Integer变量引用的是通过new创建的两个不同对象。

2.三种变量的相互比较

(1)不管是new创建的Integer对象,还是通过直接赋值Int值创建的Integer对象,它们与Int类型变量通过“==”进行比较时都会自动拆封装变成Int类型,所以Integer对象和Int变量比较的是内容大小。

例如:int a = 100;Integer b = 100;Integer c = new Integer(100);a == b == c为True。

(2)new创建的Integer对象和直接赋Int值创建的Integer对象相互比较

这两种Integer对象通过“==”比较的都是内存地址。

(3)赋Int值创建的Integer对象相互比较

当Int值在-128—127之间时,两个Integer变量引用的是IntegerCache中的同一个对象,比较的内存地址相同。

当Int值不在以上范围时,两个Integer对象都是通过new创建的,比较的内存地址不同
 

二.包装类型在基本类型在内存中的存储

  1. 首先,通过main()方法进栈。
  2. 然后再栈中定义一个对象s1,去堆中开辟一个内存空间,将内存空间的引用赋值给s1,“hello”是常量,然后去字符串常量池 查看是否有hello字符串对象,没有的话分配一个空间存放hello,并且将其空间地址存入堆中new出来的空间中。
  3. 在栈中定义一个对象s2,然后去字符串常量池中查看是否有”hello”字符串对象,有,直接把”hello”的地址赋值给s2.
  4. 即s1中存的是堆中分配的空间,堆中分配的空间中存的是字符串常量池中分配空间存放”hello”的空间的地址值。而s2中之间存的是字符串常量池中分配空间存放”hello”的空间的地址值。
  5. 由于s1与s2中存放的地址不同,所以输出false。因为,类String重写了equals()方法,它比较的是引用类型的 的值是否相等,所以输出true。即结果为false、true。

总结就是: String i=new String (); 在堆中创建一个地址,去常量池中看是否有这个常量,没有的话就在常量池中创建,堆中的地址指向这个常量池中的常量,这时候可会创建两个变量,一个在堆中,一个在常量池中,若常量池中存在则只会创建一个变量。而String  i;直接考虑常量池中是否有,最多会创建一个变量。

java通过newstring创建对象回去常量池取吗_面试官:Integer a1 = 40;Integer a2 = 40;a1 == a2吗?..._weixin_39688875的博客-CSDN博客

图是错的,JDK7之后 常量池在堆中

包装类型的常量池: 他们的常量池和String不同,他们都是在-128-127之间使用常量池,而String也不是包装类,它new String 有可能创建两个对象,而包装类型new Integer/short() 等都是直接在堆中创建新空间,他们对应的-128-127之间初始化时就被放在常量池中。String跟包装类无关

Java - 包装类 常量池 - CoderJerry - 博客园

三.包装类型的引用传递问题:

    Integer a=new Integer(130);
    set(a);
    System.out.println(a);
}
public static void set(Integer b)
{
    b=888;
}

输出: 130

这样的原因是:

 b=888; 888>127,所以 b=888 就是 b=new Integer(888);b的地址改变 不再和a指向的地址一样了。

所有的包装类型都是这样,当作形参传进去不影响实参的值。

但是放在引用类型的对象中值是可以改变的:  猜测对象中存放的是自己成员变量的地址,成员变量的值改变时,直接改变了地址

  public static void main(String[] args) {
     User user=new User(1.0,"ZYZ",456);
       System.out.println(user);
        f(user);

        System.out.println(user);
        Integer a=new Integer(130);
        set(a);
        System.out.println(a);
    }
    public static void set(Integer b)
    {
        b=888;
    }
    public  static  void  f(User user)
    {
        user.tel=000; //Integer
        user.age=213; //double
        user.name="ppp"; //String
//        user.setName(";qaz");
    }

输出结果:

User{age=1.0, name='ZYZ', tel=456}
User{age=213.0, name='ppp', tel=0}

130

四.Integer类:

构造方法得到Integer对象的方法过时了 

1>下面方法用来得到Integer对象

2>int和String相互转换

3>自动装箱和拆箱

自动装箱里面自动包含了valueOf的操作 自动拆箱里面包含了intValue的方法

四.包装类型的线程安全性:

        Integer和String一样是线程安全的,因为其中的value都加了final,当对Intger a;声明的变量赋值时和String一样,这个a指向的地址变了,存储原来数的value是没变化的。

     目前的JVM(java虚拟机)都是将32位作为原子操作,并非64位。当线程把主存中的 long/double类型的值读到线程内存中时,可能是两次32位值的写操作,显而易见,如果几个线程同时操作,那么就可能会出现高低2个32位值出错的情况发生。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值