详解Java的内部类

news2024/9/19 10:36:01

一、基本介绍

        一个类的内部又完整的嵌套了另一个类结构。被嵌套的类称为内部类(inner class)嵌套其他类的类称为外部类(outer class)。它是我们类的第五大成员,内部类最大的特点就是可以直接访问私有属性,并且可以体现类与类之间的包含关系。

二、内部类的分类 

2.1 定义在外部类局部位置上(比如方法内):

①局部内部类(有类名)

②匿名内部类(没有类名,重点)

2.2 定义在外部类的成员位置上:

①成员内部类(没用static修饰)

②静态内部类(使用static修饰)

三、内部类的使用细节

3.1 局部内部类

1.局部内部类是定义在外部类的局部位置,比如方法中或者代码块中,并且有类名。

class OuterClass {
    private int n1 = 10;

    public void m1() {
        class InnerClass {
                   //内部类
        }
    }
}

2.可以直接访问外部类的所有成员,包含外部类私有的成员

class OuterClass {
    private int n1 = 10;

    public void m1() {
        class InnerClass {
                   //内部类
            public void f1(){
                System.out.println("n1="+n1);
            }
        }
    }
}

3.不能添加访问修饰符,因为它的地位就是一个局部变量。局部变量是不能使用修饰符的。但是可以使用final 修饰(这样就不可被继承),因为局部变量也可以使用final

class OuterClass {
    private int n1 = 10;

    public void m1() {
        class InnerClass {
                   //内部类
            public void f1(){
                System.out.println("n1="+n1);
            }
        }
        
        class InnerClass1 extends InnerClass{
            //继承上面的内部类
        }
    }
}

4.作用域:仅仅在定义它的方法或代码块中

5.局部内部类可以访问外部类的成员

6.外部类访问局部内部类的成员,访问方式:  创建对象,再访问(注意:必须在作用域[所定义内部类的方法中]内)

7.如果外部类和局部内部类的成员重名,那么调用遵循就近原则(即先找局部内部类的成员),如果想访问外部类的成员变量,则需使用 

外部类名.this.成员

           //很好理解,我们可以解读为,外部类的对象的成员

 3.2 匿名内部类

匿名内部类是定义在外部类的局部位置,比如方法中或者代码块中,并且没有类名;

匿名内部类的使用是为了简化开发

①基于接口的匿名内部类

假如:我们有一个需求,“使用IA接口,并创建对象使用其方法”

按照传统方法:我们需要①编写实现类实现接口的方法②new实现类的实例

public class AnonymousInnerClass {
    public static void main(String[] args) {
        Animal animal = new Animal();
        animal.eat();
    }
}

interface IA {
    void eat();
}

class Animal implements IA {
    @Override
    public void eat() {
        System.out.println("动物吃饭");
    }
}

现在,有了匿名内部类,我们就可以这样实现:

public class AnonymousInnerClass {
    public static void main(String[] args) {
        IA animal = new IA() {
            @Override
            public void eat() {
                System.out.println("动物吃饭");
            }
        };
        animal.eat();
    }
}

interface IA {
    void eat();
}

说是匿名,其实是有名字的,在底层,系统给它起了名字,底层实现类似(大概模拟)这样:

class XXXX implements IA {
    @Override
    public void eat() {
        System.out.println("动物吃饭");
    }
}

类名是由系统起的,我们可以通过.getClass( )方法获取其运行时类型,编译类型当然是IA这不用说。

注意:匿名内部类只能使用一次,也就是只能new一个实例对象,这不代表其引用就能用一次。匿名内部类需要把接口的抽象方法都实现。

②基于普通类的匿名内部类
public class AnonymousInnerClass {
    public static void main(String[] args) {
        Animal animal = new Animal("老虎") {
            @Override
            void eat() {
                System.out.println(this.name+"要吃肉");
            }
        };
        System.out.println(animal.getClass());
        animal.eat();
    }
}

class Animal {
     String name;
    void eat() {
        System.out.println(this.name + "要吃饭");
    }
    public Animal(String name) {
        this.name = name;
    }
}

底层实现(大概模拟)

class XXXX extends Animal{

@Override
void eat() {
    System.out.println(this.name+"要吃肉");
    }
}

我们可以通过.getClass( )方法获取其运行时类型

③基于抽象类的匿名内部类
public class AnonymousInnerClass {
    public static void main(String[] args) {
        Animal animal = new Animal("老虎") {
            @Override
            void eat() {
                System.out.println(this.name + "吃肉");
            }
        };
        System.out.println(animal.getClass());
        animal.eat();
    }
}

abstract class Animal {
    String name;

    abstract void eat();

    void shout() {
        System.out.println("动物大叫");
    }

    public Animal(String name) {
        this.name = name;
    }
}

必须把抽象类中的抽象方法都实现。

这里补充说明一下,父类的私有属性可以被子类继承,但是子类无法使用;父类的构造方法,子类无法继承,但是子类创建对象会先调用父类的构造方法(默认是无参构造方法),以上案例匿名内部类应该是调用了父类的有参构造方法。

3.3 成员内部类

成员内部类定义在外部类的成员位置,并且没有static修饰。

可以添加任意访问修饰符(public、protected、默认、private),因为它的地位是一个成员。

1.成员内部类可访问外部类所有成员,包括私有的

 使用内部类方法一

public class ChengYuan {
    public static void main(String[] args) {
        OuterClass outerClass = new OuterClass();
        outerClass.shiYong();
    }
}

class OuterClass {
    int n = 10;

    public void eat() {
        System.out.println("吃顿饭");
    }

    class innerClass {
        public void f1() {
            System.out.println(n);
            eat();
        }
    }

    public void shiYong() {
        innerClass innerClass = new innerClass();
        innerClass.f1();
    }
}

使用内部类方法二

        OuterClass.innerClass innerClass = outerClass.new innerClass();
        innerClass.f1();

使用内部类方法三

外部类写方法,返回内部类对象

    public InnerClass shiYong1(){
        return new InnerClass();
    }

3.4 静态内部类

静态内部类是定义在外部类的成员位置,并且有static修饰

可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员

可以添加任意访问修饰符(public、protected、默认、private),因为它的地位就是一个成员。

作用域:同其他的成员,为整个类体

静态内部类可通过类名直接访问

public class ChengYuan {
    public static void main(String[] args) {
        OuterClass.InnerClass innerClass = new OuterClass.InnerClass();
        innerClass.f1();
    }
}

class OuterClass {
    static int n = 10;

    static class InnerClass {
        public void f1() {
            System.out.println(n);
        }
    }
}

如果外部类和静态内部类的成员重名时,静态内部类访问的时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.成员)去访问。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1911993.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解决本地操作云服务器上的Redis

方案一:开放Redis默认端口,本地通过公网IP端口号的形式访问。 方案二:每次将本地编写好的Java代码打包,放在云服务器上运行。 方案三:配置ssh端口转发,把云服务器的redis端口,映射到本地主机。 …

UI设计入门到精通:规范整理与应用技巧

很多刚入行的UI设计师在遇到一些不熟悉的词时会充满问号,往往会纠结用什么尺寸最合适。设计师在设计UI的时候不一定要严格遵守设计规范,但是要了解规范,整合,灵活处理。为了解决新手的“十万个为什么”,本文将带你了解…

idea集成本地tomcat

由于网课老师使用的是eclipse,但是……本人用的是idea,所以不得不去找教程。 解决方案1: https://blog.csdn.net/weixin_54048131/article/details/131359793 这个地方,路径一定要到这个tomcat 否则不识别: 这里的JRE也要配置一下 新问题&…

Debezium报错处理系列之第114篇:No TableMapEventData has been found for table id:256.

Debezium报错处理系列之第114篇:Caused by: com.github.shyiko.mysql.binlog.event.deserialization.MissingTableMapEventException: No TableMapEventData has been found for table id:256. Usually that means that you have started reading binary log within the logic…

Qt开发 | Qt绘图技术 | 常见图像绘制 | Qt移动鼠标绘制任意形状 | Qt绘制带三角形箭头的窗口

文章目录 一、基本绘图技术介绍二、常见的18种图形、路径、文字、图片绘制三、Qt移动鼠标绘制任意形状四、Qt绘制带三角形箭头的窗口 一、基本绘图技术介绍 Qt提供了绘图技术,程序员可以在界面上拖动鼠标,或者在代码里指定参数进行绘图。 Qt绘图技术介绍…

tableau饼图与环形图绘制 - 5

饼图与环形图绘制 1. 饼图绘制1.1 饼图绘制1.2 显示标签1.3 显示合计百分比1.4 设置百分比格式1.5 添加说明1.6 图像导出 2. 环形图绘制2.1 选择标记为饼图2.1 饼图绘制2.2 双饼图绘制2.3 设置大饼图大小2.4 设置双轴2.5 设置小饼图属性 1. 饼图绘制 酒店价格等级饼图 1.1 饼…

初识数组(二)

目录 1. 二维数组的初始化 1) 不完全初始化 2) 完全初始化 3) 按照行初始化 4) 初始化时省略行,但是不能省略列 2.二维数组的使用 1) 二维数组的下标 2)二维数组的输入和输出 3. 二维数…

Python实现吃豆人游戏详解(内附完整代码)

一、吃豆人游戏背景 吃豆人是一款由Namco公司在1980年推出的经典街机游戏。游戏的主角是一个黄色的小圆点,它必须在迷宫中吃掉所有的点数,同时避免被四处游荡的幽灵捉到。如果玩家能够吃掉所有的点数,并且成功避开幽灵,就可以进入…

小试牛刀--对称矩阵压缩存储

学习贺利坚老师对称矩阵压缩存储 数据结构实践——压缩存储的对称矩阵的运算_计算压缩存储对称矩阵 a 与向量 b 的乘积-CSDN博客 本人解析博客 矩阵存储和特殊矩阵的压缩存储_n阶对称矩阵压缩-CSDN博客 版本更新日志 V1.0: 对老师代码进行模仿 , 我进行名字优化, 思路代码注释 …

VMware Workstation 和 Fusion 现对个人用户宣布免费使用

这周笔记本坏了,重装了系统,部分软件也得重装,其中就有 VMware Workstation, 当我还在上网苦苦找破解包时(个人学习使用),发现现在居然免费了…… 原来 VMware 换了新东家,简单回顾下…

DMA方式的知识点笔记

苏泽 “弃工从研”的路上很孤独,于是我记下了些许笔记相伴,希望能够帮助到大家 目录 1. DMA基本概念 2. DMA传送过程 易错点 DMA控制器操作流程 3. DMA传送方式 这是单总线的结果 (CPU说了算 所以不会产生于CPU的冲突) 这…

谷歌摸鱼神器来了:推出AI会议替身,一键总结提问发言_会议预约 ai对话

饱受会议折磨的打工人,终于可以解放了! 就在刚刚举办的Google Cloud Next’23大会上,谷歌宣布了一系列科技新进展,最瞩目的要属其中的“开会AI替身”了。 只需要一句“帮我参加”,AI就能替你开会,并在合适…

SCI二区TOP|蜘蛛黄蜂优化算法(SWO)原理及实现【免费获取Matlab代码】

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献5.代码获取 1.背景 2023年,M Abdel-Basset受到蜘蛛黄蜂优化社会行为启发,提出了蜘蛛黄蜂优化算法(Spider Wasp Optimizer, SWO)。 2.算法原理 2.1算法思想 S…

python04——类(基础new)

类其实也是一种封装的思想,类就是把变量、方法等封装在一起,然后可以通过不同的实例化对其进行调用操作。 1.类的定义 class 类名: 变量a def __init__ (self,参数2,参数2...):初始化函数!!&…

【LeetCode】生命游戏

目录 一、题目二、解法完整代码 一、题目 根据 百度百科 , 生命游戏 ,简称为 生命 ,是英国数学家约翰何顿康威在 1970 年发明的细胞自动机。 给定一个包含 m n 个格子的面板,每一个格子都可以看成是一个细胞。每个细胞都具有一…

Qt 音频编程实战项目

一Qt 音频基础知识 QT multimediaQMediaPlayer 类:媒体播放器,主要用于播放歌曲、网络收音 机等功能。QMediaPlaylist 类:专用于播放媒体内容的列表。 二 音频项目实战程序 //版本5.12.8 .proQT core gui QT multimedia greate…

C++入门基础(2)

目录 一、引用: 1、定义: 2、特性: 3、引用的使用: 4、const引用:控制权限 const引用定义: const引用可以接收3种对象: 1、正常对象: 2、临时对象: 3、const对象: 总结&…

Sorted Set 类型命令(命令语法、操作演示、命令返回值、时间复杂度、注意事项)

Sorted Set 类型 文章目录 Sorted Set 类型zadd 命令zrange 命令zcard 命令zcount 命令zrevrange 命令zrangebyscore 命令zpopmax 命令bzpopmax 命令zpopmin 命令bzpopmin 命令zrank 命令zscore 命令zrem 命令zremrangebyrank 命令zremrangebyscore 命令zincrby 命令zinterstor…

vue子组件调用父组件方法

父组件 页面<popoverss ref"pop" :goodspop"goodspop"></popoverss>子组件components: {"popoverss": () > import(../comm/popover.vue)},方法goodspop(e){console.log(e"----")return 9999;},子组件 方法props:[go…

【转载】目标检测mAP的含义

转载自三叔家的猫 https://blog.csdn.net/qq_39056987 https://blog.csdn.net/qq_39056987/article/details/104348493 <div id"content_views" class"markdown_views prism-atom-one-light"><svg xmlns"http://www.w3.org/2000/svg" s…