包装类

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地址值都不一样

在以后的类的属性上,禁止使用基本类型来修饰

posted @ 2022-10-31 10:26  Liku007  阅读(29)  评论(0编辑  收藏  举报