C_内部类、包装类

一:内部类

  1. 定义:在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。广泛意义上的内部类一般来说包括这四种:成员内部类、局部内部类、匿名内部类和静态内部类。内部类编译后的文件名为:"外部类名$内部类名.java"
  2. 成员内部类:成员内部类是最普通的内部类,它的定义为位于另一个类的内部,形如下面的形式:
    1. 成员内部类( Draw )访问外部类( Circle ):成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)不过要注意的是:当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:
      外部类.this.成员变量
      外部类.this.成员方法
    2. 外部类( Circle )访问成员内部类( Draw ):外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个内部类对象的引用来访问。
    3. 成员内部类和外部类访问权限区别:,外部类只能被public和包访问两种权限修饰。由于成员内部类看起来像是外部类的一个成员,所以可以像类的成员一样拥有多种权限修饰。
      • 内部类可以拥有private访问权限、protected访问权限、public访问权限及包访问权限。
        例子:如果成员内部类Draw用private修饰,则只能在外部类的内部访问。
        如果用public修饰,则任何地方都能访问。
        如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问。
        如果是默认访问权限,则只能在同一个包下访问。
    4. 深入理解: 为什么成员内部类可以无条件访问外部类的成员?
      • 因为内部中都持有一个final修饰的外部类的引用。这个是引用是外部类名.this
  3. 局部内部类
    1. 注意,局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。
    2. 局部内部类也像别的类一样进行编译,但只是作用域不同而已,只在该方法或条件的作用域内才能使用,退出这些作用域后无法引用的。并且只能访问这些作用域内final修饰的变量;在Java8中取消了这个限制,但是在局部内部类中也无法对其作出修改,相当于隐形的添加了final关键字
  4. 匿名内部类
    1. 定义:没有名字的内部类。就是内部类的简化形式。一般只用一次就可以用这种形式。匿名内部类其实就是一个匿名子类对象,想要定义匿名内部类:需要前提,内部类必须继承一个类或者实现接口否则编译时提示类或者接口找不到
    2. 格式:new 父类名&接口名(){ 定义子类成员或者覆盖父类方法 }.方法
    3. 使用场景
      • 当方法的参数是接口类型引用时,如果接口中的方法不超过3个。可以通过匿名内部类来完成参数的传递。
        其实就是在创建匿名内部类时,该类中的封装的方法不要过多,最好两个或者两个以内。
    4. 当所在的方法的形参需要被内部类里面使用时,该形参必须为final。这里可以看到形参name已经定义为final了,而形参city 没有被使用则不用定义为final。在Java8中可以不用final修饰,但还是不能再匿名内部类中对其进行修改
  5. 静态内部类
    1. 定义:使用static修饰的内部类我们称之为静态内部类。注意:如果内部类中定义了静态成员,那么该内部类必须是静态的
    2. 静态内部类与非静态内部类之间存在一个最大的区别:
      非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外部类,但是静态内部类却没有。没有这个引用就意味着:
      • 它的创建是不需要依赖于外围类的。
      • 它不能使用任何外围类的非static成员变量和方法。
    3. 示例代码
  6. 为什么在Java中需要内部类?
    1. 重要原因:java不支持多继承,但是每个内部类都能独立的继承一个接口的实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。内部类的存在使得多继承的解决方案变得完整,使得Java的多继承机制变得更加完善。
    2. 方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏:即封装
    3. 方便编写事件驱动程序
    4. 方便编写线程代码

二:包装类

  1. Java中有8中基本数据类型,因为Java是一个面向对象的语言,基本类型并不具有对象的性质,为了与其他对象“接轨”就出现了包装类型。
    1.八种基本类型中有六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型。
    - 整数:包括int,short,byte,long ,初始值为0
    - 浮点型:float,double ,初始值为0.0
    - 字符:char ,初始值为空格,即'' ",如果输出,在Console上是看不到效果的。
    - 布尔:boolean ,初始值为false
    1. 注意:
      表格里的^代表的是次方;
      java采用unicode,2个字节来表示一个字符。
  2. 基本类型的包装类
    1. Integer 、Long、Short、Byte、Character、Double、Float、Boolean、BigInteger、BigDecmail
    2. 其中BigInteger、BigDecimal没有相对应的基本类型,主要应用于高精度的运算,BigInteger 支持任意精度的整数,BigDecimal支持任意精度带小数点的运算。
  3. 基本类型与包装类型的异同:
    1. 在Java中,一切皆对象,但八大基本类型却不是对象。
    2. 声明方式的不同,基本类型无需通过new关键字来创建,而封装类型需new关键字。
    3. 存储方式及位置的不同,基本类型是直接存储变量的值保存在堆栈中能高效的存取,封装类型需要通过引用指向实例,具体的实例保存在堆中。
    4. 初始值的不同,封装类型的初始值为null,基本类型的的初始值视具体的类型而定,比如int类型的初始值为0,boolean类型为false;
    5. 使用方式的不同,比如与集合类合作使用时只能使用包装类型。
  4. 装箱、拆箱
    1. 基本类型向包装类转换为:装箱,反之为拆箱
    2. Integer x = 1; x = x + 1; 经历了什么过程?装箱、拆箱、装箱
  5. int和Integer的区别
    1. int是基本数据类型之一,Integer是int的包装类
    2. Java的常量池
      Java的自动拆箱和装箱
    3. Integer.valueOf源码
    4. 结论
      • new出来的Integer相比较,均为false,代表两个不同的对象,存储在堆中的位置不一样。
      • 非new出来的Integer相比较,如果数在-128到127之间,则是true,否则为false 。
      • int和Integer相比较,均为ture,因为Integer会先自动拆箱为int,再进行比较。
      • Integer和new Integer相比较,均为false。
        1. 如果值在-128到127之间,Integer的值存在于常量池,new Integer的值存在于堆中;
        2. 如果没在-128到127之间,那么均视为new Integer,同结论1。
    5. 注意:Short、Long也有相同的问题

猜你喜欢

转载自www.cnblogs.com/cqhcxm/p/9198961.html