5.1 包装类 一、自动装箱和自动拆箱——基本数据类型和对象之间的转换 二、包装类实现基本类型变量和字符串之间的转换 三、包装类的比较

回顾Java数据类型:

graph TD Java数据类型-->基本数据类型 Java数据类型-->引用数据类型 基本数据类型-->整数类型 整数类型-->byte:1字节 整数类型-->short:2字节 整数类型-->int:4字节 整数类型-->long:4字节 基本数据类型-->浮点类型 浮点类型-->float:4字节 浮点类型-->double:8字节 基本数据类型-->字符类型 字符类型-->char:2个字节 基本数据类型-->布尔类型 布尔类型-->boolean 引用数据类型-->类 引用数据类型-->接口 引用数据类型-->数组类型 引用数据类型-->特殊值null

▲基本数据类型不具备“对象”的特性:没有成员变量和方法可以调用。基本数据类型存在一些制约,比如所有引用类型都继承Object类,都可以当成Object类型变量来使用。但基本数据类型变量就不可以,如果有个方法需要Object类型的参数,但实际上却是2,3等整型类型的数值。
Java为8种基本数据类型分别定义了相对应的引用类型,并称之为Java基本数据类型的包装类。

基本数据类型 引用类型
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

*补充:KDK1.5之前基本类型和包装类的转换(这种用法已过时):
5.1 包装类
一、自动装箱和自动拆箱——基本数据类型和对象之间的转换
二、包装类实现基本类型变量和字符串之间的转换
三、包装类的比较

自动装箱:把一个基本类型的变量直接赋给对应的包装类变量,或者赋给Object变量(Object类是所有类的的父类)。
自动拆箱:允许直接把一个包装类对象直接赋给基本类型变量。
5.1 包装类
一、自动装箱和自动拆箱——基本数据类型和对象之间的转换
二、包装类实现基本类型变量和字符串之间的转换
三、包装类的比较

class AutoBoxingUnboxing 
{
	public static void main(String[] args) 
	{
		//自动装箱实例
		//把一个基本类型的变量直接赋给Integer对象
		Integer intobj=5;
		System.out.println(intobj instanceof Object);

		//把一个浮点型变量直接赋给Float型对象
		Float flobj=1.2f;
		System.out.println(intobj*flobj);
	

		//自动拆箱
		float a=flobj;
		System.out.println(a);
	}
}

值得注意的是自动装箱和自动拆箱必须注意类型匹配,Integer只能拆箱成int类型的变量;int类型的变量只能自动装箱成Integer对象。

二、包装类实现基本类型变量和字符串之间的转换

字符串转换为基本类型的两种方式:
1、利用包装类提供的parseXxx(String str)静态方法(除Character之外的包装类都提供此类方法)
2、利用包装类提供的valueOf()静态方法。

基本类型转换字符串:
1、将基本类型变量之间和""进行连接运算,系统会自动把基本类型变量转换为字符串
2、利用String类提供的valueOf(基本类型)静态方法

5.1 包装类
一、自动装箱和自动拆箱——基本数据类型和对象之间的转换
二、包装类实现基本类型变量和字符串之间的转换
三、包装类的比较

class StringNum 
{
	//获取变量的类型
	public static String getType(Object test)
	{
		return test.getClass().toString();
	}

	public static void main(String[] args) 
	{

	/*
	 *字符串转换为基本类型
	 *方法一:包装类.parseXxx(xxxStr)
	 *方法二:包装类.valueOf(xxxStr)
	 */

		 //字符串-----→整型变量
		String intStr="123";
		System.out.println(getType(intStr));

		int it1=Integer.parseInt(intStr);//将Integer包装类自动拆箱为int类型
		int it2=Integer.valueOf(intStr);
		System.out.println(getType(it1)+"
"+getType(it2));
		
		//字符串-----→boolean类型变量
		String boolStr="true";
		boolean bool1=Boolean.parseBoolean(boolStr);
		boolean bool2=Boolean.valueOf(boolStr);
		System.out.println(bool1);
		System.out.println(bool2);


	/*
	 *基本类型转换为字符串
	 *方法:String.valueOf()
	 *直接与""进行连接运算
	 */		

	 	//浮点数转换----→字符串
		var floatNum=4.56;
		var floatStr=floatNum+"";
		System.out.println(getType(floatStr));

		//boolean类型----→字符串
		var boolStr1=String.valueOf("false");
		System.out.println(getType(boolStr1));

	}
}
---------- 运行Java捕获输出窗 ----------
class java.lang.String
class java.lang.Integer
class java.lang.Integer
true
true
class java.lang.String
class java.lang.String

输出完成 (耗时 0 秒) - 正常终止

三、包装类的比较

3.1 虽然包装类是引用类型数据类型,但包装类的实例可以与数值类型来进行比较,这种直接比较是直接取出包装类里的数值来进行比较的。

class 包装类取值 
{
	public static void main(String[] args) 
	{
		Integer a=6;
		System.out.println(a>5);//输出为True
	}
}

3.2 两个包装类的实例比较的情况比较复杂,因为只有包装类的实例是引用类型,只有两个包装类引用指向同一个对象时才会返回true。

Integer实例比较的异常情况:

class 包装类实例比较 
{
	public static void main(String[] args) 
	{
		Float f1=2.2f;
		Float f2=2.2f;
		System.out.println(f1==f2);

		Integer inta=2;
		Integer intb=2;
		System.out.println(inta==intb);

		Integer intc=128;
		Integer intd=128;
		System.out.println(intc==intd);
				
	}
}
---------- 运行Java捕获输出窗 ----------
false
true
false

输出完成 (耗时 0 秒) - 正常终止

为什么两个128装箱后就不相等了?这与Java的Integer类设计有关,查看java.lang.Integer类源代码:

//定义一个长256的Integer数组
static final Integer[] cache=new Integer[-(-128)+127+1];//-128个负数,127个正数,一个0
static{
//执行初始化,创建-128——+127的Integer实例,并放入cache数组中
for(int i=0;i<cache.length;i++)
    cache[i]=new Integer[i-128];
}

从上面可以看出,系统把-128——+127之间的整数自动装箱为Integer实例,并放入一个cache数组。因此只要是在此范围的Integer实例,永远都指向ache数组的同一个数组元素,所以他们总是相等;但把一个不在此范围的整数自动装箱为Integer实例时,系统总是先创建一个Integer实例。图示:
5.1 包装类
一、自动装箱和自动拆箱——基本数据类型和对象之间的转换
二、包装类实现基本类型变量和字符串之间的转换
三、包装类的比较

3.3包装类的功能

3.3.1 Java 7为所有包装类提供了一个静态的compare(xxx val1,xxx val2)方法

用于比较两个基本类型的大小。包括boolean类型值,两个boolean类型值比较时,true>false.

class StaticCompare 
{
	public static void main(String[] args) 
	{
		//整型类型比较
		Long num1=12L;
		Long num2=15L;
		System.out.println(Long.compare(num1,num2));//输出为-1
		//不仅可以进行包装类之间的比较,还可以用于基本整型的比较
		long num3=20L;
		long num4=18L;
		System.out.println(Long.compare(num3,num4));//输出为1

		//字符型数据比较,按编码大小进行比较
		Character cCh1='a';
		Character cCh2='b';
		System.out.println(Character.compare(cCh1,cCh2));//输出为-1

		//Boolean类型的比较
		Boolean bool1=true;
		Boolean bool2=false;
		System.out.println(Boolean.compare(bool1,bool2));//输出为-1
		//boolean类型的比较
		boolean bool3=true;
		boolean bool4=false;
		System.out.println(Boolean.compare(bool3,bool4));//输出为1

	}
}

3.3.2 Java 7为Character类增加了大量工具方法进行对一个字符进行判断。

简单介绍几个,详情参看API文档
(1)public static int charCount​(int codePoint)
描述:确定char表示 指定字符(或Unicode代码点) 所需的char数目。如果指定的字符等于或大于0x10000,则该方法返回2。否则,该方法返回1。
参数:codePoint -要测试的字符(或Unicode代码点)。
返回值:如果该字符是一个有效的字符或int codePoint<0x10000(char字符需要两个字节)返回值为1,否则为2。

class CharacterMed 
{
	public static void main(String[] args) 
	{
		System.out.println(Character.charCount('A'));//输出为1
		System.out.println(Character.charCount('中'));//输出为1
		System.out.println(Character.charCount(0x1FFF));//输出为1
		System.out.println(Character.charCount(0x10000));//输出为2
	}
}

(2)static int codePointAt(char [] a,int index)
参数:
a- char数组
index- 要查看char数组中的值(Unicode编码值)的索引
返回值:
给定索引处的Unicode编码值

char[] chs={'a','b','c','汉'};
System.out.println(Character.codePointAt(chs,0));//输出97
System.out.println(Character.codePointAt(chs,3));//27721

(3)public boolean equals(Object obj)
将此对象与指定对象进行比较。当且仅当参数不是null并且是一个Character表示与该对象相同值的对象,返回值为true。
参数:
obj -要比较的对象。
返回值:
true如果对象相同; false除此以外。

Character ch1='D';
Character ch2='D';
System.out.println(ch1.equals(ch2));//true

3.3.3 Java8为整数包装类增加了支持支持无符号运算的方法。

Java 8 为Integer、Long增加了如下方法:
(1)static String toUnsignedString(int/long i);
该方法将指定int或long型转换为无符号整数对应的字符串。
(2)static String toUnsignedString(int/long i,int radix);
该方法将指定int或long型转换为指定进制的无符号整数对应的字符串。

System.out.println(Integer.toUnsignedString(-1));//2^32-1=4294967295
System.out.println(Integer.toUnsignedString(-1,2));//11111111111111111111111111111111

(3)static xxx parseUnsignedXxx(String s);
将指定字符串解析成无符号整数。当调用Interger时,xxx为int,当调用Long时,xxx为long。
(4)static xxx parseUnsignedXxx(String s,int radix);
将指定字符串按指定进制解析成的无符号整数。当调用Interger时,xxx为int,当调用Long时,xxx为long。

System.out.println(Integer.parseUnsignedInt("122222"));//122222
System.out.println(Integer.parseUnsignedInt("1111111",2));//127

(5)static int compareUnsigned(xxx x,xxx y)
将x,y两个整数转换为无符号整数后比较大小。当调用Interger时,xxx为int,当调用Long时,xxx为long。

int a=2;
int b=-3;
System.out.println(Integer.compareUnsigned(a,b));//-1

(5)static xxx divideUnsigned(xxx x,xxx y)
将x,y两个整数转换为无符号整数后计算它们的商。当调用Interger时,xxx为int,当调用Long时,xxx为long。

int num1=-100;
int num2=25;
System.out.println(Integer.divideUnsigned(num1,num2));//171798687

(6)static xxx remainderUnsigned(xxx x,xxx y)
将x,y两个整数转换为无符号整数后计算它们的余数。当调用Interger时,xxx为int,当调用Long时,xxx为long。

3.3.4 Java8还为Byte、Short增加了toUnsignedInt(xxx x)、toUnsignedLong(xxx x)

这两个方法用于将byte或short类型的变量或值转换为无符号的int或long值。

byte bitnum=-1;
System.out.println(Byte.toUnsignedInt(bitnum));//2^8-1=255