• Java | 内部类(Inner Class)


    前言

    定义

    内部类(Inner Class),是 Java 中对类的一种定义方式,是嵌套类的一个分类,即非静态嵌套类(Non-Static Nested Class)。内部类(非静态嵌套类)分为成员内部类、局部内部类和匿名内部类三种。

    Java 编程语言允许一个类被定义在另一个类中,这样的类就称为嵌套类。嵌套类分为两种:静态的和非静态的。没有用 static 关键字来声明的嵌套类,就称为非静态嵌套类。非静态嵌套类,又称为内部类。内部类还有两个特殊的类型:局部类(Local Class)和匿名类(Anonymous Class)。

    包含嵌套类的类,可称为外围类(Enclosing Class)或外部类(Outer Class)。非静态嵌套类(内部类)可访问其外围类的其他成员,即使这些成员被声明为私有的。若内部类作为其外部类的成员,则它可声明为 privatepublicprotected 或包私有的。

    • 提示:外部类只能声明为 public 或包私有的。

    概述

    作为其外部类成员的内部类,称为成员内部类。除另有说明外,“内部类”通常是指成员内部类。

    与实例的方法和变量一样,内部类与其外围类的实例相关联,并可直接访问该外围类对象的方法和字段。此外,由于内部类与实例相关联,因此不能在内部类中定义任何静态成员。

     1 /**
     2  * 定义一个公共的 OuterClass 类。
     3  */
     4 public class OuterClass {
     5     private final String name;
     6 
     7     public static void main(String[] args) {
     8         String name = "Java";
     9         OuterClass outerObject = new OuterClass(name);
    10         OuterClass.InnerClass innerObject = outerObject.new InnerClass();
    11         System.out.println(outerObject.getName());
    12         System.out.println(innerObject.getName());
    13     }
    14 
    15     /**
    16      * 定义一个 OuterClass 类的构造方法。
    17      *
    18      * @param name 表示一个名称字符串。
    19      */
    20     public OuterClass(String name) {
    21         this.name = name;
    22     }
    23 
    24     public String getName() {
    25         return name;
    26     }
    27 
    28     /**
    29      * 定义一个私有的 InnerClass 类。
    30      */
    31     private class InnerClass {
    32         private final String name;
    33 
    34         /**
    35          * 定义一个 InnerClass 类的构造方法。
    36          */
    37         public InnerClass() {
    38             name = OuterClass.this.name + " (in the inner object)";
    39         }
    40 
    41         public String getName() {
    42             return name;
    43         }
    44     }
    45 }
    46 /* 输出结果:
    47 Java
    48 Java (in the inner object)
    49 
    50  */

    在上述示例中,InnerClass 类的实例只能存在于 OuterClass 类的实例中,并且可以直接访问 OuterClass 类的实例的方法和字段。

    要实例化内部类,就必须首先实例化外部类。然后,使用以下语法在外部对象中创建内部对象:

    1         OuterClass.InnerClass innerObject = outerObject.new InnerClass();
    • 提示:可以用内部类来实现助手类(Helper Class)。如要处理用户界面的事件,就必须知道如何使用内部类,因为内部类广泛地使用在事件处理机制上。

    遮蔽 - 重名问题

     1 public class Outer {
     2     String name = "这是外部类的成员变量名";
     3     int num = 12;
     4 
     5     public static void main(String[] args) {
     6         Outer outer = new Outer();
     7         Outer.Inner inner = outer.new Inner();
     8         int num = 56;
     9         inner.methodInInner(num);
    10     }
    11 
    12     public Outer() {
    13     }
    14 
    15     class Inner {
    16         String name = "这是内部类的成员变量名";
    17         int num = 34;
    18 
    19         public Inner() {
    20         }
    21 
    22         void methodInInner(int num) {
    23             String name = "这是内部类方法的局部变量名";
    24             System.out.println("name:" + name);
    25             System.out.println("this.name:" + this.name);
    26             System.out.println("Outer.this.name:" + Outer.this.name);
    27             System.out.println("================================");
    28             System.out.println("num = " + num);
    29             System.out.println("this.num = " + this.num);
    30             System.out.println("Outer.this.num = " + Outer.this.num);
    31         }
    32     }
    33 }
    34 /* 输出结果:
    35 name:这是内部类方法的局部变量名
    36 this.name:这是内部类的成员变量名
    37 Outer.this.name:这是外部类的成员变量名
    38 ================================
    39 num = 56
    40 this.num = 34
    41 Outer.this.num = 12
    42 
    43  */

    在上述示例中,外部类的字符串成员变量、内部类的字符串成员变量和内部类方法的字符串局部变量发生重名,则内部类方法的字符串局部变量的声明,遮蔽了外部类和内部类中的同名成员变量的作用域(如同将二者隐藏起来),使二者不能仅以名称来引用。

    同样的,外部类的整型成员变量、内部类的整型成员变量和内部类方法的整型参数发生重名,则内部类方法的整型参数的声明,遮蔽了外部类和内部类中的同名成员变量的作用域(如同将二者隐藏起来),使二者不能仅以名称来访问使用。

    如需在内部类方法中访问内部类的重名成员变量,请使用 this 关键字,如下:

    1             System.out.println("this.name:" + this.name);
    2             System.out.println("this.num = " + this.num);

    如需在内部类方法中访问外部类的重名成员变量,请使用外部类名加 this 关键字,如下:

    1             System.out.println("Outer.this.name:" + Outer.this.name);
    2             System.out.println("Outer.this.num = " + Outer.this.num);

    禁止序列化 - 兼容性问题

    Java 语言强烈建议禁止对内部类(包括局部类和匿名类)进行序列化。

    Java 编译器编译某些构造方法(如内部类)时,它会创建合成结构。与合成结构相关的类及其构造方法、字段和方法,在源代码中是没有的。合成结构能使 Java 编译器实现新的 Java 语言特性,而无需对 JVM 进行更改。

    然而,不同的 Java 编译器可能会创建不同的合成结构,这意味着 .class 文件在不同的实现中也会有所不同。因此,如果将内部类序列化,然后用不同的 JRE 将其反序列化,则可能会出现兼容性问题。

    局部类和匿名类

    局部类和匿名类是内部类的两个特殊的类型。

    在方法体中声明的内部类,称为局部内部类,亦称局部类。局部类是有类名的。

    在方法体中声明的无需命名的内部类,称为匿名内部类,亦称匿名类。匿名类是没有类名的。

  • 相关阅读:
    svn 更新
    首尾渐变
    sublime常用快捷键
    【CSS3】transition过渡和animation动画
    JS实现奇偶数的判断
    style、currentStyle、getComputedStyle区别介绍
    JavaScript中判断对象类型的种种方法
    CSS3 animation动画,循环间的延时执行时间
    EMCA创建em资料库时报错
    OS Kernel Parameter.semopm
  • 原文地址:https://www.cnblogs.com/blume/p/13189829.html
Copyright © 2020-2023  润新知