Java内部类(成员,局部,匿名,静态,多重继承)

news2024/10/2 16:29:23

java内部类

    • 内部类的定义
    • 成员内部类
      • 特点
      • 测试代码
      • 运行结果
    • 静态内部类
      • 特点
      • 测试代码
      • 运行结果
    • 匿名内部类
      • 特点
      • 测试代码
      • 运行结果
    • 局部内部类
      • 特点
      • 测试代码
    • 内部类的嵌套
      • 特点
      • 测试代码
      • 运行结果

内部类的定义

Java 编程语言允许一个类被定义在另一个类中,这样的类就称为嵌套类。嵌套类分为两种:静态的和非静态的。没有用 static 关键字来声明的嵌套类,就称为非静态嵌套类。用 static 关键字来声明的嵌套类,就称为静态嵌套类。
包含嵌套类的类,可称为外围类(Enclosing Class)或外部类(Outer Class)。非静态嵌套类可访问其外围类的其他成员,即使这些成员被声明为私有的。 若内部类作为其外部类的成员,则它可声明为 private、public、protected 或包私有的。
内部类是类的第五大成员→类的五大成员是哪些?[属性、方法、构造器、代码块、内部类]】
内部类一般来说包括这四种:成员内部类、局部内部类、匿名内部类和静态内部类。

成员内部类

特点

成员内部类在一个类里面作为类的一个字段直接定义就可以了

public class OuterClass {

    public class InnerClass {
        
    }
}

成员内部类对象可以访问外部类对象中所有访问权限的字段,同时,外部类对象也可以通过成员内部类的对象引用来访问内部类中定义的所有访问权限的字段
成员内部类是依附外部类而存在的,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象。所以在外部类访问内部类的时候必须先实例化外部类对象
成员内部类可以使用四种权限修饰符进行修饰(四种权限修饰符:public(公有的) >protected(受保护的) > (default)(缺省/默认的) > private(私有的));
成员内部类中不能书写静态变量和方法。

测试代码

public class OutClass01 {
    public     String outerName1="outerName1";
    protected  String outerName2="outerName2";
               String outerName3="outerName3";
    private    String outerName4="outerName4";
    public OutClass01() {
        // 在外部类对象内部,直接通过 new InnerClass(); 创建内部类对象
        InnerClass01 innerObj = new InnerClass01();
        System.out.println("外部类的构造方法中创建 " + this.getClass().getSimpleName() + " 对象");
        System.out.println("其内部类的 innerName1 字段的值为: " + innerObj.innerName1);
        System.out.println("其内部类的 innerName2 字段的值为: " + innerObj.innerName2);
        System.out.println("其内部类的 innerName3 字段的值为: " + innerObj.innerName3);
        System.out.println("其内部类的 innerName4 字段的值为: " + innerObj.innerName4);
        System.out.println();
    }

    public class InnerClass01 {
        public String innerName1 = "innerName1";
        protected String innerName2 = "innerName2";
        String innerName3 = "innerName3";
        private String innerName4 = "innerName4";

        // Inner classes cannot have static declarations
        // 编译错误!成员内部类中不能定义 static 属性
        // static String innerName5 = "innerName5";

        public InnerClass01() {
            System.out.println("内部类的构造方法中创建 " + this.getClass().getSimpleName() + " 对象");
            System.out.println("外部类 outerName1 字段为: " + outerName1);
            System.out.println("外部类 outerName2 字段为: " + outerName2);
            System.out.println("外部类 outerName3 字段为: " + outerName3);
            System.out.println("外部类 outerName4 字段为: " + outerName4);
            System.out.println();
        }
    }

        public static void main(String[] args) {
            OutClass01 outerObj = new OutClass01();
            // 不在外部类内部,使用:外部类对象. new 内部类构造器(); 的方式创建内部类对象
            //InnerClass01 innerObj01 =outerObj.new InnerClass01();
        }
}

运行结果

在这里插入图片描述

静态内部类

特点

静态内部类是不需要依赖于外部类的,和类的静态成员属性有点类似
静态内部类中无法访问外部类的非静态成员,因为外部类的非静态成员是属于每一个外部类对象的,而本身静态内部类就是独立外部类对象存在。
外部类可以访问静态内部类对象的所有访问权限的成员,和成员内部类无异。
不能使用外部类的非static成员变量或者方法;
静态内部类中即能声明静态成员也可以声明非静态成员。

测试代码

public class Outclass02 {
    public static String outerName1 = "outerName1";
    protected static String outerName2 = "outerName2";
    static String outerName3 = "outerName3";
    private static String outerName4 = "outerName4";
    public  String outerName5 = "outerName5";

    public  Outclass02() {
        StaticClass innerObj=new StaticClass();
        System.out.println("外部类的构造方法中创建 " + this.getClass().getSimpleName() + " 对象");
        System.out.println("其内部类的 innerName1 字段的值为: " + innerObj.innerName1);
        System.out.println("其内部类的 innerName2 字段的值为: " + innerObj.innerName2);
        System.out.println("其内部类的 innerName3 字段的值为: " + innerObj.innerName3);
        System.out.println("其内部类的 innerName4 字段的值为: " + innerObj.innerName4);
        System.out.println();
    }


    public static void show(){
        System.out.println("这是外部类的show方法");
    }

    public static class StaticClass {
        public String innerName1 = "innerName1";
        protected static String innerName2 = "innerName2";
        String innerName3 = "innerName3";
        private static String innerName4 = "innerName4";

        public StaticClass() {
            System.out.println("内部类的构造方法中创建 " + this.getClass().getSimpleName() + " 对象");
            //静态内部类能访问外部类的静态成员以及方法
            System.out.println("外部类 outerName1 字段为: " + outerName1);
            System.out.println("外部类 outerName2 字段为: " + outerName2);
            System.out.println("外部类 outerName3 字段为: " + outerName3);
            System.out.println("外部类 outerName4 字段为: " + outerName4);
            //静态内部类不能访问外部类的非静态成员
            //System.out.println("外部类 outerName5 字段为: " + outerName5);
            Outclass02.show();
            System.out.println();
        }
    }

    public static void main(String[] args) {
        Outclass02 outclass02=new Outclass02();
        //不需要依赖外部类
        System.out.println("不需要外部类直接在main创建静态内部类对象");
        StaticClass innerObj=new StaticClass();
    }
}

运行结果

在这里插入图片描述

匿名内部类

特点

匿名内部类有多种形式,其中最常见的一种形式莫过于在方法参数中新建一个接口对象 / 类对象,并且实现这个接口声明 并重写接口声明的方法,然后再创建一个这个匿名内部类的对象并赋值给前面的 Function01 类型的引用(见代码)。
外部类不能使用匿名内部类定义的属性,匿名内部类可以使用外部类的属性,因为外部类无法获取这个类的类名,无法得到属性信息。
匿名内部类不能定义任何静态成员、方法和类,只能创建匿名内部类的一个实例。一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
匿名内部类可用于给方法传递实参首先有一个接口,然后在使用的类中编写了一个方法,其参数类型是接口对象。调用此方法时构造一个接口对象传入,此时会自动生成一个此接口的子类(匿名内部类)实现接口中的方法。本质传入的类是匿名内部类。

测试代码

// 实现关系下的匿名内部类:
interface Function01 {
    void show();
}
interface Function02 {
    void call();
}
 class A {
     public     String outerName1="outerName1";
     protected  String outerName2="outerName2";
     String     outerName3="outerName3";
     private    String outerName4="outerName4";

    public void InnerFun01(){
        // 在这个过程中会新建一个匿名内部类对象,
        // 这个匿名内部类实现了 Function01 接口并重写 show 方法
        Function01 fun= new Function01(){
            // 内部类中定义属性,只能在当前内部类中使用,
            // 无法在外部类中使用,外部类获取不到匿名内部类的类名,
            // 无法创建匿名内部类的对象

            //出错  原因:内部类不能有静态声明
            //public static  String innerName2 = "innerName2";
            public String innerName1 = "innerName1";
            //实现子类 但是没有名字 所以叫匿名内部类
            @Override
            public void show() {
                //在匿名内部类中可以使用外部类的属性
                //无法获得对象因为是匿名内部类没有名字
                System.out.println("内部类的构造方法中创建 " + this.getClass().getSimpleName() + " 对象");
                System.out.println("外部类 outerName1 字段为: " + outerName1);
                System.out.println("外部类 outerName2 字段为: " + outerName2);
                System.out.println("外部类 outerName3 字段为: " + outerName3);
                System.out.println("外部类 outerName4 字段为: " + outerName4);
                System.out.println("这是一个show接口方法...");
            }
        };

      fun.show();
    }
     //匿名内部类可用于给方法传递实参
    public void InnerFun02(Function02 fun){
        System.out.println();
        System.out.println("匿名内部类可用于给方法传递实参");
         fun.call();
    }
}

public class Outclass03 {
    public static void main(String[] args) {
        A a = new A();
        a.InnerFun01();
        a.InnerFun02(new Function02() {
            @Override
            public void call() {
                System.out.println("这是一个call方法");
            }
        });
    }
}

运行结果

在这里插入图片描述

局部内部类

特点

局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。
局部内部类不可使用权限修饰符 静态(static)修饰符进行修饰 同局部变量相同。
局部内部类可以直接访问方法中的属性。
局部内部类使用较少其声明在一个方法体 / 一段代码块的内部,若不在定义类的定义域之内便无法使用。
局部内部类里可访问外部类对象的所有访问权限的字段,外部类却不能访问局部内部类中定义的字段,因为局部内部类的定义只在其特定的方法体 / 代码块中有效,出了定义域,定义就失效了。

测试代码

public class OutClass04 {

    public     String outerName1="outerName1";
    protected  String outerName2="outerName2";
    String outerName3="outerName3";
    private    String outerName4="outerName4";

    public OutClass04() {
        System.out.println("创建了 " + this.getClass().getSimpleName() + " 对象");
    }

    private void InnerClassTest() {
        // 局部内部类 InnerClass01,只能在当前方法中使用
        class InnerClass01 {
            //Inner classes cannot have static declarations
            // 编译错误!局部内部类中不能定义 static 字段
            //private static String innerName4 = "innerName4";
            public String innerName1 = "innerName1";
            public InnerClass01() {
                System.out.println("InnerClass01内部类的构造方法中创建 " + this.getClass().getSimpleName() + " 对象");
                System.out.println("外部类 outerName1 字段为: " + outerName1);
                System.out.println("外部类 outerName2 字段为: " + outerName2);
                System.out.println("外部类 outerName3 字段为: " + outerName3);
                System.out.println("外部类 outerName4 字段为: " + outerName4);
                System.out.println();
            }
        }
        InnerClass01 inner01 = new InnerClass01();

     // InnerClass02 inner03 = new InnerClass02(); // 编译错误!不在类 InnerClass02 的定义域内,找不到类 InnerClass02,
        if (true) {
            // 局部内部类 InnerClass02,只能在当前代码块中使用
            class InnerClass02 {
                public InnerClass02() {
                    System.out.println("InnerClass02内部类的构造方法中创建 " + this.getClass().getSimpleName() + " 对象");
                    System.out.println("外部类 outerName1 字段为: " + outerName1);
                    System.out.println("外部类 outerName2 字段为: " + outerName2);
                    System.out.println("外部类 outerName3 字段为: " + outerName3);
                    System.out.println("外部类 outerName4 字段为: " + outerName4);
                    System.out.println();
                }
            }
            InnerClass02 inner02 = new InnerClass02();
        }
    }

    public static void main(String[] args) {
        OutClass04 outObj = new OutClass04();
        outObj.InnerClassTest();
    }
}

运行结果
在这里插入图片描述

内部类的嵌套

特点

内部类的嵌套,即为内部类中再定义内部类,类只能实现单个的类继承,而使用内部类的嵌套,在一个外部类中不同的内部类可以继承不同的类,从而相当于一个类实现了多重继承。以下代码是使用普通内部类进行演示。

测试代码

class Father {
    public String str1(){
        return "我是爸爸类";
    }
}
class Mother {
    public String str2(){
        return "我是妈妈类";
    }
}
class Son {
    //普通内部类Father_1继承Father
    class Father_1 extends Father{
        public String str1(){
            //调用父类的方法并加上一个字符串
            return super.str1() + 888;
        }
    }
    //普通内部类Mother_1继承Mother
    class Mother_1 extends  Mother{
        public String str2(){
            //调用父类的方法并加上一个字符串
            return super.str2() +999;
        }
    }
    public String getstr1(){
        return new Father_1().str1();
    }
    public String getstr2(){
        return new Mother_1().str2();
    }
}
public class OutClass05 {

    public static void main(String[] args) {
        Son son = new Son();
        System.out.println( son.getstr1());
        System.out.println( son.getstr2());
    }
}


运行结果

在这里插入图片描述

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

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

相关文章

【第43天】sort 的复杂运用 | 对二维数组与结构体实现自定义排序

本文已收录于专栏🌸《Java入门一百练》🌸学习指引序、专栏前言一、二维排序二、【例题1】1、题目描述2、解题思路3、模板代码4、代码解析三、【例题2】1、题目描述2、解题思路3.模板代码4.代码解析四、推荐专栏五、课后习题序、专栏前言 本专栏开启&…

【ESP 保姆级教程】疯狂毕设篇 —— 案例:基于ESP8266和EMQX的教室灯光控制系统

忘记过去,超越自己 ❤️ 博客主页 单片机菜鸟哥,一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2023-02-26 ❤️❤️ 本篇更新记录 2022-02-26 ❤️🎉 欢迎关注 🔎点赞 👍收藏 ⭐️留言📝🙏 此博客均由博主单独编写,不存在任何商业团队运营,如发现错误,请…

二、mysql索引分析之二

二、mysql索引分析之一 二、mysql索引分析之二 二、mysql索引分析之二1 mysql的索引类型2 Explain执行计划2.1 执行计划之 id 属性2.1.1 id 的属性相同表示加载表的顺序是从上到下2.1.2 id 值越大,优先级越高2.1.3 id 有相同,也有不同,同时存…

【GO】k8s 管理系统项目22[前端部分–工作负载-Deployment]

k8s 管理系统项目[前端部分–工作负载-Deployment] 1. Deployment页面设计 src/layout/Layout.vue 功能 列表详情新增更新删除重启副本数 Main的布局 2. 连接配置 src/views/common/Config.js export default {//后端接口路径loginAuth: http://localhost:9091/api/login,…

RCEE: Event Extraction as Machine Reading Comprehension 论文解读

RCEE: Event Extraction as Machine Reading Comprehension 论文:Event Extraction as Machine Reading Comprehension (aclanthology.org) 代码:jianliu-ml/EEasMRC (github.com) 期刊/会议:EMNLP 2020 摘要 事件提取(Event extraction,…

Slurm集群调度策略详解(2)-回填调度

1. slurm集群调度系统简介 作业调度系统其实就是指按一定策略把并行程序的各子任务或者是面向多用户的一组作业按一定的选择策略使之与各计算节点的空闲资源相对应,让其在对应的资源上运行,所以作业调度系统是联系上层应用和下层资源的中枢。一个集群资…

纯x86汇编实现的多线程操作系统实践 - 第六章 AP1的用户进程

AP1用户进程的代码为task1.asm。该用户进程将调用0x80系统中断在界面上显示一张BMP格式的图片。用户进程还使用了彩色转灰色技术,轮流显示该图片的彩色和灰色图。代码解释如下:调用0x39号系统中断,从300号扇区获得一个扇区的数据(…

【华为OD机试模拟题】用 C++ 实现 - 身高排序(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 去重求和(2023.Q1) 文章目录 最近更新的博客使用说明身高排序题目输入输出示例一输入输出Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查看地址:ht…

每日学术速递2.27

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.CL 1.FiTs: Fine-grained Two-stage Training for Knowledge-aware Question Answering 标题:FiTs:用于知识感知问答的细粒度两阶段训练 作者:Qichen…

JavaWeb JavaBean,MVC三层架构

9、JavaBean 实体类 JavaBean有特定的写法: 必须要有一个无参构造属性必须私有化必须有对应的get/set方法; 一般用来和数据库的字段做映射 ORM; ORM :对象关系映射 表—>类字段–>属性行记录---->对象 people表 …

Qt 小项目 图片浏览系统

引言 本系统支持,自动播放,左右拖动切换,点击列表切换,点击按钮切换;是一个标准的图像浏览软件。 Windows 图片浏览器,可以查看当前文件夹下的图片,往上翻、往下翻并且自动播放; …

这只乌龟,当然离不开函数了!

什么是函数?函数就是执行特定任务和以完成特定功能的一段代码为什么需要函数?复用代码隐藏实现细节提高可维护性提高可读性便于调试函数的创建def 函数名 ([输入参数]) :函数体[return xxx]函数名需要遵循字母、数字、下划线# 这里的a,b是形式…

03 流程控制

3.1 条件判断3.2 循环控制3.3 中断循环 3.1 条件判断 if 条件判断 :单分支(if)、双分支(if…else…)、多分支(if … else if … else)Switch(Scala并没有 switch,用的是…

2023年鞋服配饰行业如何玩转全域经营?

2023年,鞋服配饰行业私域已进入深水区,这就对私域运营提出了更高的挑战和目标,企业纷纷发力以私域为基石、以消费者为核心的全域经营。 不过,虽然鞋服配饰行业私域起步早,玩法多。但在迈向全域经营的过程中&#xff0…

全网详细介绍nginx的反向代理、正向代理配置,location的指令说明,反向代理的两个示例代码以及全局块,events块和http快的说明。

文章目录1. 文章引言2. 何谓反向代理3. 解析nginx的配置文件3.1 全局块(global block)3.2 events块(events block)3.3 http块(http block)4. 如何配置反向代理4.1 反向代理示例14.2 反向代理示例25. 补充说明5.1 location指令说明5.2 nginx完整配置文件1. 文章引言 如果你的服务…

聚合效度全流程

聚合效度分析流程如下: 一、聚合效度定义 聚合效度(convergent validity),又称收敛效度,是指测量同一变量的测量项会落在同一因子上,强调本应该在同一因子下的测量项,确实在同一因子下。即一个…

基于nodejs+vue地方特色的风景文化宣传网站vscode

管理员可以根据系统给定的账号进行登录,登录后可以进入木里风景文化管理平台对木里风景文化所有模块进行管理。包括查看和修改自己的个人信息以及登录密码。 该系统为每一个用户都分配了一个用户账号,用户通过账号的登录可以在系统中查看木里风景文化信息…

怎么依靠网络赚钱,网上可以做什么副业

如今,网上赚钱已经成为许多人职业生涯的选择之一。网上有很多可靠的兼职,让你在家里轻松赚钱。今天给大家推荐五份可靠的网上兼职。一、怎样选择可靠的网络兼职可靠的网络兼职一般是指在家通过网络平台完成兼职任务,完成任务后即可获得报酬。…

JVM中TLAB(Thread Local Allocation Buffer)+逃逸分析

1、为什么有TLAB(Thread Local Allocation Buffer)堆区是线程共享区域,任何线程都可以访问到堆区中的共享数据 由于对象实例的创建在JVM中非常频繁,因此在并发环境下从堆区中划分内存空间是线程不安全的 为避免多个线程操作同一地…

java地图导出——添加经纬线

概述 前面的文章Node实现切片的拼接和地图的导出和Java实现地图的导出分别讲述可如何在node和java中实现切片的拼接以及地图的导出。本文,书接前文,实现java导出时经纬度的添加。 实现后效果 实现 完整的实现思路流程如下图: 1. 根据切片…