【Java基础】 内部类 (成员内部类、局部内部类、静态内部类、匿名内部类)

简介: Java内部类 (成员内部类、局部内部类、静态内部类、匿名内部类)

内部类是什么呢?

Java内部类,是定义在一个类内部的类。在Java编程语言中,内部类是一个十分独特且强大的结构,它允许在一个外部类的内部定义另一个类。这种结构不仅增加了代码的封装性,还提供了访问外部类的私有成员的能力,从而在某些情况下简化了代码设计。

内部类的概念:

内部类是指在一个外部类的内部定义的类。它可以访问包含它的外部类的所有成员,包括私有成员。

内部类可以定义为非静态或静态。非静态内部类持有外部类的引用,而静态内部类则不需要。

内部类的分类:

成员内部类、局部内部类、静态内部类、匿名内部类


一、成员内部类

概念

成员内部类(Member Inner Class)是指在一个外部类的内部定义的类。成员内部类和外部类有着紧密的联系,能够访问外部类的所有成员,包括私有成员。成员内部类通常用来逻辑上关联外部类,并且可以更好地封装数据和行为。

特点

  1. 访问权限:成员内部类可以访问外部类的所有成员(包括私有成员)。
  2. 与外部类实例的关联:成员内部类的实例与创建它的外部类实例相关联。要创建成员内部类的实例,必须首先创建一个外部类的实例。
  3. 外部类引用:成员内部类可以使用 OuterClass.this来引用外部类的实例。
public class OuterClass {
    private String name = "外部类";
    public void printName() {
        System.out.println("外部类名称: " + name);
    }
    class InnerClass {
        public void accessOuterClass() {
            System.out.println("内部类访问外部类成员:");
            System.out.println("外部类名称: " + OuterClass.this.name);
            OuterClass.this.printName();
        }
    }
    public static void main(String[] args) {
        OuterClass outer = new OuterClass();
        OuterClass.InnerClass inner = outer.new InnerClass();
        inner.accessOuterClass();
    }
}

在这个例子中,InnerClass通过OuterClass.this.name和OuterClass.this.printName()访问了外部类OuterClass的成员变量和方法。

  1. 实例化方式:要实例化成员内部类,必须先实例化外部类,然后使用外部类的实例来实例化内部类。

成员内部类是定义在外部类中的类,并且与外部类的实例相关联。它们可以访问外部类的所有成员,包括私有成员。使用成员内部类可以使相关类之间的关系更加紧密,并且有助于封装和组织代码。

代码实现

public class OuterClass {
    private String outerField = "Outer Field";
   
    // 成员内部类
    class InnerClass {
        private String innerField = "Inner Field";
       
        // 内部类的方法
        public void display() {
            // 访问外部类的成员
            System.out.println("Outer Field: " + outerField);
            // 访问内部类的成员
            System.out.println("Inner Field: " + innerField);
        }
    }
   
    // 外部类的方法,用于创建和使用内部类的实例
    public void useInnerClass() {
        InnerClass inner = new InnerClass();
        inner.display();
    }
   
    public static void main(String[] args) {
        // 创建外部类的实例
        OuterClass outer = new OuterClass();
        // 使用外部类的方法来使用内部类
        outer.useInnerClass();
       
        // 直接创建内部类的实例
        OuterClass.InnerClass innerDirect = outer.new InnerClass();
        innerDirect.display();
    }
}

二、局部内部类

概念

局部内部类(Local Inner Class)是定义在一个方法、构造器或代码块中的类。局部内部类只能在其定义的范围内使用,并且通常用于封装仅在该方法中需要的逻辑。局部内部类可以访问外部类的成员变量和方法,但外部类不能直接访问局部内部类的成员。

特点

  1. 局部内部类只能访问外部类的 final 变量或者实际上不变的变量。
  2. 局部内部类可以直接访问外部类的成员,包括私有成员。
  3. 局部内部类不能含有 static 的变量和方法。

注意事项

  1. 局部内部类的定义必须在方法内部,不能在类的其他部分定义。
  2. 局部内部类的对象创建时机是在方法调用时,随方法执行完毕而销毁。

代码实现

// 定义一个名为OuterClass的外部类
public class OuterClass {
    // 定义一个私有成员变量name,并初始化为"外部类"
    private String name = "外部类";
    // 定义一个公共方法printName(),用于打印name的值
    public void printName() {
        System.out.println("外部类名称: " + name);
    }
    // 定义一个公共方法method()
    public void method() {
        // 在method()方法中定义一个局部内部类LocalInnerClass
        class LocalInnerClass {
            // 定义一个私有成员变量innerName,并初始化为"局部内部类"
            private String innerName = "局部内部类";
            // 定义一个公共方法printInnerName(),用于打印innerName和访问外部类成员
            public void printInnerName() {
                System.out.println("局部内部类名称: " + innerName);
                System.out.println("访问外部类成员: " + name);
                printName();
            }
        }
        // 创建LocalInnerClass的一个实例localInner
        LocalInnerClass localInner = new LocalInnerClass();
        // 调用localInner的printInnerName()方法
        localInner.printInnerName();
    }
    // 定义主方法main()
    public static void main(String[] args) {
        // 创建OuterClass的一个实例outer
        OuterClass outer = new OuterClass();
        // 调用outer的method()方法
        outer.method();
    }
}

这段代码定义了一个名为OuterClass的外部类,其中包含一个私有成员变量name和一个公共方法printName()。在method()方法中,定义了一个局部内部类LocalInnerClass,该类包含一个私有成员变量innerName和一个公共方法printInnerName()。在main()方法中,创建了OuterClass的一个实例outer,并调用其method()方法。

三、静态内部类

概念

静态内部类(Static Nested Class)是在外部类中使用 static 修饰符定义的内部类。与非静态内部类不同,静态内部类不需要外部类的实例即可创建。静态内部类通常用于外部类的逻辑分组,并且可以访问外部类的静态成员。静态内部类是定义在另一个类中的静态类。它类似于顶级类,但被嵌套在另一个类中。静态内部类不依赖于外部类的实例,可以直接创建。

特点

  1. 无需外部类实例: 静态内部类的实例可以独立于外部类的实例创建。

  1. 访问外部类的静态成员: 静态内部类只能访问外部类的静态成员(变量和方法),不能直接访问外部类的非静态成员。

  1. 类似于顶级类: 静态内部类在许多方面类似于顶级类,但它们可以被嵌套在其他类中,用于逻辑分组。

注意事项

成员访问限制: 静态内部类不能直接访问外部类的非静态成员。如果需要访问,可以通过外部类的实例来实现。

静态上下文: 静态内部类本身是在静态上下文中定义的,因此它的所有直接成员(字段和方法)也必须是静态的,除非在实例方法中访问。

代码实现

public class OuterClass {
    private static String staticOuterField = "Static Outer Field";
    private String instanceOuterField = "Instance Outer Field";
    // 静态内部类
    public static class StaticInnerClass {
        private String innerField = "Inner Field";
        public void display() {
            // 访问外部类的静态成员
            System.out.println("Static Outer Field: " + staticOuterField);
            // 不能直接访问外部类的非静态成员
            // System.out.println("Instance Outer Field: " + instanceOuterField); // 错误
        }
        // 静态内部类中的静态方法
        public static void staticDisplay() {
            // 访问外部类的静态成员
            System.out.println("Static Outer Field: " + staticOuterField);
        }
    }
    public static void main(String[] args) {
        // 创建静态内部类的实例
        StaticInnerClass inner = new StaticInnerClass();
        inner.display();
        // 调用静态内部类的静态方法
        StaticInnerClass.staticDisplay();
    }
}

这段代码定义了一个名为OuterClass的外部类,其中包含一个静态成员变量staticOuterField和一个实例成员变量instanceOuterField。在OuterClass中还定义了一个静态内部类StaticInnerClass,该类包含一个成员变量innerField和两个方法display()和staticDisplay()。在main()方法中,创建了StaticInnerClass的一个实例inner,并调用了其display()方法和StaticInnerClass的静态方法staticDisplay()。

四、匿名内部类

概念

匿名内部类(Anonymous Inner Class)是没有名字的内部类,通常用于简化代码,只在某个特定场景下使用一次。匿名内部类可以用来继承一个类或实现一个接口。匿名内部类定义在方法、构造器或初始化块中,用于即时实例化一个对象。匿名内部类通常用于需要快速创建类的实例并覆盖其方法的情况。

特点

  1. 没有名字: 匿名内部类没有名字,不能在其他地方引用或复用。

  1. 一次性使用: 匿名内部类通常只在创建它的地方使用一次。

  1. 简化代码: 匿名内部类可以直接定义在使用它们的地方,减少了定义新类的繁琐步骤。

  1. 可以继承一个类或实现一个接口: 匿名内部类可以用来继承一个现有的类或实现一个接口。

注意事项

访问局部变量: 匿名内部类可以访问包含它的作用域中的局部变量,但这些变量必须是 final 或有效 final。

构造器: 匿名内部类没有构造器,可以通过初始化块来初始化实例变量。

限制: 由于匿名内部类没有名字,不能在定义之外的其他地方引用或复用它们。

匿名内部类是一种简化代码的方式,用于即时创建类的实例并覆盖其方法。它没有名字,通常只在创建它的地方使用一次。匿名内部类可以继承一个类或实现一个接口,可以访问外部类的成员变量和包含它的局部变量(这些变量必须是 final 或有效 final)。匿名内部类在简化代码、封装临时逻辑方面非常有用。

代码实现

public class OuterClass {
    private String outerField = "Outer Field";
    public void outerMethod() {
        final String localVar = "Local Variable";  // 局部变量,必须是 final 或有效 final
        // 使用匿名内部类创建线程
        Thread thread = new Thread() {
            @Override
            public void run() {
                // 访问外部类的成员
                System.out.println("Outer Field: " + outerField);
                // 访问局部变量
                System.out.println("Local Variable: " + localVar);
            }
        };
        thread.start();
        // 使用匿名内部类实现接口
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                // 访问外部类的成员
                System.out.println("Outer Field: " + outerField);
                // 访问局部变量
                System.out.println("Local Variable: " + localVar);
            }
        };
        new Thread(runnable).start();
    }
    public static void main(String[] args) {
        OuterClass outer = new OuterClass();
        outer.outerMethod();
    }
}


上述代码使用匿名内部类实现接口:    

// 使用匿名内部类实现接口
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                // 访问外部类的成员
                System.out.println("Outer Field: " + outerField);
                // 访问局部变量
                System.out.println("Local Variable: " + localVar);
            }
        };
        new Thread(runnable).start();

匿名内部类:这里定义了一个实现 Runnable 接口的匿名内部类,并重写了其 run 方法。该匿名内部类在创建的同时定义并实例化。

访问外部类成员:匿名内部类能够直接访问外部类的私有成员 outerField

访问局部变量:匿名内部类能够访问方法内的局部变量 localVar,因为它是 final 的。

启动线程:创建一个新的 Thread 实例,并将 Runnable 类型的匿名内部类实例 runnable 传递给 Thread 构造器,随后调用 start 方法启动线程,这会调用 run 方法。


总结

成员内部类适合在需要访问外部类的实例成员时使用,必须通过外部类的实例创建。

局部内部类适合在方法内部使用,需要局部类逻辑封装时使用,局部变量需 final。

静态内部类适合在不需要外部类实例的情况下使用,可以直接访问外部类的静态成员。

匿名内部类适合临时实现一个类或接口,通常用于简化代码和一次性使用的场景。

每种内部类都有其特定的使用场景和限制,合理使用内部类可以使代码更加简洁和具有层次性。

希望本文对你理解和使用Java内部类提供了帮助。如果你有任何问题或建议,请随时留言。

目录
相关文章
|
1天前
|
设计模式 Java 编译器
Java中的内部类(如果想知道Java中有关内部类的知识点,那么只看这一篇就足够了!)
Java中的内部类(如果想知道Java中有关内部类的知识点,那么只看这一篇就足够了!)
|
19天前
|
Java 编译器
24. 【Java教程】内部类
24. 【Java教程】内部类
14 2
|
10天前
|
Java 编译器 程序员
Java基础9-深入理解Java内部类及其实现原理
Java基础9-深入理解Java内部类及其实现原理
12 0
|
Java Android开发
java基础篇 之 再探内部类跟final
java基础篇 之 再探内部类跟final
66 0
java基础篇 之 再探内部类跟final
|
Java
java基础篇 之 非静态内部类
java基础篇 之 非静态内部类
142 0
|
Java
Java基础 | 内部类
Java中的内部类讲解
77 0
|
Java C++
打好Java基础,从使用内部类开始!
本文主要介绍 Java中内部类的用法
119 0
|
机器人 Java
java基础之内部类
前言 所有使用内部类的地方都可以不用内部类,但使用内部类可以使程序更加的简洁,便于命名规范和划分层次结构。 内部类是指在一个外部类的内部再定义一个类。内部类可为静态,可用PROTECTED和PRIVATE修饰。(而外部类不可以:顶级类只能使用PUBLIC和DEFAULT)。JAVA文件中没有publie class 可以类名和文件不同名。 作者:zhulin1028 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
|
Java Android开发
Java基础——package+权限修饰符+内部类
Java基础——package+权限修饰符+内部类
104 0
Java基础——package+权限修饰符+内部类