【Java专题】容易被忽视的包装类

什么是包装类?

包装类:就是将8种基本数据类型,装换成对应的8种包装引用类型。

 

为什么需要将8种基本数据类型转换为8中包装类型呢?

原因在于8种基本的数据类型不够用

实例代码举例:

/**

 * @author Jason

 * @create 2020-04-30 16:10

 */

public class StringTest07 {

  public static void main(String[] args) {

    MyInt myInt = new MyInt(100);

    doSome(myInt);

  }


  public static void doSome(Object object){

    System.out.println(object.toString());

  }

}

 


/**

 * @author Jason

 * @create 2020-04-30 16:11

 */

public class MyInt {

  int value;

  public MyInt() {

  }

 

  public MyInt(int value) {

    this.value = value;

  }

 

  @Override

  public String toString() {

    return String.valueOf(value);

  }

}

通过上面的实例,会发现,调用doSome方法,该方法需要的是Object类型的参数,但是如果我们此时传入的是基本类型的数字肯定是无法接收的,那我们该怎么办?其实就是用包装类的方法解决:用构造方法的形式将基本类型的数据包装成包装类型的数据。

 

8种基本数据类型对应的包装类型名是什么?

 基本数据类型 

   包装类型

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中包装类型中有6种都是数字类型的包装类,他们的父类都是Number,那么Number中的公共方法都有哪些呢?

  • byte byteValue() 以 byte 形式返回指定的数值。
  • abstract  double doubleValue()以 double 形式返回指定的数值。
  • abstract  float floatValue()以 float 形式返回指定的数值。
  • abstract  int intValue()以 int 形式返回指定的数值。
  •  abstract  long longValue()以 long 形式返回指定的数值。
  •  short shortValue()以 short 形式返回指定的数值。

这些方法其实所有的数字包装类的子类都有,这些方法是负责拆箱的。

 

具体的实例代码:

/**

 * @author Jason

 * @create 2020-04-30 16:29

 * 拆装箱

 */

public class StringTest08 {

  public static void main(String[] args) {

    //装箱

    Integer i = new Integer(123);

   

    //拆箱

    float v = i.floatValue();

    System.out.println(v);

 

    //拆箱

    int i1 = i.intValue();

    System.out.println(i1);

  }
}

 

8种包装类的构造方法有哪些呢?(以Integer为例)

  • Integer(int)
  • Integer(String)
/**

 * @author Jason

 * @create 2020-04-30 16:43

 * Integer包装类的构造方法

 */

public class StringTest09 {

  public static void main(String[] args) {

    Integer a = new Integer(100);

    System.out.println(a);//100 这里当然重写了toString方法

   

    Integer b = new Integer("111");

    System.out.println(b);//111

  }

}

 

什么是自动拆箱,自动装箱?

自动装箱:基本数据类型自动转换成包装类。

自动拆箱:包装类自动转换成基本数据类型。

 

有什么好处呢?

方便编码

 

具体实例代码:

/**

 * @author Jason

 * @create 2020-04-30 17:14

 * 自动拆箱,自动装箱

 */

public class StringTest0 {

  public static void main(String[] args) {

    //自动装箱

    Integer a = 100;

    System.out.println(a);

 

    //自动拆箱

    int b = a;

    System.out.println(b);

 

    Integer c = 10;

    System.out.println(c+1);

 

    Integer d = 222;

    Integer e = 222;

    System.out.println(d == e);//false

  }

}

 

分析:

Integer c = 10;

System.out.println(c+1);

这里的c是一个引用,一个变量,保存的是一个对象的内存地址,在进行c+1的时候为什么没有报错呢?

原因在于:加号两边要求的是基本数据类型的数字,c是包装类,不属于基本的数据类型,这里会进行自动拆箱,将c装换成基本的数据类型

 

Integer d = 222;// Integer d = new Integer(222); d是个引用,保存内存地址指向对象

Integer e = 222;// Integer e = new Integer(222); e是个引用,保存内存地址指向对象

System.out.println(d == e);//false

这个为什么没有自动拆箱呢?

  • == 比较的是对象的内存地址,d和e两个引用中保存的对象内存地址不同。
  • == 这个运算符不会触发自动拆箱机制。(只有+ - * /等运算的时候才会。)

 

在看一个实例:

/**

 * @author Jason

 * @create 2020-05-01 19:42

 * 自动拆箱问题

 */

public class StringTest {

  public static void main(String[] args) {

    Integer x = 100;

    Integer y = 100;

    System.out.println(x == y); //true

 

    Integer a = 128;

    Integer b = 128;

    System.out.println(a == b); //false

  }

}

通过这个实例可以非常清楚的发现一个问题,那就是不是“==”号两边的所有数据都不能自动拆箱。

那到底什么样的数据能自动拆箱,什么样的数据不能自动拆箱呢?

其实通过源码很容易发现在加载的时候有-128~127已经被加载到了缓存当中,当我们用到这些数字的时候JVM就自动的帮助我们拆箱了,这样一来方便了我们的开发。但是只要超过这个范围的数字JVM就不会帮助我们拆箱。

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;

        }

}

 

8种包装类中都有哪些常用方法?(以Integer举例)

  • parseInt
  • valueOf
  • toBinaryString
  • toHexString

 

下面先来看实例代码:

/**

 * @author Jason

 * @create 2020-05-01 20:03

 * 常用方法

 */

public class StringTest13 {

  public static void main(String[] args) {

    Integer a = new Integer("111");

    System.out.println(a); //111

 

    /*Integer b = new Integer("c");

    System.out.println(b); //NumberFormatException异常*/

 

    //其实它的底层就是这个静态方法,将String类型的数字转换成int类型的

    /*public static int parseInt(String s) throws NumberFormatException {

      return parseInt(s,10);

    }*/

    int i = Integer.parseInt("222");

    System.out.println(i+111); //333

 

    double v = Double.parseDouble("3.14");

    System.out.println(v+2);  //5.140000000000001

 

    //他的底层是这个方法,将int类型的转化成Integer类型的

    /*public static Integer valueOf(int i) {

      if (i >= IntegerCache.low && i <= IntegerCache.high)

        return IntegerCache.cache[i + (-IntegerCache.low)];

      return new Integer(i);

    }*/

    Integer i1 = Integer.valueOf(128);

    System.out.println(i1); //128

 

    Integer i2 = Integer.valueOf("100");

    System.out.println(i2); //100

  }

}

通过上面的实例很容易的发现parseInt和valueOf有很多的类似之处,他们的区别在于:

先看他们的示例代码:

   

//valueOf和parseInt的区别

    Integer a1 = Integer.valueOf("100");

    Integer a2 = Integer.valueOf("100");

    System.out.println(a1 == a2); //true

 

    Integer a3 = Integer.valueOf("128");

    Integer a4 = Integer.valueOf("128");

    System.out.println(a3 == a4); //false

 

    System.out.println("+++++++++++++++++");

    int a5 = Integer.parseInt("100");

    int a6 = Integer.parseInt("100");

    System.out.println(a5 == a6); //true

 

    int a7 = Integer.parseInt("128");

    int a8 = Integer.parseInt("128");

    System.out.println(a7 == a8); //true

通过上面可以看到,他们的执行结果还是有很多的不一样的,调用vauleOf的时候如果超过127他在“==”判断时候出现false,但是在调用parseInt的时候就不会。这是为什么呢?

原因在于:valueOf在缓存中存有(-128~127),他只要在这个范围内“==”JVM就会自动的拆箱,但是超过了这个范围就不会了,而parseInt就没有这个功能,所有在使用这两个常用方法的时候需要注意。请见源码:

valueOf的源码:

   

 public static Integer valueOf(int i) {

      if (i >= IntegerCache.low && i <= IntegerCache.high)

        return IntegerCache.cache[i + (-IntegerCache.low)];

      return new Integer(i);

    }

 

parseInt的源码:

    public static int parseInt(String s) throws NumberFormatException {

      return parseInt(s,10);

    }

 

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技术蜗牛-阿春

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值