包装类
Lang包里的包装类
包装类:lang包里面的常用类,lang包不用导包,它是JVM内置包
包含基本类型的包装:
为了丰富基本类型的操作,提供八个包装类型,对于数值类型的都有一个父类,number,并且继承了comparable接口,用于定义比较规则
Byte Short Integer Long Double Character Boolean
封箱:
int num1=100;//基本类型的定义
Integer num2=100;
//装箱:基本类型转换成包装类的对象
// 包装类里面的valueOf方法
Integer num3=Integer.valueOf(100);
拆箱:
System.out.println(num1==num3);//true
//拆箱:包装类对象转变为基本类型数据
// 调用了num1==num3.intValue()
整数缓存池
int num1=100;//基本类型的定义
Integer num2=100;
Integer num3=Integer.valueOf(100);
//同一个对象,都在数组里面
Integer num4=new Integer(100);
Integer num5=new Integer(100);
System.out.println(num2==num3);//true
System.out.println(num3==num4);//false
System.out.println(num4==num5);//false
上面结果应该很容易想到,但是如果我再定义两个对象,并且值是128,那会咋样呢?
Integer num6=128;
Integer num7=128;
System.out.println(num7==num6);
输出是false,为什么呢?这时候我们可以看一下,valueOf的底层代码:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
可以看到它是调用了IntegerCache静态类的两个属性low和high来返回不同的结果,如果i在low和high之间返回数值,超出就返回一个新的对象,那我们可以点开看看这个类的取值范围:
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
可以看到,比较的范围是-128~127。当超出这个范围的时候,就会给创建一个新的对象,所以才会出现num7!=num6的结果。
对于Short,Long,Byte也都是用的整数缓存池,范围都是-128~127,字符型包装类Character则是0到127
包装类型的比较
Integer的比较
之前我们讲过,形式参数传递的时候数值类型的值不会被改变:
public static void main(String[] args) {
Integer num=20;
demo2(num);
System.out.println("main+"+num);
}
private static void demo2(int num) {
num=100;
System.out.println("demo2+"+num);
}
但是为什么呢?我们知道这里是隐藏valueof装箱的过程,把valueof写出来,再点开看一下:
public Integer(int value) {
this.value = value;
}
那这个value是什么呢?
private final int value;//维护integer数据
System.out.println(num3.equals(num4));
那我们点开equals的底层看一下:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
可以看到是先判断是否是整数包装类的对象,然后再进行返回,如果说对象是integer的一个对象,返回value
private final int value;//维护integer数据
点开可以看到value是由final修饰的一个常量,所以说对于字面量类型和所有的包装类型,值都是不可更改的
comparable
上次我们点开看到number类的都实现了comparable的接口,我们也可以用compare来比较数据
Integer.compare(num1,num2);
num1.compareTo(num2);
调用compare方法:
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
调用compareto方法:
public int compareTo(Integer anotherInteger) {
return compare(this.value, anotherInteger.value);
}
可以看到最终都是调用compare方法,并且返回0,-1,1三个值
字符串转int
将string类型转换成int型:
可以用integer类里面的valueof,但我们这里用parseint
String str="123";
Integer.parseInt(str);
Integer.parseInt(str,2);
其实对于valueof,其实他底层也是用的parseint来进行转换,因此我们来看一下parseint的底层代码看看他是怎么将字符类型转换成数据类型:
public static int parseInt(String s, int radix)
throws NumberFormatException
{
/*
* WARNING: This method may be invoked early during VM initialization
* before IntegerCache is initialized. Care must be taken to not use
* the valueOf method.
*/
if (s == null) {
throw new NumberFormatException("null");
}
if (radix < Character.MIN_RADIX) {//最小2进制
throw new NumberFormatException("radix " + radix +
" less than Character.MIN_RADIX");
}
if (radix > Character.MAX_RADIX) {//最大36进制
throw new NumberFormatException("radix " + radix +
" greater than Character.MAX_RADIX");
}
int result = 0;
boolean negative = false;//判断正负
int i = 0, len = s.length();
int limit = -Integer.MAX_VALUE;
int multmin;
int digit;
if (len > 0) {
char firstChar = s.charAt(0);
if (firstChar < '0') { // Possible leading "+" or "-"
if (firstChar == '-') {
negative = true;
limit = Integer.MIN_VALUE;
} else if (firstChar != '+')
throw NumberFormatException.forInputString(s);
if (len == 1) // Cannot have lone "+" or "-"
throw NumberFormatException.forInputString(s);
i++;
}
multmin = limit / radix;
while (i < len) {
// Accumulating negatively avoids surprises near MAX_VALUE
digit = Character.digit(s.charAt(i++),radix);
if (digit < 0) {
throw NumberFormatException.forInputString(s);
}
if (result < multmin) {
throw NumberFormatException.forInputString(s);
}
result *= radix;
if (result < limit + digit) {
throw NumberFormatException.forInputString(s);
}
result -= digit;
}
} else {
throw NumberFormatException.forInputString(s);
}
return negative ? result : -result;
}
写个方法来将string转换成十进制的数字:(肯定没有底层写的那么完美啦)
private static int toInt(String str,int radix) throws ParseException {
Objects.nonNull(str);
if(str=="")throw new NumberFormatException("str is null");
int firstChar=str.charAt(0);
boolean negative=false;
int i=0;
int len=str.length();
if(firstChar<'0'){
if(firstChar=='-')
negative = true;
else if(firstChar!='+')
throw new NumberFormatException("input number is illegal");
if(len==1)
throw new NumberFormatException("str has illegal character");
i++;
}
int num=0;
while(i<len){
int n=str.charAt(i++);
if(n<'0'||n>'9')
throw new NumberFormatException("middle num illegal");
num=num*radix+(n-48);
}
return negative?-num:num;
}
没有考虑数值类型的范围2-32~231 ,因此超出范围可能还是有问题……
character类
Character ch= Character.valueOf('a');//装箱
Character ch1= 'a';
Character character=new Character('a');
System.out.println(ch);//拆箱
System.out.println(ch1);
System.out.println(character);
Character.isDigit(ch);//判断是否是数字
Character.isLetter(ch1);//判断是否是字母
Character.digit(character,16);//将指定字符转换成指定进制的整型
Character.toUpperCase(ch);//转换成大写
Character.toLowerCase(ch1);//转换成小写
character也有整数缓存池,范围为0-127,超过范围同样会new一个新的character,因此超出范围之后的每个character地址值都不一样
在以后的类的属性上,禁止使用基本类型来修饰
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?