首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >内部类的探究如何使用

内部类的探究如何使用

作者头像
Han.miracle
发布2025-12-22 14:10:24
发布2025-12-22 14:10:24
2810
举报

内部类的定义

类的五大成员:属性,方法,构造方法,代码块,内部类 在 Java 等面向对象编程语言中,内部类(Inner Class)是定义在另一个类内部的类。它与外部类(包含它的类)存在紧密关联,能够访问外部类的成员变量和方法,包括私有成员。 看下面代码:

代码语言:javascript
复制
\\这个就是外部类
public class Outer {
//这个就是内部类
public class Inner{
 }
}

//外部其他类
class Outer1{
}

那大家思考一个问题,我们为什么要学习内部类的,他的适应场景是什么呢? 那写一个描述汽车的类

代码语言:javascript
复制
 public class Car{
        String carName;
        int carAge;
        int carcolor;
        int engineAge;
        String engineName;
    }
    //大家看这个代码,这是我们是不是可以把这个Engine可以提出一个类
     public class Car{
        String carName;
        int carAge;
        int carcolor;
        //内部类
        //内部类的表示是没有任何实际意义的
        class engine{
        int engineAge;
        String engineName;
        }
    }

内部类的访问特点:

  • 内部类可直接访问外部类的成员,包括私有
  • 外部类要访问内部类的成员,必须要先创建内部类的对象
代码语言:javascript
复制
public class Car {
    private String carName;  // 外部类私有成员
    int carAge;              // 外部类成员
    
    // 发动机内部类
    class Engine {
        private String engineName;
        int engineAge;
        
        // 内部类方法可以直接访问外部类的所有成员(包括私有)
        public void showCarInfo() {
            System.out.println("汽车名称:" + carName);  // 访问外部类私有成员
            System.out.println("汽车使用年限:" + carAge);
        }
        
        public void setEngineInfo(String name, int age) {
            engineName = name;
            engineAge = age;
        }
    }
    
    // 外部类方法访问内部类成员,必须先创建内部类对象
    public void showEngineInfo() {
        Engine engine = new Engine();  // 创建内部类对象
        System.out.println("发动机名称:" + engine.engineName);
        System.out.println("发动机使用年限:" + engine.engineAge);
    }
    
    public void setCarName(String name) {
        this.carName = name;
    }
    
    public static void main(String[] args) {
        // 创建外部类对象
        Car car = new Car();
        car.carAge = 5;
        car.setCarName("特斯拉Model 3");
        
        // 创建内部类对象(需通过外部类对象)
        Car.Engine engine = car.new Engine();
        engine.setEngineInfo("永磁同步电机", 5);
        
        // 调用内部类方法
        engine.showCarInfo();
        
        // 调用外部类方法(该方法内部访问了内部类成员)
        car.showEngineInfo();
    }
}

内部类的分类

内部类分为四大类:成员内部类,静态内部类,局部内部类,匿名内部类

成员内部类

定义:直接定义在外部类的成员位置(与成员变量、成员方法同级),没有static修饰。 定义格式:

代码语言:javascript
复制
public class Outer{
String name ;
int age;
class inner {
String name;
int age;
}
}
  • 写在成员位置上的属于外部成员变量
  • 成员内部类可以被一些修饰符修饰,比如private,默认的,protected,public
  • 在成员变量内部类里,JDK之前不能定义静态变量,JDk 16才可以定义静态变量
代码语言:javascript
复制
public class Outer{
 protected class inner {
}
}

特性:

  • 属于外部类的实例成员,依赖外部类对象存在
  • 可直接访问外部类的所有成员(包括私有成员)
  • 外部类访问成员内部类的成员时,必须先创建内部类对象
  • 成员内部类中不能定义静态成员(静态常量除外)
代码语言:javascript
复制
public class Outer {
    private int outerField = 10;
    
    // 成员内部类
    public class Inner {
        int innerField = 20;
        
        public void innerMethod() {
            // 直接访问外部类成员
            System.out.println("外部类字段:" + outerField); 
        }
    }
    
    // 外部类访问内部类成员
    public void outerMethod() {
        Inner inner = new Inner(); // 必须创建内部类对象
        System.out.println("内部类字段:" + inner.innerField);
    }
    
    public static void main(String[] args) {
        Outer outer = new Outer();
        // 创建内部类对象:外部类对象.new 内部类()
        Outer.Inner inner = outer.new Inner();
        inner.innerMethod(); // 调用内部类方法
    }
}

获取成员内部类对象

方式1: 在外部类中编译使用内部类的方法,对外提供内部类的对象

代码语言:javascript
复制
public class Phone {
    private String brand;
    
    // 内部类:电池
    class Battery {
        private int capacity;
        
        public Battery(int capacity) {
            this.capacity = capacity;
        }
        
        // 内部类方法:显示电池信息
        public void showInfo() {
            // 直接访问外部类成员
            System.out.println(brand + "手机,电池容量:" + capacity + "mAh");
        }
    }
    
    // 外部类构造方法
    public Phone(String brand) {
        this.brand = brand;
    }
    
    // 对外提供内部类对象的方法
    public Battery createBattery(int capacity) {
        return new Battery(capacity); // 创建并返回内部类对象
    }
    
    public static void main(String[] args) {
        Phone phone = new Phone("华为");
        
        // 通过外部类方法获取内部类对象
        Phone.Battery battery = phone.createBattery(5000);
        battery.showInfo();
    }
}

方式2: 直接创建格式:外部类名.内部类名 对象名字 = new 外部类().new 内部类();

代码语言:javascript
复制
// 完整语法结构
外部类名.内部类名 对象名 = new 外部类().new 内部类();

这是因为成员内部类依赖于外部类的实例存在,必须先创建外部类对象,才能通过外部类对象创建内部类对象。

代码语言:javascript
复制
public class Outer {
    class Inner {
        void show() {
            System.out.println("这是内部类方法");
        }
    }
    
    public static void main(String[] args) {
        // 在外部类的静态方法中创建内部类对象(也需要遵循同样规则)
        Outer.Inner inner = new Outer().new Inner();
        inner.show();
    }
}

// 在另一个完全独立的类中使用
class OtherClass {
    public static void main(String[] args) {
        // 外部其他类中创建内部类对象
        Outer.Inner inner = new Outer().new Inner();
        inner.show();
    }
}

注意:

这种方式仅适用于非静态成员内部类 静态内部类的创建方式不同,不需要依赖外部类实例:

静态内部类

静态内部类是用 static 修饰的内部类,它是内部类中比较特殊的一种,不依赖外部类的实例而存在,更像是一个 “嵌套在外部类中的独立类”。

创建静态内部类对象的格式: 外部类名.内部类名 对象名 = new 外部类名.内部类名();

代码语言:javascript
复制
外部类名.内部类名 对象名 = new 外部类名.内部类名();

调用静态内部类的格式: 先创建对象,后对象调用

代码语言:javascript
复制
// 访问静态内部类的静态变量
外部类名.静态内部类名.静态变量名;

// 调用静态内部类的静态方法
外部类名.静态内部类名.静态方法名(参数);

通过对象访问静态内部类的非静态成员

代码语言:javascript
复制
// 创建对象后,调用非静态方法或访问非静态变量
对象名.非静态方法名(参数);
对象名.非静态变量名;

核心特点

  • 静态内部类不依赖外部类对象,因此无需先创建外部类实例。
  • 所有操作都通过 “外部类名。静态内部类名” 作为前缀,明确静态内部类的归属。
  • 静态成员可直接通过类名访问,非静态成员需通过对象访问(与普通类规则一致)

局部内部类

局部内部类是定义在外部类的方法或代码块(如if、for块)内部的类,其作用范围仅限于所在的方法或代码块,出了这个范围就无法访问。

局部内部类的特点:

  • 作用域有限:仅在定义它的方法或代码块内有效,外部无法直接访问,外部访问需要在方法内部创建对象并使用
代码语言:javascript
复制
public class Outer {
    private String outerData = "外部类数据";
    
    public void outerMethod() {
        int methodParam = 100; // 方法局部变量
        
        // 局部内部类(仅在当前方法内可见)
        class LocalInner {
            public void showInfo() {
                System.out.println("访问外部类成员:" + outerData);
                System.out.println("访问方法参数:" + methodParam);
            }
        }
        
        // 必须在方法内部创建局部内部类对象并使用
        LocalInner inner = new LocalInner();
        inner.showInfo(); // 正确:在作用域内使用
    }
    
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.outerMethod(); // 调用方法,间接触发局部内部类功能
        
        // 以下代码会编译报错(外部无法访问局部内部类)
        // LocalInner inner = new LocalInner(); // 错误:找不到LocalInner类
        // Outer.LocalInner inner = new Outer().new LocalInner(); // 错误:LocalInner不可见
    }
}
  • 访问权限: 1.可直接访问外部类的所有成员(包括私有成员)。 2. 只能访问所在方法中被final修饰(或隐式 final,即赋值后不再修改)的局部变量(Java 8 + 特性)。
  • 修饰符限制:不能使用public、private、static等修饰符(因作用域仅限方法内部)
代码语言:javascript
复制
public class Shop {
    // 外部类私有成员(验证特性:局部内部类可访问)
    private String shopName = "晨光文具店";
    // 外部类非私有成员
    int saleCount = 100;

    // 包含局部内部类的方法
    public void calculateDiscount(int originalPrice) {
        // 方法局部变量:赋值后不修改(隐式final,验证特性2)
        int discountRate = 90; // 9折
        // 方法局部变量:显式final(验证特性2)
        final int minPrice = 10;

        // 局部内部类(验证:无public/private/static修饰符,特性3)
        class DiscountCalculator {
            // 局部内部类的成员方法
            public void showFinalPrice() {
                // 1. 访问外部类所有成员(包括私有,特性1)
                System.out.println("店铺:" + shopName);
                System.out.println("本月销量:" + saleCount + "件");

                // 2. 访问方法的局部变量(final/隐式final,特性2)
                int finalPrice = originalPrice * discountRate / 100;
                System.out.println("原价:" + originalPrice + "元,折后价:" + finalPrice + "元");
                System.out.println("最低售价限制:" + minPrice + "元");

                // !若尝试修改局部变量,编译报错(验证特性2)
                // discountRate = 80; // 报错:局部变量在内部类中使用,不能修改
                // minPrice = 5; // 报错:final变量不能修改
            }
        }

        // 外部无法直接访问,必须在方法内创建对象并使用(特性:作用域有限)
        DiscountCalculator calculator = new DiscountCalculator();
        calculator.showFinalPrice();
    }

    public static void main(String[] args) {
        Shop shop = new Shop();
        // 调用方法,间接触发局部内部类功能(外部无法直接操作局部内部类)
        shop.calculateDiscount(50);

        // !以下代码均编译报错(验证特性:外部无法直接访问,特性3)
        // DiscountCalculator calc = new DiscountCalculator(); // 错误:找不到该类
        // public class DiscountCalculator{} // 错误:局部内部类不能加public
        // static class DiscountCalculator{} // 错误:局部内部类不能加static
    }
}

匿名内部类

定义:匿名内部类本质就是隐藏了名字的内部类 匿名内部类是一种没有类名的局部内部类,通常用于 “一次性” 实现接口或继承类,简化代码编写。它在定义的同时必须创建实例,语法上更像是一个 “创建对象的表达式”。

格式:

  1. 实现接口的匿名内部类(最常用)
代码语言:javascript
复制
接口类型 对象名 = new 接口名() {
    // 必须实现接口中所有抽象方法
    @Override
    public 返回值类型 方法名(参数列表) {
        // 方法体
    }
};

示例:

代码语言:javascript
复制
// 定义接口
interface Flyable {
    void fly();
}

public class Test {
    public static void main(String[] args) {
        // 创建实现Flyable接口的匿名内部类
        Flyable bird = new Flyable() {
            @Override
            public void fly() {
                System.out.println("小鸟展翅高飞");
            }
        };
        
        // 调用方法
        bird.fly();
    }
}
  1. 继承类的匿名内部类
代码语言:javascript
复制
父类类型 对象名 = new 父类名(构造参数) {
    // 可选:重写父类方法
    @Override
    public 返回值类型 方法名(参数列表) {
        // 方法体
    }
};

示例:

代码语言:javascript
复制
// 定义父类
class Person {
    public void say() {
        System.out.println("人在说话");
    }
}

public class Test {
    public static void main(String[] args) {
        // 创建继承Person类的匿名内部类
        Person student = new Person() {
            @Override
            public void say() {
                System.out.println("学生说:我在学习");
            }
        };
        
        // 调用重写后的方法
        student.say();
    }
}
  1. 直接创建匿名内部类对象(无需变量接收) 如果只需使用一次,可省略变量名,直接创建对象并调用方法:
代码语言:javascript
复制
// 实现接口的简化写法
new Runnable() {
    @Override
    public void run() {
        System.out.println("直接执行一次");
    }
}.run(); // 直接调用方法

关键语法要点:

  • 没有类名:通过new 接口名()或new 父类名()隐式定义类。
  • 必须实现抽象方法:若实现接口,需覆盖所有抽象方法;若继承类,可选择性重写方法。
  • 立即实例化:new关键字不仅是创建对象,还包含类的定义。
  • 分号结尾:整个匿名内部类定义是一个表达式,末尾必须加 ;

这种格式的优势在于:当某个类只需要使用一次时,无需单独定义类文件,直接在使用处完成定义和实例化,大幅简化代码。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-12-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 内部类的定义
  • 内部类的分类
  • 成员内部类
    • 获取成员内部类对象
    • 静态内部类
    • 局部内部类
    • 匿名内部类
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档