进阶JAVA篇-深入了解内部类

news2024/11/19 21:24:54

目录

                一.内部类概述:

                二.内部类可以分为四种:

        2.1成员内部类

        2.1.1如何编写一个成员内部类呢?

       2.1.2该如何创建内部类的对象?          

        2.1.3在内部类中该如何访问外部类中的成员呢?

        2.2静态内部类

        2.2.1如何来创建静态内部类?

         2.3局部内部类

        2.4匿名内部类(重点)

        2.4.1如何定义匿名内部类?

        2.4.2匿名内部类的特点包括:

        2.4.3对匿名内部类进行小结: 


                一.内部类概述:

        是类的五大成分之一(成员变量,成员方法,构造器,内部类,代码块),如果在一个类内部定义一个类,这就是内部类。当一个类的内部,包含完整的事务,而这个事务又没有必要单独设计,就可以在内部定义一个类。比如,内部类是车的发动机,外部类是一整辆车,发动机可以在车的内部是一个完整的事务,但又没有必要单独设计出来。

                二.内部类可以分为四种:

        2.1成员内部类

        2.1.1如何编写一个成员内部类呢?

代码如下:

public class InnerClass {
    public static void main(String[] args) {

    }
}
//外部类
class Outer{
    //内部类
    public class Inner{
    }
}

        成员内部类我们就可以直接简单的理解为是类中的成员的一种,类似成员变量,成员方法一样。

       2.1.2该如何创建内部类的对象?

代码如下:

public class InnerClass {
    public static void main(String[] args) {

        Outer outer = new Outer();
        outer.fun();

        Outer.Inner inner = new Outer().new Inner();
        inner.fun();
    }
}
//外部类
class Outer{

    public void fun(){
        System.out.println("调用外部类的方法");
    }

    //内部类
    public class Inner{

        public void fun(){
            System.out.println("调用内部类的方法");
        }
    }
}
        跟创建一个类的对象一样,内部类的类型需要由外部类.内部类完成的,因为内部类是外部类的一个成员嘛,所以外部类访问成员需要用.这个符号来引出成员,再到内部类的引用创建,先要new一个外部类的引用,再紧接着new一个内部类的引用。大概理解就行,这些语法多用就会了。
        再解释一下以上代码,创建了一个是外部对象,还有一个内部对象,然后分别取访问了fun方法。各自访问自己的方法是没有问题的。
打印结果如下:

        


        
 

        2.1.3在内部类中该如何访问外部类中的成员呢?

        在内部类中去访问外部类的成员就像类中的方法如何取访问的方式是一样的,直接去访问就行了。

代码如下:

public class InnerClass {
    public static void main(String[] args) {
        Outer.Inner inner = new Outer().new Inner();
        inner.fun();
    }
}
//外部类
class Outer{
    public String name = "lisi";

    public void fun(){
        System.out.println("调用外部类的方法");
    }

    //内部类
    public class Inner{
        public void fun(){
            System.out.println(name);
            System.out.println("调用内部类的方法");
        }
    }
}

        如果在内部类中的成员变量与外部类的成员变量的名字一样的时候,内部类去输出这个变量那肯定是优先内部类的变量的值,因为就近原则嘛.

代码如下:

public class InnerClass {
    public static void main(String[] args) {
        Outer.Inner inner = new Outer().new Inner();
        inner.fun();
    }
}
//外部类
class Outer{
    public int age = 11;

    public void fun(){
        System.out.println("调用外部类的方法");
    }

    //内部类
    public class Inner{
        public int age = 14;
        public void fun(){
            System.out.println(age);
            System.out.println("调用内部类的方法");
        }
    }
}

运行结果如下:

        

        如果非得在这种情况下,访问外部类的成员变量呢?就可以在前面加上外部类名字.this.该变量名就可以访问到外部类的成员变量了。

代码如下:

public class InnerClass {
    public static void main(String[] args) {
        Outer.Inner inner = new Outer().new Inner();
        inner.fun();
    }
}
//外部类
class Outer{
    public int age = 11;

    public void fun(){
        System.out.println("调用外部类的方法");
    }

    //内部类
    public class Inner{
        public int age = 14;
        public void fun(){
            System.out.println(Outer.this.age);
            System.out.println("调用内部类的方法");
        }
    }
}

运行结果:

        

        同理成员方法道理也是一样的,如果内外类都没有相同名称的方法的前提下,就直接可以在内部类去调用外部类的方法。

代码如下:        

public class InnerClass {
    public static void main(String[] args) {
        Outer.Inner inner = new Outer().new Inner();
        inner.fun();
    }
}
//外部类
class Outer{
    public int age = 11;

    public void fun1(){
        System.out.println("调用外部类的方法");
    }

    //内部类
    public class Inner{
        public int age = 14;
        public void fun(){
            System.out.println(Outer.this.age);
            fun1();
            System.out.println("调用内部类的方法");
        }
    }
}

        如果内外类都有相同名称的方法的前提下,就可以在内部类用外部类名称.this.方法名,去调用外部类的方法。

代码如下:

public class InnerClass {
    public static void main(String[] args) {
        Outer.Inner inner = new Outer().new Inner();
        inner.fun();
    }
}
//外部类
class Outer{
    public int age = 11;

    public void fun(){
        System.out.println("调用外部类的方法");
    }

    //内部类
    public class Inner{
        public int age = 14;
        public void fun(){
            System.out.println(Outer.this.age);
            Outer.this.fun();
            System.out.println("调用内部类的方法");
        }
    }
}

运行结果如下:

        

        

        2.2静态内部类

        在成员内部类的类名前面加上static修饰,静态内部类可以理解成静态方法,属于类的内部类,在计算机中只有一份,是公开的,共享的。可以直接访问外部类中的静态成员变量、静态方法。

        2.2.1如何来创建静态内部类?

代码如下:

public class InnerClass {
    public static void main(String[] args) {
        Outer.Inner inner = new Outer.Inner();
        inner.fun();
    }
}
class Outer{
    public int age = 11;
    public static String name = "lisi";
    public static void fun1(){
        System.out.println("调用外部类的方法");
    }
    //内部类
    static public class Inner{
        public int age = 14;
        public void fun(){
            System.out.println(name);
            fun1();
            System.out.println("调用内部类的方法");
        }
    }
}

以上代码的运行结果:

         

        由于是静态的内部类,就可以直接用类来直接访问了,不用再像成员内部类一样了,用外部对象去调用内部对象了,我们可以这样来理解,静态内部类属于外部类的,外部类.静态内部类 名称 = new(直接可以new了)外部类.静态内部类;

                在静态内部类中可以直接去访问静态成员、静态方法,不能去访问实例成员变量、实例成员方法,还有我们在介绍成员内部类是可以访问在内部类与外部类出项相同名称的成员方法或者成员变量,通过外部类.this. 去访问外部类的成员,这没有问题。但是在静态内部类中根本不存在通过外部类.this. 去访问外部类的成员,想想嘛,内部类这是直接由类去访问的,没有通过创建实例对象去访问。

         2.3局部内部类

        对于这个局部内部类简单了解就好了,局部内部类在定义在方法中、代码块中、构造器中等执行体中。

代码如下:     

public class InnerClass {
    public static void main(String[] args) {
        class A{
            public void fun(){
                System.out.println("局部内部类");
            }
        }
        A a  = new A();
        a.fun();
    }

代码如下:

         

                这个局部内部类看看就好,这个用得不多,就不多详解了。

        2.4匿名内部类(重点)

        2.4.1如何定义匿名内部类?

        为了更好的了解这个匿名内部类,在介绍匿名内部类之前,先设定一个情景,先定义一个接口Animal,有一个run()方法,再定义两个子类Dog,Cat分别重写接口的run方法,再用一个函数输出这两个重写的方法。

具体代码如下:    

package AnonymousInnerClasses;

public class Text {
    public static void main(String[] args) {
        Animal animal1 = new Dog();
        go(animal1);

        Animal animal2 = new Cat();
        go(animal2);
    }
    public static void go(Animal animal){
        animal.run();
    }
}

        其实类似这段代码,我们并不陌生了吧,这段代码完完全全解释了多态的特性。我们是创建了两个对象,再把这两个对象被接口引用。接下来,介绍一下匿名内部类这个作用就是对以上代码的简化。特别是在需要实现某个接口或继承某个父类的情况下,可以直接在创建对象的地方实现相关的方法,避免了显式定义一个新的类。

        通过new 接口名或者父类名 (){重写方法 } 方式来创建了一个类,且new了一个子类出来,用接口名或者父类名 自定义名字 = new 接口名或者父类名 (){重写方法 } 。总结,new 接口名或者父类名 (){重写方法 } 方式 一共干了两件事,一.创建了子类。二.new了一个子类的对象。

运用匿名内部类简化以上代码:

package AnonymousInnerClasses;

public class Text {
    public static void main(String[] args) {
        Animal animal1 = new Animal() {
            @Override
            public void run() {
                System.out.println("狂狂地乱跑");
            }
        };
        Animal animal2 = new Animal() {
            @Override
            public void run() {
                System.out.println("优雅地走");
            }
        };
        go(animal1);
        go(animal2);
    }
    public static void go(Animal animal){
        animal.run();
    }
}

运行结果如下:

         

        这个结果跟之前没有简化的结果是一样的,优点,减少了两个新类的定义了,但是通过new 接口名或者父类名 (){重写方法 } 方式是创建了一个类,可以反汇编看看这个类。

想来看看这个.class文件,一般来说一个类就会有一个.class文件。

        这里“多出了”两个类吧,分别是Text$1.class  Text$2.class,这就是通过new 接口名或者父类名 (){重写方法 } 方式是创建出来的。

再来具体看看里面的代码如下:

        

        这是其中的一个.class文件的反汇编代码,怎么样?这是不是一个接口被类去实现了。所以,其实说那么多,就是为了知道通过new 接口名或者父类名 (){重写方法 }  这个方式是创建一个匿名类。    

        2.4.2匿名内部类的特点包括:

  1. 没有显式的类名,只能在创建对象的时候定义并实现。
  2. 可以实现接口或继承父类。
  3. 可以直接访问外部类的成员变量和方法,以及方法的参数和局部变量(但是需要声明为final)。
  4. 由于没有类名,所以无法在其他地方创建该类的实例。

        2.4.3对匿名内部类进行小结: 

       小结一下:匿名内部类是一种特殊的局部内部类,它没有显式的类名,只能在创建对象的时候定义并实现。匿名内部类通常用于创建一个只需要使用一次的类的实例,避免了显式定义一个新的类。



                    

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

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

相关文章

react管理系统layOut简单搭建

一、新建立react文件夹,生成项目 npx create-react-app my-app cd my-app npm start 二、安装react-router-dom npm install react-router-dom 三、安装Ant Design of React(UI框架库,可根据需求进行安装) npm install antd …

Idea JavaWeb项目,继承自HttpFilter的过滤器,启动Tomcat时部署工件出错

JDK版本:1.8 Tomcat版本:8.5 10-Oct-2023 13:55:17.586 严重 [RMI TCP Connection(3)-127.0.0.1] org.apache.catalina.core.StandardContext.startInternal One or more Filters failed to start. Full details will be found in the appropriate conta…

onnx转换TensorRT的步骤

A. 解析onnx 已有的trt不适配,需要将onnx转为trt parse onnxserialize trt保存trt文件 注意:如果不使用Int8模式,onnx的parser代码几乎通用 概览 构建阶段 建立logger(日志)建立builder(网络元数据)创…

SpringBoot 如何使用 Sleuth 进行分布式跟踪

使用Spring Boot Sleuth进行分布式跟踪 在现代分布式应用程序中,跟踪请求和了解应用程序的性能是至关重要的。Spring Boot Sleuth是一个分布式跟踪解决方案,它可以帮助您在分布式系统中跟踪请求并分析性能问题。本文将介绍如何在Spring Boot应用程序中使…

【Python深度学习】目标检测和语义分割的区别

在计算机视觉领域,语义分割和目标检测是两个关键的任务,它们都是对图像和视频进行分析,但它们之间存在着明显的区别。本文将通过图像示例,详细阐述语义分割和目标检测之间的差异。 一、基本概念 1.1 语义分割(Semantic…

Git【入门】从安装到会用(千字总结)

Git使用 一、Git介绍 1.1 版本控制(理解) 无论是代码编写,还是文档编写,我们都会遇到对文档内容反复修改的情况 但我们不能只保留最后一次修改的文件,其余版本也要保留,有可能老板想要的就是你的上一个版本的 1.2 开发中存在的…

基于YOLOv5、YOLOv8的火灾检测(超实用毕业设计项目)

yolo系列文章目录 摘要:基于YOLOV5模型的火灾检测系统用于日常生活中检测与定位火灾目标,包括建筑火灾、森林火灾等。利用深度学习算法可实现图片、视频、摄像头等方式的火灾目标检测,另外本系统还支持图片、视频等格式的结果可视化与结果导…

云安全之信息内容安全

内容安全产生背景 随着互联网、智能设备及各种新生业务的飞速发展,互联网上的数据呈现爆炸式增长,图片、视频、发文、聊天等互动内容已经成为人们表达感情、记录事件和日常工作不可或缺的部分。每天,通过互联网上传的视频、图片数量超过10亿…

在工业机器视觉领域中应用钡铼技术有限公司的EtherCAT网关

钡铼技术有限公司作为一家专注于业物联网关、工业智能网关、边缘计算网关、ARM嵌入式工业计算机、PLC远程采集网关、Modbus转MQTT网关、OPC UA网关、BACnet网关路由器、Lora网关、工业4G边缘路由器、4G无线远程数据采集模块、4G DTU RTU、以太网远程IO模块、工业总线分布式I/O模…

R语言实现向量自回归和误差修正模型——附实战代码

大家好,我是带我去滑雪! 向量自回归(VAR)模型和误差修正模型(ECM)是时间序列分析中常用的两种模型,它们用于研究多个变量之间的动态关系。VAR 模型适用于研究多个相关变量之间的相互影响和动态关…

总结CRM客户管理系统实施失败的主要原因

实施CRM系统相对于ERP等大型软件要更加容易,但不是每一家企业都能成功实施CRM系统,实施CRM销售管理系统失败的原因有很多比如准备工作不足、与现有应用无法集成做到数据互通、销售人员不容易操作系统。 准备工作不足 部署方式是本地化还云服务主要取决…

除了console.log(),很多人不知道的其他方法console.table,console.dir,console.time等

console.dir 可以对象化输出 dom <script>setTimeout(() > {let d document.querySelector(.box);console.log(d);console.dir(d);}, 500);</script>输出结果 这个对象展开之后的内容太多了就不截图了 console.table能够以表格形式展现对象/数组 <scrip…

如何在 PyTorch 中冻结模型权重以进行迁移学习:分步教程

一、说明 迁移学习是一种机器学习技术&#xff0c;其中预先训练的模型适用于新的但类似的问题。迁移学习的关键步骤之一是能够冻结预训练模型的层&#xff0c;以便在训练期间仅更新网络的某些部分。当您想要保留预训练模型已经学习的特征时&#xff0c;冻结至关重要。在本教程中…

回馈式负载箱的应用

回馈式负载箱通过用来模拟负载来测量电源的性能和稳定性&#xff0c;由可编程电子负载、控制电路和测量电路组成&#xff0c;回馈式负载箱的应用非常广泛&#xff0c;它用于电源系统的研发和测试。通过连接回馈式负载箱到待测电源上&#xff0c;可以模拟不同的负载情况&#xf…

LuaRadio介绍

介绍 LuaRadio是一个用于构建信号处理流程图的框架 在软件定义的无线电流图中&#xff0c;源和接收块倾向于实现某种I/O&#xff0c;如从SDR加密狗读取样本&#xff0c;或将样本写入IQ文件&#xff0c;而处理块倾向于计算&#xff0c;如滤波器和乘法器。 数据类型说明 LuaRadio…

ERROR 2003 (HY000): Can‘t connect to MySQL server on ‘localhost‘ (10061)的问题解决

winR打开窗口输入 services.msc 停止mysql 找到data文件&#xff0c;清空其中全部文件。没有data文件&#xff0c;手动创建 ​ 输入 mysqld --remove mysql 移除服务&#xff1b; 注册服务&#xff0c;mysqld -install&#xff1b; 并开始初始化&#xff0c;mysqld --initi…

【FreeRTOS】【STM32】03 FreeRTOSConfig.h头文件简介与修改

基于[野火]《FreeRTOS%20内核实现与应用开发实战—基于STM32》.pdf FreeRTOSConfig.h头文件是FreeRTOS各项功能的打开与关闭 FreeRTOSConfig.h头文件简介 之前也说过了&#xff0c;FreeRTOSConfig.h文件可以添加在工程中任意文件夹&#xff0c;只需要在路径中添加好了就行。…

修炼k8s+flink+hdfs+dlink(四:k8s概念)

一&#xff1a;概念 1. 概述 1.1 kubernetes对象. k8s对象包含俩个嵌套对象字段。 spec&#xff08;规约&#xff09;&#xff1a;期望状态 status&#xff08;状态&#xff09;&#xff1a;当前状态 当创建对象的时候&#xff0c;会按照spec的状态进行创建&#xff0c;如果…

某省医保局:强化医保信息化高质量建设,提升数字医疗保障服务能力

自2018年起&#xff0c;国家医保信息化工作启动&#xff0c;2020年10月完成了国家医保信息平台主体建设&#xff0c;随后国家医保信息化工作重点转向地方落地应用。在国家医保局的指导下&#xff0c;全国各地省市级医保部门制定了医疗保障信息化工作目标。 东北某省作为医保信息…

java日志框架详解-Log4j2

一、概述 Apache Log4j 2 &#xff08;Log4j – Apache Log4j 2&#xff09;是对Log4j的升级&#xff0c;它比其前身Log4j 1.x提供了重大改进&#xff0c;并参考了Logback中优秀的设计&#xff0c;同时修复了Logback架构中的一些问题。被誉为是目前最优秀的Java日志框架&#x…