包装类型

Javabean的概念(了解)
Java语言的命名,最早是Oak(橡树),因为有品牌注册该商标,他们又另外取名字。在喝咖啡时,想到用“爪哇岛”的咖啡来源地作为新语言的名字,就是Java。
因此Java中就有很多名称和“豆bean”有关。
Java类,可以称为Javabean。
但是很多时候,在平时的文章或者聊天时(特别是中国环境下),我们把Javabean的范围又缩小了,不是代码所有Java类,
而是特指哪些存储对象的基本属性的类,例如:学生类、商品类、订单类。像这些类通过都是用来表示数据的,即和数据库中的表对应。

这种类,通常有这些要求:
(1)习惯放到bean包中,有时候bean包又称为vo,pojo,do等
(2)这种中一般都是public的
(3)属性都是私有化的
(4)有标准的get/set
(5)有无参构造
(6)有toString方法

包装类型
1、什么是包装类,为什么要用包装类?
(1)Java是面向对象的语言,在Java中设计的很多语法或API,都是针对“对象”(引用数据类型)来设计的,
比如:后面的<泛型>,集合容器,等都只针对对象,不支持基本数据类型。

(2)Java中又保留了C语言的8种基本数据类型和void,所以Java是不“纯”的面向对象语言。
因为8种基本数据类型和void,有相当的背景基础,比如:有丰富的运算符的支持,有很多C库底层兼容,
并且每一种基本数据类型都有固定的宽度....等特点,使得Java就直接保留了这些类型,不用重头开始设计了。

Java发明的时候,C语言已经很成熟了,而且使用非常广泛,所以Java就借鉴C语言的一些语法或类型等。
Java一开始被人戏称为“C++--”,在C的基础上加上一些东西(对象),去掉一些东西(指针)。

(3)而且Java程序中,大量的数据仍然需要用基本数据类型来表示的。为了兼容Java的面向对象语法和基本数据类型,
Java提供了一套API,我们称为包装类。即Java为每一种基本数据类型和void都定制了一个对应的引用数据类型。

基本数据类型      包装类(java.lang包)
byte            Byte
short           Short
int             Integer
long            Long
float           Float
double          Double
char            Character
boolean         Boolean
void            Void

总结来说:包装类是基本数据类型与面向对象语法之间的桥梁,是一个包装。

2、如何使用包装类?

JDK1.5之前,我们需要使用包装类来包装基本数据类型的数据,必须手动装箱。即手动new对象。
JDK1.5之后,我们需要使用包装类来包装基本数据类型的数据,支持自动装箱。即不用手动new对象。

包装类的对象,就和Java其他对象一样,就可以调用方法等。

3、有时候,需要把包装类的对象,转为基本数据类型的数据,这个过程称为“拆箱”。
例如:需要使用运算符进行计算时。
JDK1.5之前,必须手动拆箱。调用包装类对象的value()方法等,把数据拿出来。
JDK1.5之后,支持自动拆箱。

装箱:把基本数据类型->包装类对象
拆箱:把包装类对象->基本数据类型

public class TestWrapper {
    public static void main(String[] args) {
        int a = 1;//基本数据类型
        Integer objA = new Integer(a);//包装类对象,把基本数据类型的a包装为一个对象  手动装箱

        //Object obj1 = a;//JDK1.5之前是错误的,因为a是基本数据类型,是不能赋值给Object类型的变量的
        Object obj2 = objA;//可以的,因为objA是引用数据类型,可以赋值给给Object类型的变量的

        System.out.println("-----------------------------------");
        int b = 1;
        Integer objB = a;//包装类对象,把基本数据类型的a包装为一个对象  自动装箱
        Object obj3 = b;//JDK1.5之后是可以,因为b被自动装箱为Integer对象
        System.out.println(obj3.getClass());//class java.lang.Integer

        System.out.println("-----------------------------------");
        //JDK1.5之前
        Integer x = new Integer(1); //手动装箱
        Integer y = new Integer(2); //手动装箱
        System.out.println("求和:" + (x.intValue() + y.intValue())); //手动拆箱
        System.out.println("比较大小:" + (x.intValue() < y.intValue()));//手动拆箱

        System.out.println("-----------------------------------");
        //JDK1.5之后
        Integer m = 1;//自动装箱
        Integer n = 2;//自动装箱
        System.out.println("求和:" + (m + n)); //自动拆箱
        System.out.println("比较大小:" + (m < n));//自动拆箱
    }

4、包装类的其他用途
(1)实现基本数据类型与字符串之间的转换
A:把基本数据类型转为字符串很简单,直接拼接字符串就可以了
    int a = 1;
    String str = a + "";
B:把字符串转为基本数据类型,就需要用包装类来辅助
    String str = "123";
    int num = str;//错误的
    int num = (int)str;//错误的
    int num = Integer.parseInt(str); //可以

    应用场景,从命令行参数接收的数据,Web页面接收的数据等,无论是什么类型,都是按照字符串接收的。

字符串-->int  Integer.parseInt(字符串)
字符串-->double  Double.parseDouble(字符串)
字符串-->long  Long.parseLong(字符串)
字符串-->boolean  Boolean.parseBoolean(字符串)
字符串-->char      字符串.charAt(0)

(2)获取数据类型的最大最小值
包装类.MAX_VALUE
包装类.MIN_VALUE

(3)单字符转大小写
Character.toUpperCase(letter)转大写
Character.toLowerCase(letter)转小写

(4)比较两个基本数据的值,特别是double类型
因为double类型的数据是不精确的,所以使用>,<等比较可能会有误差,一般开发中推荐使用 包装类的compare方法等方式比较。

(5)包装类中还有其他的一些方法,这里没有一一列举,可以自己看API。

public class TestWrapperAPI {
    //在运行这个main方法时,传入什么类型的命令行参数,都是放到了String[] args数组中
    //例如:从命令行参数接收两个整数,求和
    public static void main(String[] args) {
        int a = Integer.parseInt(args[0]);
        int b = Integer.parseInt(args[1]);
        System.out.println("a+b=" + (a+b));

        System.out.println("----------------------");
//        获取int的最大最小值
        System.out.println("int的最大值:" + Integer.MAX_VALUE);//2147483647
        System.out.println("int的最小值:" + Integer.MIN_VALUE);//-2147483648


        System.out.println("----------------------");
        char letter = 'a';
        //转大写
        System.out.println((char)(letter-32));
        System.out.println(Character.toUpperCase(letter));

        System.out.println("----------------------");
        double d1 = 1.4;
        double d2 = 1.2;
        //Double.compare(d1, d2)方法调用会返回3种结果,分别是正、负、0
        int result = Double.compare(d1, d2);
        if (result == 0) {
            System.out.println("d1=d2");
        }else if(result>0){
            System.out.println("d1>d2");
        }else{
            System.out.println("d1<d2");
        }

    }
}

5、包装类对象的缓存问题(或者说是常量对象问题)
(1)缓存对象范围
Byte,Short,Integer,Long这些整数的包装类型,会有缓存对象(常量对象):[-128,127]
    因为这些范围的数字在程序开发中最常用。
Float和Double,没有缓存对象。
Character的缓存对象范围是[0,127]
Boolean类型的缓存对象:true,false

(2)什么时候会启用缓存对象
自动装箱和valueOf方法创建的包装类对象,并且在缓存范围的,就用缓存对象。
其他的不用缓存对象,例如手动new,超过缓存范围的。

(3)讲解缓存对象的作用
A:面试题
B:开发中尽量使用自动装箱和valueOf方法,这样的话,如果是缓存对象范围内的数据,就共享同一个常量对象,可以节省内存。
要是每次new的话,就占太多内存,增加GC的负担。

public class TestCache {
    public static void main(String[] args) {
        int a = 1;
        int b = 1;
        System.out.println(a == b);//true

        Integer obj1 = 1; //自动装箱
        Integer obj2 = 1; //自动装箱
        System.out.println(obj1 == obj2);//true 比较对象的地址  用缓存对象,两个值一样的包装类对象,是同一个
        System.out.println(obj1.equals(obj2));//true 如果重写比较对象的内容值,如果没有重写,也是比较地址

        System.out.println("-------------------------------");
        int x = 128;
        int y = 128;
        System.out.println(x == y);//true

        Integer obj3 = 128; //自动装箱
        Integer obj4 = 128; //自动装箱
        System.out.println(obj3 == obj4);//false   比较对象的地址      没有用缓存对象,超过范围了,新new的
        System.out.println(obj3.equals(obj4));//true  Integer重写了Object的equals方法

        System.out.println("-------------------------------");
        Integer obj5 = new Integer(1);
        Integer obj6 = new Integer(1);
        System.out.println(obj5 == obj6);//false  没有用缓存对象,是新new的
        System.out.println(obj5.equals(obj6));//true

        System.out.println("-------------------------------");
        Integer obj7 = Integer.valueOf(1);
        Integer obj8 = Integer.valueOf(1);
        System.out.println(obj7 == obj8);//true  用缓存对象,两个值一样的包装类对象,是同一个
        System.out.println(obj7.equals(obj8));//true
    }
}

6、包装类的特点
(1)包装类与基本数据类型进行运算时,会自动拆箱。
    包装类与包装类进行  ==和!=、=以外的运算(<,>等)时,也会自动拆箱处理。
    包装类与包装类进行  ==和!=、=的运算时,不会自动拆箱,那么要求 两边的类型必须一致。

(2)包装类与基本数据类型的自动装箱与拆箱,只在自己对应的类型之间发生
int<--->Integer
double<---->Double
....

(3)包装类对象是不可变对象
包装类对象的修改,会产生新对象。

public class TestWrapperExam {
    public static void main(String[] args) {
        Integer obj1 = 130;
        int i = 130;
        System.out.println(obj1 == i); // true  obj1是引用数据类型,i是基本数据类型
                                        //问题?是吧obj1对象自动拆为基本数据类型 还是把i自动装为包装类的对象比较?
                                        //结果可以看出是拆箱为基本数据类型做比较

        Double d = 1.2;
        int j = 1;
        System.out.println(d < j);//false
                                //d是引用数据类型,j是基本数据类型,怎么处理的?
                                //(1)先把d拆箱为基本数据类型double
                                //(2)再把int自动类型提升为double

        Integer m = 1;
        Double n = 1.1;
        System.out.println(m < n);//m和n都是引用数据类型
                                //(1)先将m自动拆箱为int,n自动拆为double(2)然后int自动类型提升为double

        //System.out.println(m == n);//报错   因为==本身是支持引用数据类型,如果==双边都是引用数据类型,那么就不会自动拆箱
                                    //就按照引用数据类型处理,m和n之间是不同的,并且没有父子类关系的类型,是无法比较的

        System.out.println("-------------------------");
        Double d1 = 11.0; //Double与double之间可以自动装箱
        Integer k = 15;//Integer与int之间可以自动装箱
//        Double d2 = 15;//错误  因为左边是Double,右边是int类型,它俩之间不会直接发生自动装箱

        System.out.println("-------------------------");
        int num = 1;
        Integer obj = 1;
        String str = "java";
        MyData myData = new MyData();
        myData.a = 1;
        MyData data = new MyData();
        data.a = 1;

        change(num,obj,str,myData,data);

        System.out.println("num=" + num);//1
        System.out.println("obj=" + obj);//1
        System.out.println("str=" + str);//java
        System.out.println("myData.a = " + myData.a);//2
        System.out.println("data.a = " + data.a);//1
    }

    /*
    考点:方法的参数传递机制
    基本数据类型:形参修改和实参无关,例如:int
    引用数据类型:形参修改了成员变量,和实参有关,例如:MyData
    另外,引用数据类型的形参如果指向了新对象,也和实参无关,例如:j,s,d
     */
    public static void change(int i, Integer j, String s, MyData m, MyData d){
        i++;
        j++; //j是包装类型,它的修改会产生新对象,相当于 j = new Integer(j+1);
        s+="hello";//s是字符串,也是不可变对象类型,修改也会产生新对象,相当于 s = new String(s + "hello");
        m.a ++;
        d = new MyData();//d直接指向对象,和实参无关
        d.a=3;
    }
}
class MyData{
    int a;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值