接口之美,内部之妙:深入解析Java的接口与内部类

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 接口之美,内部之妙:深入解析Java的接口与内部类

接口

接口不是类,而是对类的一组需求描述,这些类要遵从在接口中定义的统一格式。

接口中的所有方法自动地属于 public。因此,在接口中声明方法时,不必提供关键字 public。但是在方法的实现时,需要将方法根据需求进行作用域声明。

接口可以包含多个方法声明,Java8 以后可以在接口中添加默认方法。

接口中可以定义常量,但是不可以定义实例域(属性)。实例域和方法的实现应该由实现此接口的那个类来提供。

接口的特性

不能使用 new 进行实例化,不能创建接口对象,但是可以声明接口变量,接口变量必须引用实现了接口的类对象。

使用 instanceof 检查一个对象是否实现了某个接口,一个类可以实现多个接口。

接口可以使用 extends 进行继承

Java 的早期版本中,接口中不可以包含实例域和静态方法,后面 Java8 允许在接口中增加静态方法,但是这样做其实有些违背当初接口设计的初衷。之前想要为接口设计静态方法,通常是为接口设计一个伴随类,成对存在,比如:Collection/Collections。

接口中可以定义常量,接口中的常量默认为 public static final。有些接口专门只用来定义常量,那么所有实现此接口的类都自动的继承,可以直接使用而不需要使用类名.常量名的方式。

接口与抽象类

由于 Java 的单继承机制,一个类最多可继承自一个抽象类,但是可以实现多个接口。

相比 C++ 是支持多继承,但是多继承会让语言本身变得更加复杂,而且效率也会降低。那么接口可以提供多重继承的大多数好处,同时还能避免多重继承的复杂性和低效性。

接口的默认方法

Java8 后可以为接口方法提供一个默认的实现,需要使用 default 关键字标记。

声明了默认方法之后,类想要实现此接口就可以不一定重写此方法了。

默认方法的冲突问题
多个接口有相同的默认方法【手动解决】

父类(protected)和接口中有相同的方法【手动解决】

父类(public)和接口中有相同的方法【优先父类】

内部类

内部类式定义在另一个类中的类。

  1. 内部类方法可以访问该类定义所在的作用域中的数据,包括私有的数据。
  2. 内部类可以对同一个包中的其他类隐藏起来。
  3. 当想要定义一个回调函数且不想编写大量代码时,使用匿名 (anonymous )内部类比较便捷。

内部类是一种编译器现象,与虚拟机无关。编译器将会把内部类翻译成用 $ (美元符号)分隔外部类名与内部类名的常规类文件,而虚拟机则对此一无所知。

例如:在 User 类内部的 Contact 类会被编译成类文件 User$Contact.class

使用内部类访问对象状态

内部类可以直接访问所在类的所有内容,比如私有的属性和方法。内部类的对象总有一个隐式引用,它指向了创建它的外部类对象。

内部类的分类

成员内部类

成员内部类:类比成员方法,不能拥有静态域但是可以访问外部类的静态域。

  • 成员内部类的创建需要依赖于外部类对象(成员方法必须通过对象调用),在没有外部类实例之前无法创建成员内部类对象。
  • 内部类与外部类相对独立,不是 is a 的关系。
  • 私有属性的互相访问,内部类可以直接访问外部类,而外部类访问内部类需要内部类的对象来访问。
  • 创建内部类的语法
  • 在外部类内部创建内部类对象 Inner inner = new Inner();
  • 在外部类外部创建内部类对象,外部类.内部类 inner = new Outter().new Inner();
  • 在内部类内部使用隐藏的外部类对象(隐藏的this),外部类名.this

静态内部类

定义在外部类的内部,使用static修饰,类比静态方法,静态内部类不需要外部类对象产生就能使用,不能访问外部类的成员域,但能访问静态域。

静态内部类的创建语法:

  • 外部类内部:Inner inner = new Inner();
  • 外部类外部:StaticInnerClass.Inner inner = new StaticInnerClass.Inner();

方法内部类/局部内部类

局部内部类不仅能够访问包含它们的外部类,还可以访问局部变量。不过,那些局部变量必须事实上为 final。这说明,它们一旦赋值就绝不

会改变。

局部类不能用 public 或 private 访问说明符进行声明。它的作用域被限定在声明这个局部类的块中。

局部类的优点是对外部世界完全隐藏。

匿名内部类

只创建这个类的一个对象,不需要明确定义类名。不过必须继承一个抽象类或者实现一个接口。而且匿名内部类是没有构造方法的。

内部类是否有用、必要和安全

代理

给一个对象提供一种代理对象以控制对该对象的访问。代理对象在不改变原对象代码的基础上对原对象的功能进行扩展。

使用代理降低了系统的耦合度,扩展性也会更好,还可以起到保护目标对象的作用。

代理模式在 Java 开发中是广泛应用的,特别是在框架中底层原理经常涉及到代理模式(尤其是动态代理)。

静态代理和动态代理,实际使用时还是动态代理使用的比较多。原因就是静态代理需要自行手写代码,维护、修改非常繁琐,会额外引入很多工作量。也不能很好的使用配置完成逻辑的指定,所以使用较少。

基于 JDK 和基于 CGLIB,实际使用时两个都会用到。

在 Spring 中,默认情况下它就支持了两种动态代理方式。如果你指定的目标类实现了接口,Spring 就会自动选择 JDK 的动态代理。而如果目标类没有实现接口,则 Spring 会使用 CGLIB。

我们在开发时,由于基于 JDK 的动态代理要求比较多,更不容易实现,所以很多人习惯于统一配置为使用 CGLIB 进行代理。也就是 CGLIB 更通用。

静态代理

静态代理维护复杂,一旦接口或父类发生改变,所有相关的类或接口就都得进行维护。

通过接口

让目标对象和代理对象都实现一个共同接口。那么这两个类就有了公共的方法,就可以在代理对象中实现对目标对象功能的扩展。

通过继承

让代理对象继承目标对象,那么代理对象就拥有目标对象的方法,同时又可以对其功能进行扩展。

动态代理

无需手写代理类,也不会存在代码编译的过程。运用在内存中生产代理类的技术在JVM的运行区造一个代理对象,只需对需要修改的部分进行编辑。

JDK 动态代理【接口】

CGLIB 动态代理【继承】

笔记大部分摘录自《Java核心技术卷I》,含有少数本人修改补充痕迹。

参考文章:http://gg.gg/12h2s6

相关文章
|
9天前
|
Java 开发者
重学Java基础篇—Java类加载顺序深度解析
本文全面解析Java类的生命周期与加载顺序,涵盖从加载到卸载的七个阶段,并深入探讨初始化阶段的执行规则。通过单类、继承体系的实例分析,明确静态与实例初始化的顺序。同时,列举六种触发初始化的场景及特殊场景处理(如接口初始化)。提供类加载完整流程图与记忆口诀,助于理解复杂初始化逻辑。此外,针对空指针异常等问题提出排查方案,并给出最佳实践建议,帮助开发者优化程序设计、定位BUG及理解框架机制。最后扩展讲解类加载器层次与双亲委派机制,为深入研究奠定基础。
32 0
|
9天前
|
机器学习/深度学习 人工智能 NoSQL
JAVA接入DeepSeek大模型接口开发---阿里云的百炼模型
随着大模型的越来越盛行,现在很多企业开始接入大模型的接口,今天我从java开发角度来写一个demo的示例,用于接入DeepSeek大模型,国内的大模型有很多的接入渠道,今天主要介绍下阿里云的百炼模型,因为这个模型是免费的,只要注册一个账户,就会免费送百万的token进行学习,今天就从一个简单的可以执行的示例开始进行介绍,希望可以分享给各位正在学习的同学们。
117 3
JAVA接入DeepSeek大模型接口开发---阿里云的百炼模型
|
3天前
|
数据采集 安全 数据挖掘
淘宝天猫宝贝详情页面商品评论采集接口全解析
淘宝天猫商品评论采集接口为电商数据挖掘提供了重要工具。通过分析海量评论,消费者可获取购买决策参考,商家能优化产品与服务,市场研究者则能洞察行业趋势与竞品表现。该接口支持Python请求,助力开发者构建智能分析应用,推动电商生态中各方价值提升。使用时需遵守平台规则,确保数据安全与合法利用。
55 15
|
8天前
|
存储 设计模式 Java
重学Java基础篇—ThreadLocal深度解析与最佳实践
ThreadLocal 是一种实现线程隔离的机制,为每个线程创建独立变量副本,适用于数据库连接管理、用户会话信息存储等场景。
39 5
|
9天前
|
存储 监控 安全
重学Java基础篇—类的生命周期深度解析
本文全面解析了Java类的生命周期,涵盖加载、验证、准备、解析、初始化、使用及卸载七个关键阶段。通过分阶段执行机制详解(如加载阶段的触发条件与技术实现),结合方法调用机制、内存回收保护等使用阶段特性,以及卸载条件和特殊场景处理,帮助开发者深入理解JVM运作原理。同时,文章探讨了性能优化建议、典型异常处理及新一代JVM特性(如元空间与模块化系统)。总结中强调安全优先、延迟加载与动态扩展的设计思想,并提供开发建议与进阶方向,助力解决性能调优、内存泄漏排查及框架设计等问题。
29 5
|
8天前
|
机器学习/深度学习 人工智能 Java
Java机器学习实战:基于DJL框架的手写数字识别全解析
在人工智能蓬勃发展的今天,Python凭借丰富的生态库(如TensorFlow、PyTorch)成为AI开发的首选语言。但Java作为企业级应用的基石,其在生产环境部署、性能优化和工程化方面的优势不容忽视。DJL(Deep Java Library)的出现完美填补了Java在深度学习领域的空白,它提供了一套统一的API,允许开发者无缝对接主流深度学习框架,将AI模型高效部署到Java生态中。本文将通过手写数字识别的完整流程,深入解析DJL框架的核心机制与应用实践。
29 2
|
9天前
|
安全 IDE Java
重学Java基础篇—Java Object类常用方法深度解析
Java中,Object类作为所有类的超类,提供了多个核心方法以支持对象的基本行为。其中,`toString()`用于对象的字符串表示,重写时应包含关键信息;`equals()`与`hashCode()`需成对重写,确保对象等价判断的一致性;`getClass()`用于运行时类型识别;`clone()`实现对象复制,需区分浅拷贝与深拷贝;`wait()/notify()`支持线程协作。此外,`finalize()`已过时,建议使用更安全的资源管理方式。合理运用这些方法,并遵循最佳实践,可提升代码质量与健壮性。
20 1
|
15天前
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
65 29
|
11天前
|
前端开发 数据安全/隐私保护 CDN
二次元聚合短视频解析去水印系统源码
二次元聚合短视频解析去水印系统源码
29 3
|
13天前
|
JavaScript 算法 前端开发
JS数组操作方法全景图,全网最全构建完整知识网络!js数组操作方法全集(实现筛选转换、随机排序洗牌算法、复杂数据处理统计等情景详解,附大量源码和易错点解析)
这些方法提供了对数组的全面操作,包括搜索、遍历、转换和聚合等。通过分为原地操作方法、非原地操作方法和其他方法便于您理解和记忆,并熟悉他们各自的使用方法与使用范围。详细的案例与进阶使用,方便您理解数组操作的底层原理。链式调用的几个案例,让您玩转数组操作。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

推荐镜像

更多