【JAVA基础之内部类】匿名内部类

🔥作者主页:小林同学的学习笔录

🔥小林同学的专栏:JAVA之基础专栏

目录

1.内部类

1.1 概述

1.1.1 什么是内部类

1.1.2 什么时候使用内部类

1.2 内部类的分类

1.3 成员内部类

1.3.1  获取成员内部类对象的两种方式

1.3.2  经典面试题

1.4  静态内部类

1.4.1  静态内部类对象的创建格式

1.5  局部内部类

1.6  匿名内部类

1.6.1  引出匿名内部类 

1.6.2  匿名内部类用处

1.6.3  匿名内部类的使用场景


1.内部类

1.1 概述

1.1.1 什么是内部类

将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类,其他称为外部其他类可以把内部类理解成寄生,外部类理解成宿主。

1.1.2 什么时候使用内部类

一个事物内部还有一个独立的事物,内部的事物脱离外部的事物无法独立使用

  1. 人里面有一颗心脏。

  2. 汽车内部有一个发动机。

  3. 目的为了实现更好的封装性。

1.2 内部类的分类

按定义的位置来分

  1. 成员内部内,类定义在了成员位置 (类中方法外称为成员位置,无static修饰的内部类)

  2. 静态内部类,类定义在了成员位置 (类中方法外称为成员位置,有static修饰的内部类)

  3. 局部内部类,类定义在方法内

  4. 匿名内部类,没有名字的内部类,可以在方法中,也可以在类中方法外。

1.3 成员内部类

类定义在成员位置上

1.3.1  获取成员内部类对象的两种方式

  • 方式一:外部直接创建成员内部类的对象
    • 外部类.内部类 变量 = new 外部类().new 内部类();
  • 方式二:在外部类中定义一个方法提供内部类的对象(一般用在内部类用private修饰才用到)

代码演示:

方式一:
public class Test {
    public static void main(String[] args) {
        //  宿主:外部类对象。
       // Outer out = new Outer();
        // 创建内部类对象。
        Outer.Inner oi = new Outer().new Inner();
        oi.method();
    }
}

class Outer {
    // 成员内部类,属于外部类对象的。
    // 拓展:成员内部类不能定义静态成员。
    public class Inner{
        // 这里面的东西与类是完全一样的。
        public void method(){
            System.out.println("内部类中的方法被调用了");
        }
    }
}


方式二:
public class Outer {
    String name;
    private class Inner{
        static int a = 10;
    }
    public Inner getInstance(){
        return new Inner();
    }
}

public class Test {
    public static void main(String[] args) {
        Outer o = new Outer();
        System.out.println(o.getInstance());


    }
}

1.3.2  经典面试题

public class Test {
    public static void main(String[] args) {
        Outer.inner oi = new Outer().new inner();
        oi.method();
    }
}

class Outer {	// 外部类
    private int a = 30;

    // 在成员位置定义一个类
    class inner {
        private int a = 20;

        public void method() {
            int a = 10;
            System.out.println(???);	// 10   答案:a
            System.out.println(???);	// 20	答案:this.a
            System.out.println(???);	// 30	答案:Outer.this.a
        }
    }
}

执行原理:

1.4  静态内部类

静态内部类可以直接访问外部类的静态成员。

静态内部类不可以直接访问外部类的非静态成员,如果要访问需要创建外部类的对象。

静态内部类中没有虚拟机所创建的Outer.this

如何调用静态内部类的方法?

  • 非静态方法:创建对象,并调用方法
  • 静态方法:外部类名.内部类名.方法名()

1.4.1  静态内部类对象的创建格式

外部类.内部类  变量 = new  外部类.内部类构造器;

代码演示:

// 外部类:Outer01
class Outer01{
    private static  String sc_name = "小白";
    private String sc_age = 24;
    // 内部类: Inner01
    public static class Inner01{
        // 这里面的东西与类是完全一样的。
        private String name;
        public Inner01(String name) {
            this.name = name;
        }
        public void showName(){
            System.out.println(this.name);
            // 拓展:静态内部类可以直接访问外部类的静态成员。
            System.out.println(sc_name);
            //访问外部类的非静态的变量需要创建外部类的对象
            Outer01 outer01 = new Outer01();
            System.out.println(outer.sc_age);
        }
    }
}

public class InnerClassDemo01 {
    public static void main(String[] args) {
        // 创建静态内部类对象。
        // 外部类.内部类  变量 = new  外部类.内部类构造器;
        Outer01.Inner01 in  = new Outer01.Inner01("张三");
        in.showName();
    }

1.5  局部内部类

将内部类定义在方法里面就叫做局部内部类,类似于方法中的局部变量

外部类是无法直接获取局部内部类的,需要创建该类的对象,然后再进行使用

该类可以直接访问外部类的成员,也可以访问方法内的局部变量

public class Outer {
    private int outerField = 10;

    public void outerMethod() {
        final int localVar = 20;
        //局部内部类
        class LocalInner {
            void display() {
                System.out.println("Outer Field: " + outerField);
                System.out.println("Local Variable: " + localVar);
            }
        }
        //外部类获取内部类信息,需要创建对象
        LocalInner inner = new LocalInner();
        inner.display();
    }


    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.outerMethod();
    }
}

1.6  匿名内部类

1.6.1  引出匿名内部类 

正常类:

匿名内部类(Student被匿名):

代码演示:

interface Swim {
    public abstract void swimming();
}

public class Demo07 {
    public static void main(String[] args) {
        // 使用匿名内部类对象,并且调用匿名内部类里面的方法
		new Swim() {
			@Override
			public void swimming() {
				System.out.println("自由泳...");
			}
		}.swimming();

        // 接口 变量 = new 实现类(); // 多态,走子类的重写方法
        Swim s2 = new Swim() {
            @Override
            public void swimming() {
                System.out.println("蛙泳...");
            }
        };

        s2.swimming();
        s2.swimming();
    }
}

注意:

new Swim(){
    @Override
    public void swim() {
        System.out.println("Demo01匿名内部类");
    }
};

这样的话是不会有打印数据的,因为整体只是一个匿名内部类对象,需要再去调用相应的成员

匿名内部类字节码文件反编译看到的效果

实际案例:

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

        ArrayList<String> list = new ArrayList<>();
        list.add("11");
        list.add("12");
        list.add("13");
        //下面就是一个匿名内部类
        list.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });
    }
}

反编译之后

1.6.2  匿名内部类用处

匿名内部类在Java中有着一些重要的用途,其中包括:

  1. 简化代码:使用匿名内部类可以减少代码量,避免编写大量的类定义。

  2. 事件处理器:在GUI编程中常常使用匿名内部类来实现事件处理器,如按钮点击事件、菜单项选择等。

  3. 回调函数:匿名内部类也可以用作回调函数的实现,例如对异步任务的处理。

  4. 接口实现:如果只需要使用接口的一次实例,可以直接使用匿名内部类来实现接口的抽象方法。

  5. 方法重写:可以在匿名内部类中重写父类或接口的方法,以实现特定的逻辑。

总之,匿名内部类提供了一种简洁、灵活的方式来实现某些具体功能,通常用于临时、一次性的场景中。

1.6.3  匿名内部类的使用场景

interface Swim {
    public abstract void swimming();
}

public class Demo07 {
    public static void main(String[] args) {
        // 普通方式传入对象
        // 创建实现类对象
        Student s = new Student();
        
        goSwimming(s);
        // 匿名内部类使用场景:作为方法参数传递
        Swim s3 = new Swim() {
            @Override
            public void swimming() {
                System.out.println("蝶泳...");
            }
        };
        // 传入匿名内部类
        goSwimming(s3);

        // 完美方案: 一步到位
        goSwimming(new Swim() {
            public void swimming() {
                System.out.println("大学生, 蛙泳...");
            }
        });

        goSwimming(new Swim() {
            public void swimming() {
                System.out.println("小学生, 自由泳...");
            }
        });
    }

    // 定义一个方法,模拟请一些人去游泳
    public static void goSwimming(Swim s) {
        s.swimming();
    }
}

总结:

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深入pandas:导入数据表

目录 前言 第一点&#xff1a;导入模块 第二点&#xff1a;创建excel表 第三点&#xff1a;读取数据表 总结 前言 数据分析和处理过程中&#xff0c;我们经常需要从外部文件中读取数据。本文将介绍如何使用Python中的Pandas库来读取CSV和Excel文件&#xff0c;以及提取纯数…

v-cloak 用于在 Vue 实例渲染完成之前隐藏绑定的元素

如果你是后端开发者&#xff08;php&#xff09;&#xff0c;在接触一些vue2开发的后台时&#xff0c;会发现有这段代码&#xff1a; # CDN <script src"https://cdn.jsdelivr.net/npm/vue2/dist/vue.js"></script> # 或 <script src"https://cd…

Nacos启动报错:[db-load-error]load jdbc.properties error

在学习Nacos中间件时&#xff0c;出现了一个错误&#xff0c;竟然启动报错&#xff01;&#xff01;&#xff01;! 这个错误第一次遇见&#xff0c;当时我感觉大体就是--数据库连接方面的错误。 可是&#xff0c;对于初学者的我来说一脸懵啊&#xff1f;&#xff1f;&#xff…

微信小程序仿胖东来轮播和背景效果(有效果图)

效果图 .wxml <view class"swiper-index" style"--width--:{{windowWidth}}px;"><image src"{{swiperList[(cardCur bgIndex -1?swiperList.length - 1:cardCur bgIndex > swiperList.length -1?0:cardCur bgIndex)]}}" clas…

代码随想录Day 49|Leetcode|Python|● 647. 回文子串 ● 516.最长回文子序列● 动态规划总结篇

647. 回文子串 给你一个字符串 s &#xff0c;请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 解题思路&#xff1a; 确认dp含义&#xff1a;dp[i][j] s[i:j]是否为回文串…

k8s 1.24.x之后如果rest 访问apiserver

1.由于 在 1.24 &#xff08;还是 1.20 不清楚了&#xff09;之后&#xff0c;下面这两个apiserver的配置已经被弃用 了&#xff0c;简单的说就是想不安全的访问k8s是不可能了&#xff0c;所以只能走安全的访问方式也就是 https://xx:6443了&#xff0c;所以需要证书。 - --ins…

工况数据导入MATLAB及数据复用

01--数据导入 之前在Matlab/Simulink的一些功能用法笔记&#xff08;二&#xff09;中有介绍过数据的导入到MATLAB工作区间 本次主要是想介绍下数据的复用 我们以NEDC工况数据为例&#xff1a; 通过下列3种方法进行导入&#xff1a; 1.通过导入Excel表数据&#xff0c;使用F…

RH850F1KM-S4-100Pin_ R7F7016453AFP MCAL Gpt 配置

1、Gpt组件包含的子配置项 GptDriverConfigurationGptDemEventParameterRefsGptConfigurationOfOptApiServicesGptChannelConfigSet2、GptDriverConfiguration 2.1、GptAlreadyInitDetCheck 该参数启用/禁用Gpt_Init API中的GPT_E_ALREADY_INITIALIZED Det检查。 true:开启Gpt_…

驱动未来:IT行业的现状与发展趋势

前言 随着技术的不断进步&#xff0c;IT行业已成为推动全球经济和社会发展的关键力量。从云计算、大数据、人工智能到物联网、5G通信和区块链&#xff0c;这些技术正在重塑我们的生活和工作方式。本文将探讨IT行业的现状和未来发展趋势&#xff0c;并邀请行业领袖、技术专家和…

大语言模型量化方法对比:GPTQ、GGUF、AWQ 包括显存和速度

GPTQ: Post-Training Quantization for GPT Models GPTQ是一种4位量化的训练后量化(PTQ)方法&#xff0c;主要关注GPU推理和性能。 该方法背后的思想是&#xff0c;尝试通过最小化该权重的均方误差将所有权重压缩到4位。在推理过程中&#xff0c;它将动态地将其权重去量化为f…

centos7安装jdk的几种方式

一、使用Yum安装 安装OpenJDK的可以选择此方法&#xff0c;方便快捷 1. 查看是否有JDK环境 使用java命令查看 java -version 可以看到系统自带的OpenJDK版本信息&#xff0c;如果满足你现在需要配置的JDK环境&#xff0c;下面的教程可以不用看了。 ps&#xff1a;我这是虚拟机…

前端传参的三种方式

1、params 传参 参数拼接在地址 url 的后面给后台&#xff1b;地址栏中可见 案例1 地址栏&#xff1a;https://xxxxxxxx/admin/clues/detail?id558 接口代码&#xff1a; export function getClueDetail(query: any) {return request<clueItem>({url: /clues/detai…

Web Speech API(1)—— SpeechRecognition

Web Speech API 使你能够将语音数据合并到 Web 应用程序中。Web Speech API 有两个部分&#xff1a;SpeechSynthesis 语音合成&#xff08;文本到语音 TTS&#xff09;和 SpeechRecognition 语音识别&#xff08;异步语音识别&#xff09;。 SpeechRecognition 语音识别通过 S…

C语言指针相关知识(第四篇章)(非常详细版)

文章目录 前言一、什么是回调函数二、qsort函数的介绍(默认升序排序)三、qsort函数的模拟实现&#xff08;通过冒泡排序&#xff09;总结 前言 本文介绍了回调函数&#xff0c;qsort函数的使用&#xff0c;以用冒泡排序来模拟实现qsort函数 提示&#xff1a;以下是本篇文章正文…

ASP+ACCESS基于B2C电子商务网站设计

摘 要 运用ASP技术结合了Access数据库原理&#xff0c;基于B/S模式我们开发了一个网上购物系统。在我们的系统中&#xff0c;顾客可以很方便的注册成为会员&#xff0c;对商品进行浏览检索&#xff0c;查看商品的详细资料&#xff0c;然后根据各人的喜好购买心仪的商品。系统…

Day21:Leetcode513.找树左下角的值 +112. 路径总和 113.路径总和ii + 106.从中序与后序遍历序列构造二叉树

LeetCode&#xff1a;513.找树左下角的值 解决方案&#xff1a; 1.思路 在遍历一个节点时&#xff0c;需要先把它的非空右子节点放入队列&#xff0c;然后再把它的非空左子节点放入队列&#xff0c;这样才能保证从右到左遍历每一层的节点。广度优先搜索所遍历的最后一个节点…

Amesim基础篇-元件详解-流体库管路

1 流体类型选择 如下图1所示&#xff0c;流体可以选择流体库中自带的流体。常用的流体类型为50%乙二醇溶液&#xff08;EG50W50 coolant&#xff09;。 2 管路 该模型是常用的管路&#xff0c;如下图所示。如之前所讲的建模原则&#xff1a;严格遵循R-C-R-C的原则。下图中的管…

Golang | Leetcode Golang题解之第98题验证二叉搜索树

题目&#xff1a; 题解&#xff1a; func isValidBST(root *TreeNode) bool {stack : []*TreeNode{}inorder : math.MinInt64for len(stack) > 0 || root ! nil {for root ! nil {stack append(stack, root)root root.Left}root stack[len(stack)-1]stack stack[:len(s…

领域知识 | 智能驾驶安全领域部分常见概论

Hi&#xff0c;早。 最近想买个新能源车&#xff0c;这个车吧相比于之前的内燃车&#xff0c;新能源车与外界的交互多了很多。比如娱乐的第三方应用&#xff0c;OTA升级等应用。 交互带来的便利越多&#xff0c;暴露的风险自然也就越大&#xff0c;相比于手机等消费者终端设备…

Linux信号:信号的保存

目录 一、信号在内核中的表示 二、sigset_t 2.1sigset_t的概念和意义 2.2信号集操作数 三、信号集操作数的使用 3.1sigprocmask 3.2sigpending 3.3sigemptyset 四、代码演示 一、信号在内核中的表示 实际执行信号的处理动作称为信号 递达(Delivery) 。 信号从产生到递达…