总结:Java各种内部类与外部类的关系

总结:Java各种内部类与外部类的关系

一·权限修饰符:影响所修饰代码,能不能被其他地方代码直接引用(间接引用是可以的),不同权限修饰符,影响的范围不一样

1.私有(private):

修饰的代码,只能够在代码所属类里面,任意地方直接引用

2. 默认(package-private):

修饰的代码,只能够在代码类所属包下面的所有类里面,任意地方直接引用

3.受保护(protected):

修饰的代码,只能够在本类、本包以及其他包下所有子类里面,任意地方直接引用

4.公共(public):

修饰的代码,能够在不同包下,所有类里面,任意地方直接引用

二·static关键字:影响所修饰代码,在类加载的时候执行顺序;static修饰代码比非static修饰代码先加载执行;且static修饰的代码是被该类的所有对象实例共享

三·final关键字:影响所修饰代码保持不变

  1. 修饰类:当一个类被声明为 final 时,意味着这个类不能被其他类继承。这样做的目的是为了保护类的设计完整性或者防止被子类修改功能
  2. 修饰方法:如果一个方法被声明为 final,那么该方法不能在其子类中被重写(override)。
  3. 修饰变量:当 final 关键字修饰实例变量(成员变量)时,该变量必须在声明时初始化或者在构造函数中赋值,一旦赋值后就无法更改其引用指向的对象。final经常用于创建常量,尤其是在静态上下文中。

四·什么是外部类、内部类?

1. 一个个普通独立类就是外部类,外部类只能使用两种权限修饰符(缺省、public),以及final修饰符,不能使用static修饰

2. 内部类是外部类的一部分,地位等同外部类的其他成员属性

3. 一般B类只属于A类的一部分,且B类单独存在没有意义,那么B类就建议声明为内部类形式

在这里插入图片描述

五·内部类相关概念:

1.概念:嵌套在外部类里面的类,就是内部类

2.分类:普通内部类、静态内部类、局部内部类、匿名内部类

3.修饰符:私有、缺省、受保护、公共权限修饰符都可以修饰、final也可以修饰

六·各种内部类与外部类之间的联系

1.普通内部类:

在这里插入图片描述

(1)示例代码:

public class OuterClass {
    private int age = 100;
    private String name = "outer";

    public static void main(String[] args) {
        //外部类创建内部类对象
        OuterClass.InnerClass innerClass = new OuterClass().new InnerClass();
        //访问内部类正常属性方法
        innerClass.print(10);
        
        //访问内部类静态属性
        System.out.println(OuterClass.InnerClass.size);

        //获取私有内部类对象
        OuterClass.InnerClass2 innerClass2 = new OuterClass().getInnerClass2();
        innerClass2.print(20);
    }
    

    //公共内部类
    public class InnerClass {
    	//jdk16之前不能定义静态变量,jdk16之后才行
        static int size = 50;
        private int age = 90;

        public void print(int age) {
            System.out.println("形参age:" + age);
            System.out.println("外部类name:" + name);
            System.out.println("内部类age:" + this.age);
            /** Java虚拟机会在内部类里面自动维护一个外部类对象,通过OuterClass.this访问 */
            System.out.println("外部类age:" + OuterClass.this.age);
        }
    }

    /**
     * 获取私有内部类对象方法,提供给外部使用
     *
     * @param
     * @return
     * @author LiuMingFu
     * @date 2024/7/5
     */
    public InnerClass2 getInnerClass2() {
        return new InnerClass2();
    }

    //私有内部类
    private class InnerClass2 {
        private int age = 80;

        public void print(int age) {
            System.out.println("形参age:" + age);
            System.out.println("外部类name:" + name);
            System.out.println("内部类age:" + this.age);
            /** Java虚拟机会在内部类里面自动维护一个外部类对象,通过OuterClass.this访问 */
            System.out.println("外部类age:" + OuterClass.this.age);
        }
    }
}

(2)普通内部类在jdk16之前不能定义静态变量,jdk16之后才行

(3)Java虚拟机会在内部类里面自动维护一个成员属性:外部类对象,通过OuterClass.this访问

(4)外部类访问内部类:

  • 4-1 外部类不能直接访问内部类普通成员属性。必须通过外部类的对象再创建一个内部类对象,最后通过这个内部类对象去访问其所属成员,也遵循各种权限修饰符控制:
    外部类名.内部类名 对象名 = new 外部类名().new 内部类名();
//外部类创建内部类对象
OuterClass.InnerClass innerClass = new OuterClass().new InnerClass();
//访问内部类正常属性方法
innerClass.print(10);
  • 4-2 外部类可以直接访问内部类静态成员属性,也遵循各种权限修饰符控制:外部类.内部类.静态属性名/方法名
//访问内部类静态属性
System.out.println(OuterClass.InnerClass.size);

(5)内部类访问外部类:

  • 5-1 普通内部类可以直接访问外部类的所有静态、非静态成员,包括私有(private)、默认(package-private)、受保护(protected)和公共(public)级别的成员变量和方法

2.静态内部类:

在这里插入图片描述

(1)示例代码:

public class OuterClass {
    private static int age = 100;
    private String name = "outer";

    public static void main(String[] args) {
        //外部类创建内部类对象
        OuterClass.InnerClass innerClass = new OuterClass.InnerClass();
        //访问内部类正常属性方法
        innerClass.print(10);
        
        //访问内部类静态属性
        System.out.println(OuterClass.InnerClass.size);
    }
    

    //公共内部类
    public static class InnerClass {
        static int size = 50;
        private int age = 90;

        public void print(int age) {
            System.out.println("形参age:" + age);
            System.out.println("内部类age:" + this.age);
            System.out.println("外部类age:" + OuterClass.age);
            OuterClass outerClass = new OuterClass();
            System.out.println("外部类name:" + outerClass.name);
        }
    }
}

(2)静态内部类里面可以存在静态、非静态成员

(3)外部类访问内部类:

  • 3-1 外部类可以直接访问内部类静态成员,也遵循各种权限修饰符控制:外部类.内部类.静态属性名/方法名
//访问内部类静态属性
System.out.println(OuterClass.InnerClass.size);
  • 3-2 外部类不可以直接访问内部类非静态成员,需要先创建静态内部类的对象,再通过这个对象去访问:
    外部类名.内部类名 对象名 = new 外部类名.内部类名();
//创建静态内部类对象示例:
OuterClass.InnerClass inner = new OuterClass.InnerClass();
inner.非静态成员

(4)内部类访问外部类:

  • 4-1 静态内部类只能直接访问外部类的静态成员

  • 4-2 静态内部类访问外部类的非静态属性,需要先创建外部类对象

  • 4-3 静态内部类可以访问外部类的所有成员,包括私有(private)、默认(package-private)、受保护(protected)和公共(public)级别的成员变量和方法,只不过得注意方式

3.局部内部类:几乎很少使用

在这里插入图片描述

(1)示例代码:

public class OuterClass {
    private static int age = 100;
    private String name = "outer";

    public static void main(String[] args) {
        new OuterClass().showOuter();
    }

    public void showOuter() {
        int a = 90;
        class innerClass {
            int b = 80;

            public void showInner() {
                int c = 70;
                System.out.println("局部内部类,方法局部变量c:" + c);
                System.out.println("局部内部类,成员变量b:" + b);
                System.out.println("外部类,方法局部变量a:" + a);
                System.out.println("外部类,成员变量age:" + age);
            }
        }
        
        innerClass innerClass = new innerClass();
        innerClass.showInner();
    }
}

4.匿名内部类:可以快速创建接口实现类对象,或者某个类的子类对象;需要重写原本的抽象方法

在这里插入图片描述

(1)示例代码:

import java.util.ArrayList;
import java.util.List;

public class AnonymousInnerClassExample {
    public static void main(String[] args) {
        // 使用匿名内部类实现Runnable接口
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Running in anonymous inner class");
            }
        });

        thread.start();

        // 或者使用匿名内部类继承自一个抽象类或具体类
        List<String> list = new ArrayList<String>() {{
            add("Item added by anonymous inner class");
        }};

        System.out.println(list.get(0));
    }
}

七·内部类与外部类的类加载联系:jvm遵循“懒加载”原则,能不加载就不加载

  1. 加载外部类,会触发静态内部类加载,但不会触发非静态内部类加载
  2. 若是触发内部类加载,会先去加载外部类
  3. 任何类都只会被JVM加载一次

八·内部类应用的开发场景:

1. 封装实现细节:

  • 当一个类的实现依赖于另一个类,且这个类只被外部类使用时,将该类设计为内部类可以隐藏实现细节,提高封装性。这有助于减少代码对外暴露的接口,降低耦合度。

2. 逻辑相关性:

  • 当几个类之间有较强的逻辑关联,并且希望将它们组织在一起时,可以使用内部类来表达这种关系。这样不仅可以保持代码结构清晰,还能方便地访问外部类的私有属性和方法。

3. 匿名内部类与函数式编程:

  • 在需要实现单次使用的、简洁的类实例时(例如事件监听器、回调函数等),可以使用匿名内部类或Lambda表达式简化代码编写。

4. 多重继承模拟:

  • 在Java中,由于不支持多继承,但可以通过实现多个接口解决部分问题。若需从多个抽象类派生,则可以创建一个内部类并继承这些抽象类,然后让外部类持有这个内部类的引用,间接实现类似多重继承的效果。

5. 线程和并发:

  • 内部类可用于实现线程类,尤其是当每个线程执行的任务与外部类的方法紧密相关时,通过定义Runnable或Callable的匿名内部类来启动新线程,使代码更紧凑。

6. 静态嵌套类(静态内部类):

  • 当某个类只是逻辑上属于另一个类,但实际上并不依赖于外部类的实例时,可将其设计为静态内部类。这样的类可以独立于外部类实例存在,并且可以包含静态成员,适合用来组织工具类或者枚举类等。

总之,选择使用内部类主要考虑的是代码组织、封装性以及逻辑关联性等因素,以提升代码质量和可维护性。

  • 24
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ideal-cs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值