内部类是定义在另一个类内部的类。它们与外部类之间存在一种特殊的关系,内部类可以访问外部类的成员,包括私有成员,而外部类也可以访问内部类的成员。内部类提供了一种封装和组织代码的方式,并且可以用于实现一些特定的设计模式和功能。

Java中有四种类型的内部类:

成员内部类(Member Inner Class)

成员内部类是定义在类内部的普通类,它与外部类的实例相关联。成员内部类可以访问外部类的成员,包括私有成员,并且可以使用this关键字来引用外部类的实例。可以通过以下语法创建成员内部类的实例:

public class OuterClass {
    /**
     * 静态内部类
     **/
    static class InnerClass {
        private String name;
        private Integer age;

        @Override
        public String toString() {
            return "InnerClass{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

    public static void main(String[] args) {
        OuterClass.InnerClass innerClass = new OuterClass.InnerClass();
        innerClass.name="wangzijian";
        innerClass.age=18;
        System.out.println(innerClass);
    }
}

静态内部类(Static Inner Class)

静态内部类是定义在类内部的静态类,它与外部类的实例无关,并且可以直接通过外部类的类名访问。静态内部类不能访问外部类的非静态成员,只能访问外部类的静态成员。可以通过以下语法创建静态内部类的实例:

public class OuterClass {
    /**
     * 成员内部类
     */
    class InnerClass {
        private String name;
        private Integer age;

        @Override
        public String toString() {
            return "InnerClass{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    public static void main(String[] args) {
        OuterClass outerClass = new OuterClass();
        OuterClass.InnerClass innerClass = outerClass.new InnerClass();
        innerClass.name = "wangzijian";
        innerClass.age = 18;
        System.out.println(innerClass);
    }
}

局部内部类(Local Inner Class)

局部内部类是定义在方法或作用域内的类,它的作用域被限定在所在的方法或作用域中。局部内部类可以访问外部类和方法或作用域的局部变量,但这些变量必须是final或实际上的final(Java 8+中允许访问非final的局部变量)。局部内部类的作用域仅限于定义它的方法或作用域内部。

public class OuterClass {

    public static void fun() {
        /**
         * 方法内部类
         **/
        class InnerClass {
            private String name;
            private Integer age;

            @Override
            public String toString() {
                return "InnerClass{" +
                        "name='" + name + '\'' +
                        ", age=" + age +
                        '}';
            }
        }
        InnerClass innerClass = new InnerClass();
        innerClass.name = "wangzijian";
        innerClass.age = 18;
        System.out.println(innerClass);
    }
    public static void main(String[] args) {
        fun();
    }
}

匿名内部类(Anonymous Inner Class)

匿名内部类是没有显式定义类的名称的内部类,它通常用于创建只需要一次使用的简单类。匿名内部类可以实现接口或扩展类,并且可以在创建对象的同时进行方法重写或实现。匿名内部类不能有显式的构造函数

public interface Person {

    /**
     * 人说话
     *
     * @param name
     */
    void speak(String name);
}

public class OuterClass {
    public static void main(String[] args) {

        Person person = new Person() {
            @Override
            public void speak(String name) {
                System.out.println(name);
            }
        };
        person.speak("hello world!");
    }
}

内部类的使用场景和优势:

  • 封装性:内部类可以访问外部类的私有成员,可以在内部类中隐藏一些细节,提高代码的封装性和安全性。

  • 实现特定功能:内部类可以用于实现一些特定的功能和设计模式,例如迭代器模式、事件监听器、线程等。

  • 代码组织和可读性:内部类可以将相关的类和接口组织在一起,提高代码的可读性和可维护性。

  • 访问外部类的成员:成员内部类可以直接访问外部类的成员,包括私有成员,这样可以简化代码并提供更好的代码组织。

需要注意的是,内部类会增加类之间的耦合性,因此在使用内部类时需要谨慎考虑设计和代码结构。同时,内部类的创建和使用语法相对复杂,需要注意语法规则和使用方式。

  1. 成员内部类
    假设有一个汽车类(Car),而汽车内部有一个引擎类(Engine),引擎与汽车之间有密切的关联。在这种情况下,可以将引擎类定义为汽车类的成员内部类。成员内部类可以访问汽车类的私有成员,并且通过外部类的实例来创建和操作引擎对象。

  2. 静态内部类
    假设有一个图形类(Shape),而图形类中有一个嵌套的计算工具类(Calculator),用于计算图形的面积和周长。由于计算工具类不需要访问图形类的实例变量,可以将其定义为静态内部类。静态内部类不依赖于外部类的实例,可以直接访问外部类的静态成员。

  3. 匿名内部类
    假设有一个按钮类(Button),当按钮被点击时,需要执行某个特定的操作。在这种情况下,可以使用匿名内部类来实现按钮的点击监听器接口。匿名内部类可以快速创建并实现接口,将按钮点击的逻辑直接定义在按钮的点击事件处理中,避免了创建独立的监听器类。

  4. 方法内部类
    假设有一个订单类(Order),每个订单可以包含多个商品。在订单类的方法中,可能需要定义一个内部类来表示商品对象,并提供一些与订单相关的特定操作。在这种情况下,可以使用方法内部类来定义订单类的特定商品类。方法内部类仅在方法内部可见,可以与订单类的其他成员进行交互。