🎉🎉🎉点进来你就是我的人了
博主主页:🙈🙈🙈戳一戳,欢迎大佬指点!
人生格言:当你的才华撑不起你的野心的时候,你就应该静下心来学习!欢迎志同道合的朋友一起加油喔🦾🦾🦾
目标梦想:进大厂,立志成为一个牛掰的Java程序猿,虽然现在还是一个🐒嘿嘿
谢谢你这么帅气美丽还给我点赞!比个心
目录
一、包装类分类
二、使用包装类的原因
三、包装类的自动拆装箱机制
三、包装类中的缓存机制
(方法区) 整数型常量池
equals方法
四. Integer方法
五. Character方法
一、包装类分类
基本数据类型 | 包装类型 |
---|---|
byte | java.lang.Byte(父类Number) |
short | java.lang.Short(父类Number) |
int | java.lang.Integer(父类Number) |
long | java.lang.Long(父类Number) |
float | java.lang.Float(父类Number) |
double | java.lang.Double(父类Number) |
boolean | java.lang.Boolean(父类Object) |
char | java.lang.Character(父类Object) |
注意: 8种包装类属于 引用数据类型
二、使用包装类的原因
Java语言是面向对象的编程语言,而基本数据类型声明的变量并不是对象,为其提供包装类,增强了Java面向对象的性质。
而且,如果只有基本数据类型,使用时是很不方便的,比如,在集合类中,无法将int 、double等类型放进去的,因为集合的容器要求元素是Object类型。
此外,包装类还为基本类型添加了属性和方法,丰富了基本类型的操作。如当我们想知道int取值范围的最小值,我们需要通过运算,如下面所示,但是有了包装类,我们可以直接使用Integer.MAX_VALUE即可。
//求int的最大值
int max = 0;
int flag = 1;
for (int i=0; i<31; i++) {
max += flag;
flag = flag << 1;
}
System.out.println(max +" "+ Integer.MAX_VALUE); //2147483647 2147483647
为什么要保留基本数据类型?
因为Java种创建的对象都是存储在堆里的,使用的时候需要通过栈中的引用,所以常用的基本数据类型,不需要使用new在堆上创建,而是直接在栈内存中存储不创建对象,就会比较高效。
三、包装类的自动拆装箱机制
进行基本类型数据和包装类对象之间的互转时:
使用new关键字或者使用Integer类的valueOf()可以手动转换成包装类。这两个方式是有所区别的,我们下面会说到。
//创建包装类对象有两种方式:new关键字、valueOf()方法。
Integer num1 = new Integer(1); //基本数据类型转为包装类
Integer integer = Integer.valueOf(10);//基本数据类型转为包装类
int num2 = num1.intValue(); //包装类型转为基本数据类型
System.out.println(num1 +" "+ num2);
为了方便使用和性能优化,提供了自动装箱和拆装箱机制(不需要手动转换了)
- 自动装箱:基本数据类型自动转换成包装类。
- 自动拆箱:包装类自动转换成基本数据类型
//1、包装类中的自动装箱拆箱机制
Integer num1 = 1; //自动装箱
int num2 = num1; //自动拆箱
System.out.println(num1 +" "+ num2);
当使用jad工具对上面的代码进行反编译时,结果如下:
Integer integer = Integer.valueOf(1);
int i = integer.intValue();
System.out.println((new StringBuilder()).append(integer).append("\t").append(i).toString());
从反编译可以看出,底层也是调用ValueOf方法帮我们完成的自动装箱!
三、包装类中的缓存机制
前面说到创建包装类对象有两种方式:new关键字、valueOf()方法。我们来看一段代码感受一下它们的区别。
//包装类中的缓存机制
Integer num3 = 10;
Integer num4 = 10;
Integer num5 = new Integer(20);
Integer num6 = new Integer(20);
Integer num7 = 128;
Integer num8 = 128;
System.out.println((num3==num4) +" "+ num3.equals(num4));
System.out.println((num5==num6) +" "+ num5.equals(num6));
System.out.println((num7==num8) +" "+ num7.equals(num8));
运行结果为
为什么会得到这样的运行结果呢?
首先,我们查看Integer的valueOf()方法的源码
在Java中,Integer类使用了一个静态内部类(Static Nested Class),它在首次使用Integer类时被加载。该内部类预先创建了一个包含-128到127之间的所有Integer对象的缓存数组(cache),以优化性能。
当使用
Integer.valueOf()
方法创建Integer对象时,如果数值在-128到127范围内,方法会直接返回缓存数组中的对应对象,而不会新建对象。这种方法称为“享元模式”,可以节省内存,提高性能。当使用
new
关键字创建Integer对象或使用Integer.valueOf()
方法创建小于-128或大于127的值时,Java会创建一个新的Integer对象。注意,直接使用new
关键字创建对象时,无论数值是否在-128到127范围内,都会新建一个对象,而不是使用缓存中的对象。
(方法区) 整数型常量池
java中为了提高程序的执行效率,将 [-128 ~ 127]
之间所有的包装对象提前创建好, 放到了一个方法区的“整数型常量池
”当中了。
目的是:只要用这个区间的数据不需要再new了,直接从整数型常量池当中取出来。
//包装类中的缓存机制
Integer num3 = 10;
Integer num4 = 10;
Integer num5 = new Integer(20);
Integer num6 = new Integer(20);
Integer num7 = 128;
Integer num8 = 128;
System.out.println((num3==num4) +" "+ num3.equals(num4));
System.out.println((num5==num6) +" "+ num5.equals(num6));
System.out.println((num7==num8) +" "+ num7.equals(num8));
由于num3、num4都小于等于127,它们指向的是同一个缓存的Integer对象,所以用==进行比较的结果是true;num5、num6由于使用new关键字指向的是两个不同的新对象,结果为false;num7、num8虽然是采用自动装箱的方式,但执行valueOf()方法的时候,由于不满足条件i >= IntegerCache.low && i <= IntegerCache.high,而同样新建了两个不同的新对象,结果同样是false。
接着,我们再来看看源码中Integer的equals()方法的实现
equals方法
可见equals()方法比较的是Integer对象的值,而不是像==一样比较的是对象是否是同一个对象。所以,当需要比较两个Integer对象的值是否相等时,记住要用equals()方法。用==比较的话由于缓存机制的存在,可能产生一些让人困扰的结果。
此外,在8种包装类型中,有缓存区的有Character、Byte、Short、Integer、Long,而且它们的实现方式基本一样,都是-128到127的缓存范围。Boolean虽然没有缓存区,但是因为只有两个值true、false,所以Boolean在成员变量中就创建了两个相应的对象。没有缓存区的只有Float、Double,之所以没有原因很简单,即便是0到1这么小的范围,浮点数也有无数个,因此,在实际应用中,为这些值创建缓存区不具备现实意义和实用性。
缓存区的存在使得常用的包装类对象可以得到复用,这有利于提升性能。当我们需要创建新对象的时候再new一个,增加了灵活性。
四. Integer方法
方法名 | 作用 |
---|---|
static Integer decode(String nm) | 将String转成Integer |
static int compare(int x, int y) | 比较两个数是否相等;相等返回0;前大后小返回1;后大前小返回-1 |
static int signum(int i) | 符号函数;负数返回-1;正数返回1;0返回0 |
static String toBinaryString(int i) | 将i转成二进制 |
static String toHexString(int i) | 将i转成十六进制 |
static String toOctalString(int i ) | 将i转成八进制 |
常用方法 | |
static int parseInt(String s) | 字符串转int |
static Integer valueOf(String s) | 字符串转Integer |
String toString() | Integer转String |
boolean equals(Object obj) | 判断两个Integer是否相等 |
代码演示:
class IntegerTest{
public static void main(String[] args) {
Integer d = Integer.decode("123");
System.out.println(d);//自动拆箱 123
Integer a = 100;
Integer b = 100;
int res1 = Integer.compare(a, b);
System.out.println(res1);//0
res1 = Integer.compare(-a, b);
System.out.println(res1);//-1
res1 = Integer.compare(a, -b);
System.out.println(res1);//1
System.out.println(a.equals(b));//true
int i = Integer.parseInt("123");
System.out.println(i);//123
System.out.println(Integer.signum(-123));//-1
System.out.println(Integer.signum(123));//1
System.out.println(Integer.signum(0));//0
System.out.println(Integer.toBinaryString(10));//1010
System.out.println(Integer.toOctalString(10));//12
System.out.println(Integer.toHexString(10));//a
String s = Integer.toString(123);
System.out.println(s);//123
Integer int1 = Integer.valueOf("123");
System.out.println(int1);//123
}
}
五. Character方法
方法名 | 作用 |
---|---|
char charValue() | 将Character转成char |
int compareTo(Character anotherCharacter) | 判断两个Character是否相等;相等返回0;前大后小返回1;后大前小返回-1 |
常用方法 | |
boolean equals(Object obj) | 判断两个Character是否相等 |
String toString() | 将Character转成String |
static boolean isDigit(char ch) | 判断ch是不是数字 |
static boolean isLetter(char ch) | 判断ch是不是字母 |
static boolean isLetterOrDigit(char ch) | 判断ch是不是字母或数字 |
static boolean isLowerCase(char ch) | 判断ch是不是小写字母 |
static boolean isUpperCase(char ch) | 判断ch是不是大写字母 |
static boolean isSpaceChar(char ch) | 判断ch是不是空格 |
static Character valueOf(char c) | 将char转成Character |