内部类

内部类:将一个类的定义放在另一个类的定义内部。内部类机制可以把逻辑相关的类组织在一起,并控制位于内部的类的可视性。

内部类与组合是完全不同的概念。

内部类不仅是一种代码隐藏机制(将类置于其他类的内部),还能与外围类通信。

类似于外围类的成员的内部类。

2-1 链接到外部类

内部类可以访问其外围类的 所有字段和方法(所有成员)。创建一个普通内部类对象需要先创建其外围类的对象,然后使用该外围类对象取创建内部类对象。当某个外围类创建了一个内部类对象时,此内部类对象必定会秘密地捕获一个指向那个外围类对象的引用。然后就可使用这个引用来访问外围类对象的成员。

运行结果为:

2-2 使用 外围类名.this

如果需要在内部类中获取外围类对象的引用,可以使用 外围类名.this 来获取

运行结果为:

2-3 使用 外围类对象.new

要直接创建普通内部类对象,必须使用外围类的对象来创建该内部类对象。这也解决了内部类名字作用域的问题,即使用外围类对象只能创建定义在外围类中的内部类的对象。

因此,就不必声明(也不能声明)外围类的类名,如inner = dot.new DotNew.Inner();

在拥有外围类对象之前是不可能创建内部类对象的。这是因为内部类对象会暗暗地连接到创建它的外围类对象上。但是,如果你创建的是嵌套类(静态内部类),那就不需要先创建外围类对象。

2-4 外围类访问内部类

先看一下内部类访问外围类成员的方式:如果想要访问外围类的某个成员,直接使用外围类这个成员的名字就可以。

但是,如果外围类要访问内部类的成员的话就不能使用这种方式(即直接使用内部类成员的名字):

正确的方式应该先创建内部类的对象再通过此对象去访问:

内部类可以直接通过外围类的成员名去访问外围类成员,而外围类需要通过内部类的对象去访问内部类成员。造成这种差别的原因可能是:

在使用内部类对象时,可保证其外围类对象一定被创建了,且内部类对象一定有一个指向其外围类对象的引用,所以内部类可以通过成员名直接访问(可能编译器会在成员名前自动拼接 外围类对象引用.);而在使用外部类对象时,并不能保证内部类对象一定被创建了,所以需要先创建内部类对象,然后通过这个内部类对象去访问内部类成员。

可以在一个方法里面或在任意作用域(方法的作用域:if(isOk){作用域}、类的作用域)中定义内部类。这么做有两个理由:

3-1定义在方法中的类

在方法的作用域内(而不是在其他类的作用域内)创建一个完整的类,这被称作局部内部类。

运行结果为:

注意:

1.PDestination类是destination方法的一部分,而不是Parcel5的一部分。所以,在destination()之外不能访问PDestination;

2.在destination()方法中定义了内部类PDestination,并不意味着一旦destination()方法执行完毕,PDestination就不可用了。

3-2定义在方法内作用域中的类

TrackingSlip类被嵌入在if语句的作用域内,这并不是说该类本身的创建是有条件的,它其实会与其他类一起被编译。然而,在定义TrackingSlip的作用域之外,它是不可用的;除此之外,它与普通类一样。

3-3实现了接口的匿名内部类

return语句的含义为:创建一个实现(继承)了Contents接口(类)的匿名类对象。

3-4扩展了有非默认构造器的类的匿名内部类

有非默认构造器的类Wrapping

匿名类Parcel8扩展Wrapping类

运行结果为:

目前来看,定义匿名内部类的方式为:

1.当是 new 接口名()时,创建的就是一个实现类对象;

2.当是 new 基类名(基类构造器的参数)时,创建的是一个子类对象,但在创建子类对象中包含的基类对象时调用的就是new关键字后 指定的基类构造器

3-5执行字段初始化的匿名内部类

在匿名类中定义字段时,还能够对其执行初始化操作。

运行结果为:

如果定义一个匿名内部类,并且希望它使用一个在其外部定义的对象(可以是方法传入的参数,也可以是外围类的成员),那么编译器会要求 这个对象是final的。

注:匿名内部类(子类)本身使用外部对象才要求是final的,但如果只是基类使用而匿名内部类自身不使用,则不需要是final的。

上面的例子中的匿名内部类使用的在其外部定义的对象是通过方法的参数传入的,也可以直接使用外围类的成员(private成员默认是final的)。

运行结果为:

3-6通过实例化实现构造的匿名内部类

匿名类因为没有名字,所以不可能有构造器。

通过实例初始化(本质就是通过 普通代码块),就能达到为匿名内部类创建一个构造器的效果。

运行结果为:

匿名内部类与正规的继承相比有些受限,因为匿名内部类 既可以扩展类,也可以实现接口,但是不能两者兼备。而且如果是实现接口,也只能实现一个接口。

如果不需要内部类对象与其外围类对象之间有联系,那么可以将内部类声明为static。这通常称之为嵌套类或者静态内部类。

普通的内部类对象隐式地保存了一个引用,指向它的外围类对象。而嵌套类对象就没有这个引用,这意味着:

普通的内部类中不能有static数据和static字段,也不能包含嵌套类(也是static的),但是嵌套类可以包含这些静态的东西。其原因可认为是:

普通内部类可看作是外围类的非静态成员,要求它的初始化必须在其外围类对象创建之后进行。在创建内部类对象的时候,会先加载外围类,再加载内部类。类加载完成后就会初始化类的静态成员,如果内部类有静态成员,那么就会在类加载后初始化内部类的静态成员,但这个时候其外围类对象还未创建,这与要求冲突。所以不允许普通内部类包含静态成员。

这个例子中还有一个需要注意的地方:外围类能直接访问静态内部类的静态私有成员(构造器)。所以总结一下外围内访问内部类的规律:

4-1接口中的类

接口中的变量默认是public static final的;

接口中的方法默认是public的;

接口中的类默认是public static的,也就是说,接口中的类默认是静态内部类。

运行结果为:

Original: https://www.cnblogs.com/certainTao/p/14844775.html
Author: certainTao
Title: 内部类

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/711169/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • DNS解析流程

    DNS简单来说就是进行域名和IP的转换,那该如何转换呢?既然要转换,肯定有转换表,那表应该存哪个服务器上,怎样去请求域名服务器来进行转换,所以,这个转换的过程都是什么。而面试的时经…

    技术杂谈 2023年6月21日
    0103
  • ansible -自动运维工具

    Ansible-自动运维工具 1.简介 Ansible是一个基于Python开发的配置管理和应用部署工具,现在也在自动化管理领域大放异彩。它融合了众多老牌运维工具的优点,Pubbe…

    技术杂谈 2023年7月10日
    087
  • 自动安装驱动程序

    关于 驱动程序安装,只要你细心看了ddk,就应该知道怎样做对于即插即用简单地说要对付2种情况1。在你的设备未安装前,安装 驱动程序这叫预先安装。最简单的方法就是使用SetupCop…

    技术杂谈 2023年5月31日
    084
  • CESIUM 原理 之 COMMAND拼接【转】

    VAO VAO(Vertext Array Object),中文是顶点数组对象。之前在《Buffer》一文中,我们介绍了Cesium如何创建VBO的过程,而VAO可以简单的认为是基…

    技术杂谈 2023年5月31日
    0106
  • Python3中datetime不同时区转换介绍与踩坑

    最近的项目需要根据用户所属时区制定一些特定策略,学习、应用了若干python3的时区转换相关知识,这里整理一部分记录下来。 下面涉及的几个概念及知识点: GMT时间:Greenwi…

    技术杂谈 2023年6月21日
    072
  • [CSS] css使用first-child 和last-child 实现三条杠效果

    first-child 和last-child是伪类选择器,选择第一个和选择最后一个子元素 现在实现下面的效果 class="menuico"> .men…

    技术杂谈 2023年6月1日
    079
  • Flink CDC同步MySQL数据到Iceberg实践

    Flink CDC: 捕获数据库完整的变更日志记录增、删、改等所有数据. Flink在1.11版本开始引入了Flink CDC功能,并且同时支持Table & SQL两种形…

    技术杂谈 2023年7月10日
    087
  • 【转】iPhone is not available. Please reconnect the device

    原文网址:https://blog.csdn.net/baidu_40537062/article/details/107396905 我的手机是iOS13.5,Xcode是11….

    技术杂谈 2023年6月1日
    088
  • 【软考】信息系统开发方法

    1.结构化方法 结构是指系统内各个组成要素之间的相互联系、相互作用的框架。架构化方法也称为生命周期法,是一种传统的信息系统开发方法,由结构化分析(Structured Analys…

    技术杂谈 2023年5月31日
    079
  • 部署-gitlab克隆地址踩坑

    gitlab克隆地址踩坑 gitlab中的web界面的默认端口是80,ssh端口为22端口。而一般情况下,我们的服务器或者本地电脑 已经占用了这俩个端口,那么我们就需要进行端口映射…

    技术杂谈 2023年7月23日
    077
  • python-数据描述与分析(1)

    数据描述与分析 在进行数据分析之前,我们需要做的事情是对数据有初步的了解,这个了解就涉及对行业的了解和对数据本身的敏感程度,通俗来说就是对数据的分布有大概的理解,此时我们需要工具进…

    技术杂谈 2023年7月25日
    0109
  • K8S的安装部署以及基础知识

    Kubernetes(K8S)概述 Kubernetes又称作k8s,是 Google在2014年发布的一个开源项目。 最初Google开发了一个叫 Borg的系统(现在命名为Om…

    技术杂谈 2023年7月11日
    078
  • 迷宫问题详解(数据结构实验)

    实验项目 2: 栈结构及其应用 实验题目: 迷宫问题求解 实验内容: 一个迷宫可以看成是由 m × n 个房间组成的矩形,迷宫内部的每个房间有 4个方向,每个方向或者有障碍(如墙)…

    技术杂谈 2023年7月11日
    0123
  • Linux学习笔记(一)初识Linux

    初始Linux Linux可划分为以下四部分: Linux内核 GNU工具 图形化桌面环境 应用软件 每一部分在Linux系统中各司其职,下图是各部分对应关系: 1、Linux内核…

    技术杂谈 2023年7月11日
    073
  • 解决Visual Studio Code无法响应的问题

    最近发现我的Visual Studio Code总是莫名其妙的无响应,具体症状是:打开VS Code一段时间后,通过右键菜单打开Visual Studio Code新文件的时候,无…

    技术杂谈 2023年5月31日
    0105
  • 汇编语言学习记录一

    0x00——什么是汇编语言? 汇编语言:早期实现程序员和机器进行交互的汇编指令集。 汇编指令,通过编译器,转换成机器码,从而使 机器 理解其指令。 0x01——汇编语言的组成 汇编…

    技术杂谈 2023年6月21日
    098
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球