java基础知识-内部类

本文详细介绍了Java中的内部类概念,包括成员内部类、局部内部类、匿名内部类和静态内部类,并重点阐述了静态内部类的特点及其与非静态内部类的区别。

内部类(Inner Class)是定义在另一个类内部的类。它允许将逻辑上相关的类组织在一起,并可以控制内部类的可见性。

分类

  • 成员内部类
  • 局部内部类
  • 匿名内部类
  • 静态内部类(定义在类中,任何方法外,用static修饰)

1、成员内部类

这是最普通的内部类形式,定义为另一个类的成员,与类的字段、方法、构造器处于同一级别。

  • 语法位置: 定义在外部类的内部,与方法、属性平级。
  • 访问权限: 可以是 public, protected, (默认), private。这决定了它在外部类之外的可见性。
  • 核心特性:
    它隐式持有一个指向外部类对象的引用(OuterClass.this)。因此,它可以无限制地访问外部类的所有成员(包括私有成员)。
    反之,外部类要访问成员内部类的成员,必须先创建一个成员内部类的对象。
  • 创建对象:
    在外部类内部:直接 new InnerClass()。
    在外部类之外:必须先有一个外部类的实例,然后通过这个实例来创建。
OuterClass outerObj = new OuterClass();
OuterClass.InnerClass innerObj = outerObj.new InnerClass(); // 注意 new 关键字前的实例

示例代码:

public class Outer {
    private String outerField = "Outer Field";

    // 成员内部类
    public class Inner {
        public void print() {
            // 可以直接访问外部类的私有字段
            System.out.println("Accessing from Inner: " + outerField);
            // 等价于 System.out.println(Outer.this.outerField);
        }
    }

    public void useInner() {
        Inner inner = new Inner(); // 在外部类内部创建内部类对象
        inner.print();
    }
}

// 在另一个类中使用
class Test {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.useInner(); // 方式一:通过外部类方法间接使用

        // 方式二:直接创建内部类对象
        Outer.Inner inner = outer.new Inner(); // 关键语法
        inner.print();
    }
}

2、局部内部类

定义在方法、代码块或构造器内部的类,其作用域仅限于所在的代码块内。

  1. 语法位置: 定义在方法内部。
  2. 访问权限: 不能使用任何访问修饰符(如 public, private),因为它本身就是方法的一部分,其作用域已被方法限定。
  3. 核心特性:
    和成员内部类一样,它可以访问外部类的所有成员。
    它可以访问方法中的 final 或 有效最终(effectively final)的局部变量(即初始化后值永不改变的变量)。在 Java 8 之前,必须显式声明为 final。
  4. 创建对象: 只能在定义它的方法或作用域内部创建和使用。

示例代码:

public class Outer {
    private String outerField = "Outer Field";

    public void someMethod() {
        final String localVar = "Local Variable"; // 有效最终变量

        // 局部内部类
        class LocalInner {
            public void print() {
                System.out.println("Outer field: " + outerField);
                System.out.println("Local variable: " + localVar); // 只能访问 final 或 effectively final 的局部变量
            }
        }

        // 只能在方法内部使用局部内部类
        LocalInner localInner = new LocalInner();
        localInner.print();
    }
}

3、 匿名内部类

一种没有名字的局部内部类,它同时完成了类的定义和实例化。通常用于只需使用一次的场景,例如实现接口或继承类,并重写方法。

  1. 语法位置: 通常作为 new 语句的一部分。

  2. 语法: new InterfaceName() { … } 或 new ClassName() { … }。

  3. 核心特性:
    没有显式的 class 关键字和类名。
    只能继承一个类或实现一个接口。
    同样可以访问外部类的所有成员以及作用域内的 final/有效最终变量。

  4. 常见用途: 快速创建线程(Runnable)、事件监听器(ActionListener)等。

示例代码:

public interface Greeting {
    void sayHello();
}

public class Outer {
    public void greet() {
        // 匿名内部类:实现 Greeting 接口
        Greeting greeting = new Greeting() { // Greeting 是一个接口
            @Override
            public void sayHello() {
                System.out.println("Hello from Anonymous Inner Class!");
            }
        }; // 注意这里有分号,因为这是一个赋值语句

        greeting.sayHello();

        // 更常见的用法:直接在方法参数中使用
        new Thread(new Runnable() { // Runnable 是一个接口
            @Override
            public void run() {
                System.out.println("A new thread is running.");
            }
        }).start();
    }
}

**注意:**在 Java 8 之后,很多匿名内部类的场景可以被 Lambda 表达式 替代,使代码更简洁。

4、静态内部类

使用 static 关键字修饰的内部类。它不依赖于外部类的实例。

  • 语法位置: 定义在外部类的内部,用 static 修饰。
  • 访问权限: 可以是 public, protected, (默认), private。
  • 核心特性:
    它没有指向外部类实例的隐式引用(即没有 OuterClass.this)。因此:
    它不能直接访问外部类的非静态成员(包括非静态字段和方法)。
    它的创建不需要外部类的实例。
    它就像是外部类的一个静态成员,只是这个成员恰好是一个类。
  • 创建对象:
    在外部类之外:直接通过外部类名创建,无需外部类实例。
OuterClass.StaticNestedClass nestedObj = new OuterClass.StaticNestedClass();

示例代码:

public class Outer {
    private String nonStaticField = "Non-Static";
    private static String staticField = "Static";

    // 静态内部类
    public static class StaticNested {
        public void print() {
            // System.out.println(nonStaticField); // 错误!不能访问外部类的非静态成员
            System.out.println("Accessing static field: " + staticField); // 可以访问静态成员
            System.out.println("I am a static nested class.");
        }
    }
}

class Test {
    public static void main(String[] args) {
        // 创建静态内部类对象,无需外部类实例
        Outer.StaticNested nested = new Outer.StaticNested();
        nested.print();
    }
}

总结对比

特性成员内部类局部内部类匿名内部类静态内部类
位置类成员,与方法平级方法或代码块内部方法内,通常是new语句类成员,用static修饰
类名有明确类名有明确类名无类名有明确类名
访问修饰符可以使用不能使用不能使用可以使用
持有外部类引用是 (Outer.this)
访问外部类成员可访问所有可访问所有可访问所有只能访问静态成员

静态内部类和非静态内部类的区别

  1. 非静态内部类不可以声明静态成员变量和静态成员方法。
  2. 一般非静态内部类可以随意访问其外部类的成员变量以及方法(包括声明为private的方法);静态内部类只能访问外部类的静态成员变量和静态成员方法,不能访问非静态成员变量和方法。
  3. 在一个类中创建非静态内部类,内部类的实例一定要绑定在外部类的实例中,在一个外部类中定义一个静态的内部类,不需要利用关键字new来创建内部类的实例,也就是说创建静态内部类对象时,不需要其外部类的对象。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值