java char的包装器是什么,Java类型包装器有什么作用
这篇文章给大家聊聊关于java char的包装器是什么,以及Java类型包装器有什么作用对应的知识点,希望对各位有所帮助,不要忘了收藏本站哦。
java 什么是拆箱和装箱,拆箱和装箱 嘛用啊
详解Java的自动装箱与拆箱(Autoboxing and unboxing)
一、什么是自动装箱拆箱
很简单,下面两句代码就可以看到装箱和拆箱过程
//自动装箱
Integertotal=99;
//自定拆箱
inttotalprim=total;
简单一点说,装箱就是自动将基本数据类型转换为包装器类型;拆箱就是自动将包装器类型转换为基本数据类型。
下面我们来看看需要装箱拆箱的类型有哪些:
这个过程是自动执行的,那么我们需要看看它的执行过程:
publicclassMain{
publicstaticvoidmain(String[]args){
//自动装箱
Integertotal=99;
//自定拆箱
inttotalprim=total;
}
}
反编译class文件之后得到如下内容:
javap-cStringTest
Integer total= 99;
执行上面那句代码的时候,系统为我们执行了:
Integer total= Integer.valueOf(99);
int totalprim= total;
执行上面那句代码的时候,系统为我们执行了:
int totalprim= total.intValue();
我们现在就以Integer为例,来分析一下它的源码:
1、首先来看看Integer.valueOf函数
publicstaticIntegervalueOf(inti){
returni>=128||i<-128?newInteger(i):SMALL_VALUES[i+128];
}
它会首先判断i的大小:如果i小于-128或者大于等于128,就创建一个Integer对象,否则执行SMALL_VALUES[i+ 128]。
首先我们来看看Integer的构造函数:
privatefinalintvalue;
publicInteger(intvalue){
this.value=value;
}
publicInteger(Stringstring)throwsNumberFormatException{
this(parseInt(string));
}
它里面定义了一个value变量,创建一个Integer对象,就会给这个变量初始化。第二个传入的是一个String变量,它会先把它转换成一个int值,然后进行初始化。
下面看看SMALL_VALUES[i+ 128]是什么东西:
privatestaticfinalInteger[]SMALL_VALUES=newInteger[256];
它是一个静态的Integer数组对象,也就是说最终valueOf返回的都是一个Integer对象。
所以我们这里可以总结一点:装箱的过程会创建对应的对象,这个会消耗内存,所以装箱的过程会增加内存的消耗,影响性能。
2、接着看看intValue函数
@Override
publicintintValue(){
returnvalue;
}
这个很简单,直接返回value值即可。
二、相关问题
上面我们看到在Integer的构造函数中,它分两种情况:
1、i>= 128|| i<-128=====> new Integer(i)
2、i< 128&& i>=-128=====> SMALL_VALUES[i+ 128]
privatestaticfinalInteger[]SMALL_VALUES=newInteger[256];
SMALL_VALUES本来已经被创建好,也就是说在i>= 128|| i<-128是会创建不同的对象,在i< 128&& i>=-128会根据i的值返回已经创建好的指定的对象。
说这些可能还不是很明白,下面我们来举个例子吧:
publicclassMain{publicstaticvoidmain(String[]args){
Integeri1=100;
Integeri2=100;
Integeri3=200;
Integeri4=200;
System.out.println(i1==i2);//true
System.out.println(i3==i4);//false
}
}
代码的后面,我们可以看到它们的执行结果是不一样的,为什么,在看看我们上面的说明。
1、i1和i2会进行自动装箱,执行了valueOf函数,它们的值在(-128,128]这个范围内,它们会拿到SMALL_VALUES数组里面的同一个对象SMALL_VALUES[228],它们引用到了同一个Integer对象,所以它们肯定是相等的。
2、i3和i4也会进行自动装箱,执行了valueOf函数,它们的值大于128,所以会执行new Integer(200),也就是说它们会分别创建两个不同的对象,所以它们肯定不等。
下面我们来看看另外一个例子:
publicclassMain{publicstaticvoidmain(String[]args){
Doublei1=100.0;
Doublei2=100.0;
Doublei3=200.0;
Doublei4=200.0;
System.out.println(i1==i2);//false
System.out.println(i3==i4);//false
}
}
看看上面的执行结果,跟Integer不一样,这样也不必奇怪,因为它们的valueOf实现不一样,结果肯定不一样,那为什么它们不统一一下呢?
这个很好理解,因为对于Integer,在(-128,128]之间只有固定的256个值,所以为了避免多次创建对象,我们事先就创建好一个大小为256的Integer数组SMALL_VALUES,所以如果值在这个范围内,就可以直接返回我们事先创建好的对象就可以了。
但是对于Double类型来说,我们就不能这样做,因为它在这个范围内个数是无限的。
总结一句就是:在某个范围内的整型数值的个数是有限的,而浮点数却不是。
所以在Double里面的做法很直接,就是直接创建一个对象,所以每次创建的对象都不一样。
publicstaticDoublevalueOf(doubled){
returnnewDouble(d);
}
下面我们进行一个归类:
Integer派别:Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。
Double派别:Double、Float的valueOf方法的实现是类似的。每次都返回不同的对象。
下面对Integer派别进行一个总结,如下图:
下面我们来看看另外一种情况:
publicclassMain{publicstaticvoidmain(String[]args){
Booleani1=false;
Booleani2=false;
Booleani3=true;
Booleani4=true;
System.out.println(i1==i2);//true
System.out.println(i3==i4);//true
}
}
可以看到返回的都是true,也就是它们执行valueOf返回的都是相同的对象。
publicstaticBooleanvalueOf(booleanb){
returnb?Boolean.TRUE:Boolean.FALSE;
}
可以看到它并没有创建对象,因为在内部已经提前创建好两个对象,因为它只有两种情况,这样也是为了避免重复创建太多的对象。
publicstaticfinalBooleanTRUE=newBoolean(true);
publicstaticfinalBooleanFALSE=newBoolean(false);
上面把几种情况都介绍到了,下面来进一步讨论其他情况。
Integernum1=400;
intnum2=400;
System.out.println(num1==num2);//true
说明num1== num2进行了拆箱操作
Integernum1=100;
intnum2=100;
System.out.println(num1.equals(num2));//true
我们先来看看equals源码:
@Override
publicbooleanequals(Objecto){
return(oinstanceofInteger)&&(((Integer)o).value==value);
}
我们指定equal比较的是内容本身,并且我们也可以看到equal的参数是一个Object对象,我们传入的是一个int类型,所以首先会进行装箱,然后比较,之所以返回true,是由于它比较的是对象里面的value值。
Integernum1=100;
intnum2=100;
Longnum3=200l;
System.out.println(num1+num2);//200
System.out.println(num3==(num1+num2));//true
System.out.println(num3.equals(num1+num2));//false
1、当一个基础数据类型与封装类进行==、+、-、*、/运算时,会将封装类进行拆箱,对基础数据类型进行运算。
2、对于num3.equals(num1+ num2)为false的原因很简单,我们还是根据代码实现来说明:
@Override
publicbooleanequals(Objecto){
return(oinstanceofLong)&&(((Long)o).value==value);
}
它必须满足两个条件才为true:
1、类型相同
2、内容相同
上面返回false的原因就是类型不同。
Integernum1=100;
Ingegernum2=200;
Longnum3=300l;
System.out.println(num3==(num1+num2));//true
我们来反编译一些这个class文件:javap-c StringTest
可以看到运算的时候首先对num3进行拆箱(执行num3的longValue得到基础类型为long的值300),然后对num1和mum2进行拆箱(分别执行了num1和num2的intValue得到基础类型为int的值100和200),然后进行相关的基础运算。
我们来对基础类型进行一个测试:
intnum1=100;
intnum2=200;
longmum3=300;
System.out.println(num3==(num1+num2));//true
上面就说明了为什么最上面会返回true.
所以,当“==”运算符的两个操作数都是包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。
通过上面的分析我们需要知道两点:
1、什么时候会引发装箱和拆箱
2、装箱操作会创建对象,频繁的装箱操作会消耗许多内存,影响性能,所以可以避免装箱的时候应该尽量避免。
我有一个微信公众号,经常会分享一些Java技术相关的干货文章,还有一些学习资源。
如果你需要的话,可以用微信搜索“Java团长”或者“javatuanzhang”关注。
基本数据类型和包装器类型有什么关联
基本数据类型,例如 int、float、double、boolean、char
等,是不具备对象的特性的,比如基本类型不能调用方法、功能简单。。。,为了让基本数据类型也具备对象的特性, Java
为每个基本数据类型都提供了一个包装类,这样我们就可以像操作对象那样来操作基本数据类型。
基本类型和包装类之间的对应关系:
包装类主要提供了两大类方法:
1.将本类型和其他基本类型进行转换的方法
2.将字符串和本类型及包装类互相转换的方法
Java类型包装器有什么作用
Java类型包装器,是在基本类型的基础上,对于基本类型进行对象化,使其能够相互转换,扩展如下::
1.基本数据类型之间的相互转换不是都可以制动转换的,而你强制转换又会出问题,比如String类型的转换为int类型的,那么jdk为了方便用户就提供了相应的包装类。
例子:
publicclassInteger{
privateinti;
publicInteger(inta){
i=a;
}
publicstaticintparseToInt(){
returni;
}
publicstaticIntegervalueOf(Stringstr){
//封装一系列的逻辑最终将str转换成int类型的IntegerStr
returnnewInteger(IntegerStr);
}
}
2.有时候一个函数需要传递一个Object的变量,而想传递int类型的进去显然不行需要用到了包装类传递object类型。
public void test(Object obj){
}
test(new Integer(5));
综上所述,包装类有三个用法一个实现基本类型之间的转换二是便于函数传值三就是在一些地方要用到Object的时候方便将基本数据类型装换
java中char类型大小写转换问题
public class CharTest{
public static void main(String[] args){
Scanner in= new Scanner(System.in);
System.out.print("请输入字母:");
char c= in.next().charAt(0);
if(c>='A'&& c<='Z'){
c+= 32;
System.out.println("这里的大写"+(char)(c- 32)+"被转换成了"+ c);
System.out.println("这里的大写"+(c- 32)+"被转换成了"+ c);
} else if(c>='a'&& c<='z'){
c-= 32;
System.out.println("这里的小写"+(char)(c+ 32)+"被转换成了"+ c);
System.out.println("这里的小写"+(c+ 32)+"被转换成了"+ c);
}
/*
*首先,我加了两句,输出,楼主先运行看一下。然后我再解释。
*这里涉及到三个知识第
* 1.字母有其对应的A码,
* 2.大小写相差32
* 3.自动数据类型转化。
*
*上面例子如果不好理解的话,我们换一个,好理解的
* int a=2;
* double b=2.2;
* a+b最后的结果会是什么类型呢???????
*显示会是double,为什么这样呢?我们说数据的处理,肯定要在同一个类型的时候才能处理,
*所有不同数据类型处理时要通过自动或者强制转化,否则会报错。
*这里是自动转化,自动转化有两个要求:
* 1.两种数据类型兼容
* 2.小的向大的转化。
*所以这里int转为double,最终结果是double
*
*
*好了,现在来分析一下
*(char)(c-32)和(c-32)的区别
*其实也就是c-32。
* 1.这里的首先char和int通过A码可以转换,所以兼容
* 2.int比char大。
*所以计算的时候c先转为相应的A码,也就是整数,然后进行计算。计算后的结果必然是整数
*如果你此时想得到char。就必须通过强制类型转化。所以要(char)
**/
}
}
总结一下:通过转化后,因为参与了+或者-32,所以最终的结果是以整数的形式出现的。
当然,如果你这样写的话,就另当别论了
再举例说明清楚
如果是这样的话
c+=32;
System.out.print(c);
输出的是字母
对比
System.out.pirnlnt(c+32);
输出的是数字??
为什么呢
因为c=c+32,c本身的数据类型是char后面的结果计算后的时候会自动根据对应的A码转为对应的char
所以需要区别的是:
如果是赋值运算。运算后的右边的结果,会自动转型为左边的类型,如果不能转型会报异常。
如果是通过其他运算(比如四则运算),它会先把所有数据类型先转化为较大的数据类型,最终得到的结果也是较大的数据类型。
最后举例
int a=32;
char b='A';
char c='A';
b+=32;//赋值运算
//或者b='A'+32;
//如果是b=b+32;就会报错。因为后面进行了加法运算,结果需要用int来接收
//int d=b+32;这个就对了
System.out.println(b);//a
System.out.println(c+32);//97,其他运算
java char的包装器是什么和Java类型包装器有什么作用的问题分享结束啦,以上的文章解决了您的问题吗?欢迎您下次再来哦!