内部类(3):匿名内部类
1 匿名类
请看下面这个例子:
public class Parcel7 {public Contents contents() {return new Contents() {private int i = 11;public int value() {return i;}};}public static void main(String[] args) {Parcel7 p = new Parcel7();Contents c = p.contents();}
}
contents() 方法将返回值的生成与表示这个返回值的类定义结合在一起。另外,这个类是匿名的,它没有名字。更糟糕的是,看起来似乎是你正要创建一个Contents对象。但是然后(在到达语句结束的分号之前)你却说:“等一等,我想在这里插入一个类的定义”。
这种奇怪的语法指的是:“创建一个继承自Contents的匿名类的对象。”通过new表达式返回的引用被自动向上转型为对Contents的引用。上述匿名内部类的语法是下述形式的简化形式:
public class Parcel7b {class MyContents implements Contents {private int i = 11;public int value() {return i;}}public Contents contents() {return new MyContents();}public static void main(String[] args) {Parcel7b p = new Parcel7b();Contents c = p.contents();}
}
在这个匿名内部类中,使用了默认的构造器来生成Contents。下面的代码展示的是,如果你的基类需要一个有参数的构造器,应该怎么办:
public class Parcel8 {public Wrapping wrapping(int x) {return new Wrapping(x) {public int value() {return super.value() * 47;}};}public static void main(String[] args) {Parcel8 p = new Parcel8();Wrapping w = p.wrapping(10);}
}
只需简单地传递合适的参数给基类的构造器即可,这里是将x传进new Wrapping(x)。尽管Wrapping只是一个具有具体实现的普通类,但它还是被其导出类当作公共“接口”来使用:
public class Wrapping {private int i;public Wrapping(int x) {i = x;}public int value() {return i;}
}
你会注意到,Wrapping拥有一个要求传递一个参数的构造器,这使得事情变得更加有趣了。
在匿名内部类末尾的分号,并不是用来标记此内部类结束的。实际上,它标记的是表达式的结束,只不过这个表达式正巧包含了匿名内部类罢了。因此,这与别的地方使用的分号是一致的。
在匿名类中定义字段时,还能够对其执行初始化操作:
public class Parcel9 {public Destination destination(final String dest) {return new Destination() {private String label = dest;public String readLabel() {return label;}};}public static void main(String[] args) {Parcel9 p = new Parcel9();Destination d = p.destination("Tasmania");}
}
如果定义一个匿名内部类,并且希望它使用一个在其外部定义的对象,那么编译器会要求其参数引用是final的,就像你在destination() 的参数中看到的那样。如果你忘记了,将会得到一个编译时错误消息。
如果只是简单地给一个字段赋值,那么此例中的方法是很好的。但是,如果想做一些类似构造器的行为,该怎么办呢?在匿名类中不可能有命名构造器(因为它根本没名字),但通过实例初始化,就能够达到为匿名内部类创建一个构造器的效果,就像这样:
abstract class Base {public Base(int i) {System.out.println("Base constructor, i = " + i);}public abstract void f();
}public class AnonymousConstructor {public static Base getBase(int i) {return new Base(i) {{System.out.println("Inside instance initializer");}public void f() {System.out.println("In AnonymousConstructor.f()");}};}public static void main(String[] args) {Base base = getBase(47);base.f();}
}
在此例中,不要求变量i一定是final的,因为i被传递给匿名类的基类构造器,它并不会在匿名类内部被直接使用。
下面是带实例化的“parcel”形式。注意destination()的参数必须是final的,因为它们是在匿名类内部使用的:
public class Parcel10 {public Destination destination(final String dest, final float price) {return new Destination() {private int cost;{cost = Math.round(price);if (cost > 100) {System.out.println("Over budget!");}}private String label = dest;public String readLabel() {return label;}};}public static void main(String[] args) {Parcel10 p = new Parcel10();Destination d = p.destination("Tasmania", 101.395f);}
}
在实例初始化操作的内部,可以看到有一段代码,它们不能作为字段初始化动作的一部分来执行(就是if语句)。所以对于匿名类而言,实例初始化的实际效果就是构造器。当然它受到了限制,你不能重载实例初始化方法,所以你仅有一个这样的构造器。
匿名内部类与正规的继承相比有些受限,因为匿名内部类既可以扩展类,也可以实现接口,但是不能两者兼备。而且如果是实现接口,也只能实现一个接口。
2 再访工厂方法
看看在使用匿名内部类时,Factories.java示例:
interface Service {void method1();void method2();
}interface ServiceFactory {Service getService();
}class Implementation1 implements Service {private Implementation1() {}public void method1() {System.out.println("Implementation1 method1");}public void method2() {System.out.println("Implementation1 method2");}public static ServiceFactory factory = new ServiceFactory() {public Service getService() {return new Implementation1();}};
}class Implementation2 implements Service {private Implementation2() {}public void method1() {System.out.println("Implementation2 method1");}public void method2() {System.out.println("Implementation2 method2");}public static ServiceFactory factory = new ServiceFactory() {public Service getService() {return new Implementation2();}};
}public class Factories {public static void serviceConsumer(ServiceFactory fact) {Service s = fact.getService();s.method1();s.method2();}public static void main(String[] args) {serviceConsumer(Implementation1.factory);serviceConsumer(Implementation2.factory);}
}
现在用于Implementation1和Implementation2的构造器都可以是private的,并且没有任何必要去创建作为工厂的具名类。另外,你经常只需要单一的工厂对象,因此在本例中它被创建为Service实现中的一个static域。这样所产生语法也更具有实际意义。
Games.java示例也可以通过使用匿名内部类来改进:
interface Game {boolean move();
}interface GameFactory {Game getGame();
}class Checkers implements Game {private Checkers() {}private int moves = 0;private static final int MOVES = 3;public boolean move() {System.out.println("Checkers move " + moves);return ++moves != MOVES;}public static GameFactory factory = new GameFactory() {public Game getGame() {return new Checkers();}};
}class Chess implements Game {private Chess() {}private int moves = 0;private static final int MOVES = 4;public boolean move() {System.out.println("Chess move " + moves);return ++moves != MOVES;}public static GameFactory factory = new GameFactory() {public Game getGame() {return new Chess();}};
}public class Games {public static void playGame(GameFactory factory) {Game s = factory.getGame();while (s.move());}public static void main(String[] args) {playGame(Chess.factory);playGame(Checkers.factory);}
}
请记住优先使用类而不是接口。如果你的设计中需要某个接口,你必须了解它。否则,不到迫不得已,不要将其放到你的设计中。
相关文章:
内部类(3):匿名内部类
1 匿名类 请看下面这个例子: public class Parcel7 {public Contents contents() {return new Contents() {private int i 11;public int value() {return i;}};}public static void main(String[] args) {Parcel7 p new Parcel7();Contents c p.contents();} }…...
组件通信-$attrs
概述:$attrs用于实现当前组件的父组件,向当前组件的子组件通信(爷→孙)。 具体说明:$attrs是一个对象,包含所有父组件传入的标签属性。 注意:$attrs会自动排除props中声明的属性(可以认为声明过…...
Laravel Octane 项目加速与静态资源优化指南
Laravel Octane 项目加速与静态资源优化指南 一、Octane 核心加速配置 扩展安装与环境配置 composer require laravel/octane # 安装核心扩展php artisan octane:install # 生成配置文件(选择 Swoole/RoadRunner 等服务器)服务器参数调优 …...
【Linux】Petalinux U-Boot
描述 部分图片和经验来源于网络,若有侵权麻烦联系我删除,主要是做笔记的时候忘记写来源了,做完笔记很久才写博客。 专栏目录:记录自己的嵌入式学习之路-CSDN博客 目录 0 引导流程示例 1 进入U-Boot 2 常用U-Boot操作命…...
【KWDB 创作者计划】技术解读:多模架构、高效时序数据处理与分布式实现
技术解读:多模架构、高效时序数据处理与分布式实现 一、多模架构1.1 架构概述1.2 源码分析1.3 实现流程 二、高效时序数据处理2.1 处理能力概述2.2 源码分析2.3 实现流程 三、分布式实现3.1 分布式特性概述3.2 源码分析3.3 实现流程 四、总结 在当今数据爆炸的时代&…...
深度学习框架PyTorch——从入门到精通(YouTube系列 - 4)——使用PyTorch构建模型
这部分是 PyTorch介绍——YouTube系列的内容,每一节都对应一个youtube视频。(可能跟之前的有一定的重复) torch.nn.Module(PyTorch神经网络模块)和torch.nn.Parameter(PyTorch神经网络参数)常见…...
通过组策略使能长路径
打开组策略编辑器,依次展开: 计算机配置 > 管理模板然后双击 所有设置 右侧就会出现列表。接着在列表中找到 启用 win32 长路径 ,双击 改成 已启用 ,然后点击确定。最后重启计算机。...
Dubbo(90)如何设计一个支持多协议的Dubbo服务?
设计一个支持多协议的Dubbo服务需要考虑以下几个方面: 服务接口设计:确保服务接口的定义可以被不同协议实现。多协议配置:配置不同的协议,例如 Dubbo、HTTP、gRPC 等。服务注册与发现:确保服务能够在多个协议下注册和…...
JavaScript常规解密技术解析指南
第一章:密码学基础铺垫 逆向思维提示框 逆向思维在密码学中至关重要。当面对加密数据时,不要局限于常规的加密过程,而是要从解密的角度去思考。例如,在看到Base64编码的数据时,要立刻联想到它是如何从原始数据转换而…...
字符串的相关方法
1. equals方法的作用 方法介绍 public boolean equals(String s) 比较两个字符串内容是否相同、区分大小写 示例代码 public class StringDemo02 {public static void main(String[] args) {//构造方法的方式得到对象char[] chs {a, b, c};String s1 new String(chs);…...
云原生后端架构的实践与挑战:探索现代后端开发的未来
📝个人主页🌹:一ge科研小菜鸡-CSDN博客 🌹🌹期待您的关注 🌹🌹 随着云计算的普及,云原生架构已经逐渐成为现代软件开发的主流方式。云原生后端架构通过容器化、微服务、自动化运维等技术,帮助企业构建具有高度可扩展性和可靠性的系统。在本文中,我们将深入探讨…...
MySQL基础关键_005_DQL(四)
目 录 一、分组函数 1.说明 2.max/min 3.sum/avg/count 二、分组查询 1.说明 2.实例 (1)查询岗位和平均薪资 (2)查询每个部门编号的不同岗位的最低薪资 3.having (1)说明 (2ÿ…...
Gradio全解20——Streaming:流式传输的多媒体应用(3)——实时语音识别技术
Gradio全解20——Streaming:流式传输的多媒体应用(3)——实时语音识别技术 本篇摘要20. Streaming:流式传输的多媒体应用20.3 实时语音识别技术20.3.1 环境准备和开发步骤1. 环境准备2. ASR应用开发步骤(基于Transform…...
[android]MT6835 Android 关闭selinux方法
Selinux SELinux is an optional feature of the Linux kernel that provides support to enforce access control security policies to enforce MAC. It is based on the LSM framework. Working with SELinux on Android – LineageOS Android 关闭selinux MT6835 Android…...
GitHub 趋势日报 (2025年05月01日)
本日报由 TrendForge 系统生成 https://trendforge.devlive.org/ 📈 今日整体趋势 Top 10 排名项目名称项目描述今日获星总星数语言1hacksider/Deep-Live-Camreal time face swap and one-click video deepfake with only a single image⭐ 1311⭐ 56231Python2day…...
对称加密算法(AES、ChaCha20和SM4)Python实现——密码学基础(Python出现No module named “Crypto” 解决方案)
文章目录 一、对称加密算法基础1.1 对称加密算法的基本原理1.2 对称加密的主要工作模式 二、AES加密算法详解2.1 AES基本介绍2.2 AES加密过程2.3 Python中实现AES加密Python出现No module named “Crypto” 解决方案 2.4 AES的安全考量 三、ChaCha20加密算法3.1 ChaCha20基本介…...
n8n 键盘快捷键和控制键
n8n 键盘快捷键和控制键 工作流控制键画布操作移动画布画布缩放画布上的节点操作选中一个或多个节点时的快捷键 节点面板操作节点面板分类操作 节点内部操作 n8n 为部分操作提供了键盘快捷键。 工作流控制键 Ctrl Alt n:创建新工作流Ctrl o:打开工作…...
部署Superset BI(二)再战Superset
上次安装没有成功,这次把superset的安装说明好好看了一下。 rootNocobase:/usr# cd superset rootNocobase:/usr/superset# git clone https://github.com/apache/superset.git Cloning into superset... remote: Enumerating objects: 425644, done. remote: Count…...
生日快乐祝福网页制作教程
原文:https://www.w3cschool.cn/article/88229685.html (本文非我原创,请标记为付费文章,也请勿将我标记为原创) 一、引言 生日是每个人一年中最特别的日子之一。在这个特别的日子里,我们都希望能够给亲…...
Spring MVC @RequestHeader 注解怎么用?
我们来详细解释一下 Spring MVC 中的 RequestHeader 注解。 RequestHeader 注解的作用 RequestHeader 注解用于将 HTTP 请求中的**请求头(Request Headers)**的值绑定到 Controller 方法的参数上。 请求头是 HTTP 请求的一部分,包含了关于…...
【Linux深入浅出】之全连接队列及抓包介绍
【Linux深入浅出】之全连接队列及抓包介绍 理解listen系统调用函数的第二个参数简单实验实验目的实验设备实验代码实验现象 全连接队列简单理解什么是全连接队列全连接队列的大小 从Linux内核的角度理解虚拟文件、sock、网络三方的关系回顾虚拟文件部分的知识struct socket结构…...
Linux C++ JNI封装、打包成jar包供Java调用详细介绍
在前面 Android专栏 中详细介绍了如何在Android Studio中调用通过jni封装的c库。 在Android使用 opencv c代码,需要准备opencv4android,也就是c的任何代码,是使用Android NDK编译的,相当于在windows/mac上使用Android stdido交叉…...
CPO-BP+NSGA,豪冠猪优化BP神经网络+多目标遗传算法!(Matlab完整源码和数据)
目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.CPO-BPNSGA,豪冠猪优化BP神经网络多目标遗传算法!(Matlab完整源码和数据),豪冠猪算法优化BP神经网络的权值和阈值,运行环境Matlab2020b及以上…...
组件通信-v-model
概述:实现 父↔子 之间相互通信。 前序知识 —— v-model的本质 <!-- 使用v-model指令 --> <input type"text" v-model"userName"><!-- v-model的本质是下面这行代码 --> <input type"text" :value"use…...
使用PyMongo连接MongoDB的基本操作
MongoDB是由C语言编写的非关系型数据库,是一个基于分布式文件存储的开源数据库系统,其内容存储形式类似JSON对象,它的字段值可以包含其他文档、数组及文档数组。在这一节中,我们就来回顾Python 3下MongoDB的存储操作。 常用命令:…...
010302-oss_反向代理_负载均衡-web扩展2-基础入门-网络安全
文章目录 1 OSS1.1 什么是 OSS 存储?1.2 OSS 核心功能1.3 OSS 的优势1.4 典型使用场景1.5 如何接入 OSS?1.6 注意事项1.7 cloudreve实战演示1.7.1 配置cloudreve连接阿里云oss1.7.2 常见错误1.7.3 安全测试影响 2 反向代理2.1 正向代理和反向代理2.2 演示…...
PyQt 或 PySide6 进行 GUI 开发文档与教程
一、官网文档 Qt 官方文档:Porting to Qt 6 | Qt 6.9Qt 维基:Qt WikiQt for Python (PySide6) :Qt for Python - Qt WikiPySide6 快速上手指南:Getting Started - Qt for Python PyS…...
【东枫科技】AMD / Xilinx Alveo™ V80计算加速器卡
AMD / Xilinx Alveo™ V80计算加速器卡 AMD/Xilinx Alveo ™ V80计算加速器卡是一款功能强大的计算加速器,基于7nm Versal™ 自适应SoC架构而打造。 AMD/Xilinx Alveo V80卡设计用于内存密集型任务。 这些任务包括HPC、数据分析、网络安全、传感器处理、计算存储和…...
C++ 动态内存管理
operator new和operator delete函数是两个全局函数,编译器在编译new和delete时会调用这两个函数,其底层分别是封装malloc和free 1.new new 内置类型 内置类型没有构造函数,所以使用new就是调operator new函数开空间,如果要初始化…...
(11)Vue-Router路由的详细使用
本系列教程目录:Vue3Element Plus全套学习笔记-目录大纲 文章目录 第2章 路由 Vue-Router2.1 Vue路由快速入门2.1.1 创建项目2.1.2 路由运行流程 2.2 传递参数-useRoute2.2.1 路径参数-params1)普通传参2)传递多个参数3)对象方式传…...
RISCV的smstateen-ssstateen扩展
RISC-V 的 Smstateen / Ssstateen 扩展是为了解决安全性和资源隔离性问题而设计的,尤其是针对在多个上下文(如用户线程、多个虚拟机)之间 潜在的隐蔽信道(covert channel) 风险。 🌐 背景:隐蔽信道与上下文切换问题 当…...
C++ 与 Lua 联合编程
在软件开发的广阔天地里,不同编程语言各有所长。C 以其卓越的性能、强大的功能和对硬件的直接操控能力,在系统开发、游戏引擎、服务器等底层领域占据重要地位,但c编写的程序需要编译,这往往是一个耗时操作,特别对于大型…...
瑞萨 EZ-CUBE2 调试器
瑞萨 EZ-CUBE2 调试器 本文介绍了瑞萨 EZ-CUBE2 调试器的基本信息、调试方式、环境搭建、硬件连接、软件测试等。 包装展示 调试器展示 开关选项 详见:EZ-CUBE2 | Renesas 瑞萨电子 . 环境搭建 使用 Renesas 公司的 e2 studio 开发工具,下载 并安装该…...
MATLAB滤波工具箱演示——自定义维度、滤波方法的例程演示与绘图、数据输出
使用 M A T L A B MATLAB MATLAB的界面做了一个 M A T L A B MATLAB MATLAB滤波工具箱 d e m o demo demo,本文章给出演示:自定义维度、滤波方法的例程演示与绘图、数据输出 文章目录 编辑界面使用方法优势待改进点部分代码 编辑界面 使用 M A T L A B …...
数据库索引优化实战: 如何设计高效的数据库索引
数据库索引优化实战: 如何设计高效的数据库索引 一、理解数据库索引的核心原理 1.1 B树索引的结构特性 数据库索引(Database Index)的本质是通过特定数据结构加速数据检索。现代关系型数据库普遍采用B树(B Tree)作为默认索引结构&…...
TS 安装
TS较JS优势 1 TS静态类型编程语言。编译时发现错误 2 类型系统 强化变量类型概念 3 支持新语法 4 类型推断机制 可以和React框架中的各种hook配合 5 任何地方都有代码提示 tsc 命令 将TS转为JS 1 tsc 文件.ts 生成 js文件 2 执行JS代码...
CMake separate_arguments用法详解
separate_arguments 是 CMake 中用于将字符串分割成参数列表的命令,适用于处理包含空格的参数或复杂命令行参数。以下是其用法详解: 基本语法 separate_arguments(<variable> [UNIX|WINDOWS_COMMAND] [PROGRAM <program>] [ARGS <args&…...
【AI科技】AMD ROCm 6.4 新功能:突破性推理、即插即用容器和模块化部署,可在 AMD Instinct GPU 上实现可扩展 AI
AMD ROCm 6.4 新功能:突破性推理、即插即用容器和模块化部署,可在 AMD Instinct GPU 上实现可扩展 AI 现代 AI 工作负载的规模和复杂性不断增长,而人们对性能和部署便捷性的期望也日益提升。对于在 AMD Instinct™ GPU 上构建 AI 和 HPC 未来…...
2025年- H20-Lc128-240. 搜索二维矩阵 II(矩阵)---java版
1.题目描述 2.思路 遍历矩阵,然后如果遇到矩阵中的值正好等于target,输出true。否则,输出false。 3.代码 public class H240 {public boolean searchMatrix(int[][] matrix, int target) {//1.计算出总的行值,总的列值。int mm…...
LearningFlow:大语言模型城市驾驶的自动化策略学习工作流程
《LearningFlow: Automated Policy Learning Workflow for Urban Driving with Large Language Models》2025年1月发表,来自香港科技大学广州分校的论文。 强化学习(RL)的最新进展表明了自动驾驶的巨大潜力。尽管有这一前景,但奖励…...
C语言数据类型与内存布局
C语言数据类型内存占用 类型32位系统64位系统格式说明符char1字节1字节%cint4字节4字节%dfloat4字节4字节%fdouble8字节8字节%lflong long8字节8字节%lld...
从原理到实战讲解回归算法!!!
哈喽,大家好,我是我不是小upper, 今天系统梳理了线性回归的核心知识,从模型的基本原理、参数估计方法,到模型评估指标与实际应用场景,帮助大家深入理解这一经典的机器学习算法,助力数据分析与预测工作。 …...
linux指令中的竖线(“|”)是干啥的?【含实例展示】
文章目录 一、管道符的基本概念二、管道符的核心作用三、常用实例展示四、进阶技巧五、注意事项总结 实操展示**案例1:统计日志中特定错误的数量****案例2:查找当前运行的进程****案例3:合并排序并去重****案例4:实时监控CPU占用前…...
[HOT 100] 0124. 二叉树中的最大路径和
文章目录 1. 题目链接2. 题目描述3. 题目示例4. 解题思路5. 题解代码6. 复杂度分析 1. 题目链接 124. 二叉树中的最大路径和 - 力扣(LeetCode) 2. 题目描述 二叉树中的 路径 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一…...
[SoC]AXI总线Performance验证方案
AXI总线Performance验证方案 测试 AXI (Advanced eXtensible Interface) 的性能是 SoC 验证中的重要任务,旨在评估其在不同负载和配置下的表现是否满足设计要求。以下详细说明如何测试 AXI 的性能、需要统计的变量、计算方法、在验证环境中动态计算性能的方法,以及如何…...
EMC PowerStore存储学习之一NVMe磁盘的命名规则
PowerStore的日志中经常会看到类似于/dev/nvme1n1的磁盘,在svc_diag list --show_drives中也可以看到类似这样的输出,如下图: 这里的Drives的显示都是 /dev/nvmeXnY的形式,那么这个磁盘命名规则怎么解读呢? 在Linux系…...
apt-mirror搭建ubuntu本地离线源
参考资料 4 Steps to Setup Local Repository in Ubuntu using APT-mirror 使用 APT-mirror 四步配置 Ubuntu 本地软件仓库 ubuntu下的apt-get内网本地源的搭建...
【记录】新Ubuntu20配置voxelmap的环境安装
因为系统总出问题,仅用于个人纪录。 1. 升级CMake到3.28及以上版本(Sophus依赖) wget https://github.com/Kitware/CMake/releases/download/v3.28.3/cmake-3.28.3-linux-x86_64.sh chmod x cmake-3.28.3-linux-x86_64.sh sudo ./cmake-3.2…...
Python全流程开发实战:基于IMAP协议安全下载个人Gmail邮箱内所有PDF附件
在日常办公场景中,面对成百上千封携带PDF附件的邮件,手动逐一下载往往耗时耗力,成为效率瓶颈。如何通过代码实现“一键批量下载”?本文将以**“Gmail全量PDF附件下载工具”**开发为例,完整拆解从需求分析到落地交付的P…...
CPU:AMD的线程撕裂者(Threadripper)和霄龙(EPYC)的区别
AMD的**线程撕裂者(Threadripper)和霄龙(EPYC)**虽然都是面向高性能市场的处理器,但它们在定位、功能和技术规格上有显著区别。以下是两者的主要差异: 1. 目标市场 线程撕裂者(Threadripper&…...