当前位置: 首页 > news >正文

Java开发 | 内部类 | 静态内部类 | 非静态内部类 | 匿名内部类

目录

1.内部类

1.1内部类的简单创建 

1.2内部类的分类

1.2.1普通内部类

1.2.2静态内部类

1.3匿名内部类

1.4局部内部类

1.内部类

内部类就是一是一个类里面装着另外一个类,就像俄罗斯套娃一样。最外层的类我们叫外部类,内层的类我们叫内部类


1.1内部类的简单创建 

内部类就是一个类中的包含的另外一个类我们称之内部类,内部类外面那个类我们称之为外部类。如以下代码:

//这是一个外部类
class OutClass {//这是一个普通内部类class NeiBuClass {}
}

以上代码中OutClass为外部类,NeiBuClass为内部类。这样的一段代码就构成了一个类包含另一个类,当然你也可以在一个类里面定义多个类。以上是对外部类与内部类的一个简单创建,详细讲解请看下方。


1.2内部类的分类

内部类可分为:静态内部类、实例内部类、匿名内部类、局部内部类。其中的局部内部类是在方法里面定义的类,几乎不用。匿名内部类是没有名称的类,也几乎不用。因此我们今天主要掌握前两种内部类,但后两种我们也会讲到。


1.2.1普通内部类

普通内部类是非静态内部类/实例内部类。它是没有任何修饰符修饰的一个内部类。它的语法格式为: class 类名。如以下代码展示:

//外部类
class OutClass { //普通内部类/非静态内部类class NeiBuClass {}
}

以上代码中OutClass为外部类,NeiBuCass为一个普通内部类,下面我就来讲解它的用法。

class OutClass {public int num1;private int num2;protected int num3;public void fun() {System.out.println("今天过得很开心!");}class NeiBuClass {public void show() {//外部类里的任何属性都内被内部类使用num1 = 1;num2 = 2;num3 = 3;System.out.println(num1+" "+num2+" "+num3);//访问外部类成员方法fun();}}
}
public class Test {public static void main(String[] args) {//实例化内部类前得先实例化外部类OutClass.NeiBuClass neiBuClass = new OutClass().new NeiBuClass();neiBuClass.show();}
}

运行后输出:

通过上述代码,我们可以看到外部类中的成员变量和成员方法都能被我们的普通内部类使用。无论外部类是被public还是private或者protected修饰都能使用。此外,我们在实例化内部类时,必须先实例化外部类。这样才能得到一个内部类引用。

因此我们有一个问题,在我们学习封装的时候知道了一个概念。一个类里面被private修饰的属性,不能在其他类中使用,比如:

class Try1 {private int num = 10;
}
class Try2 {num = 20;
}

报错:

那为什么在外部类与内部类的关系中,我们能使用呢?大家不必惊慌,这是语法所规定的。我们只需要知道这是一个特例就好了,可以放心使用。


注意,当我们外部类与内部类中有相同的属性时,我们优先访问内部类中的属性,如下代码:

class OutClass {//外部类成员变量public int num = 10;//外部类成员变量public void fun() {System.out.println("今天过得很开心!");}class NeiBuClass {//内部类成员变量public int num = 20;//内部类成员方法public void fun() {System.out.println("今天过得不开心!");}public void show() {//优先访问内部类自己的成员System.out.println(num);//优先访问内部类自己的方法fun();}}
}
public class Test {public static void main(String[] args) {//实例化内部类前得先实例化外部类OutClass.NeiBuClass neiBuClass = new OutClass().new NeiBuClass();neiBuClass.show();}
}

运行后输出:

如果我们非得访问外部类中的属性怎么办呢?我们可以用外部类名.this.属性名来访问外部类的属性。如:

class OutClass {public int num = 10;public void fun() {System.out.println("今天过得很开心!");}class NeiBuClass {public int num = 20;public void fun() {System.out.println("今天过得不开心!");}public void show() {//访问了外部类成员变量System.out.println(OutClass.this.num);//访问外部类成员方法OutClass.this.fun();}}
}public class Test {public static void main(String[] args) {//实例化内部类前得先实例化外部类OutClass.NeiBuClass neiBuClass = new OutClass().new NeiBuClass();neiBuClass.show();}
}

运行后输出:

通过以上代码,很好的展示了通过外部类名.this.外部属性名就能访问到外部类中的属性。


那么我们的外部类能不能访问内部类中的成员变量或方法呢?我们来看一组代码:

class OutClass {//外部类成员变量public int num1 = 10;//外部类成员方法public void show() {fun();System.out.println(num2);}class NeiBuClass {//内部类成员变量public int num2 = 20;//内部类成员方法public void fun() {System.out.println("今天过得很开心!");}
}

报错: 

因此,外部类不能直接访问内部类中的属性,如果我们要访问的化,可以创建一个内部类对象。通过引用这个对象就可以访问内部类中的属性,如下代码:

class OutClass {//实例化了内部类的一个对象NeiBuClass neiBuClass = new NeiBuClass();//外部类成员变量public int num1 = 10;//外部类成员方法public void show() {neiBuClass.fun();System.out.println(neiBuClass.num2);}class NeiBuClass {//内部类成员变量public int num2 = 20;//内部类成员方法public void fun() {System.out.println("今天过得很开心!");}}
}public class Test {public static void main(String[] args) {OutClass outClass = new OutClass();outClass.show();}
}

运行后输出:

以上代码展示了,在外部类访问内部类的方法就是实例化内部类出一个对象即可访问内部类属性。

总结

  • 外部类的属性可以在内部类中使用(实例内部类所处的位置与外部类成员位置相同,因此也受public、private等访问限定符的约束)
  • 当外部类的属性与内部类中的属性同名时,在内部类中使用该属性时会优先访问内部类中该属性
  • 在内部类中访问同名属性时,可以使用外部类名.this.属性名来访问外部类属性
  • 实例化内部类时,必须先实例化外部类(借助外部类来访问内部类)
  • 外部类不能直接访问内部类中的属性,必须得实例化一个内部类对象才可访问

1.2.2静态内部类

静态内部类是由static修饰的类,它的语法格式为:static class 类名。下面我们来看代码:

//外部类
class OutClass {//静态内部类static class NeiBuClass {}
}

以上代码就是一个静态内部类的创建方式,下面我们来看它的用法。当我们直接在静态内部类访问外部类中的非静态属性时是访问不到的,我们只能访问静态的成员属性。因为静态不依赖于类。

//外部类
class OutClass {//外部类成员public int num1 = 10;private int num2 = 10;protected int num3 = 20;public static int num4 = 30;//静态内部类static class NeiBuClass {public void show() {//num1-num3不能直接访问System.out.println(num1);System.out.println(num2);System.out.println(num3);System.out.println(num4);}}
}

报错:

因此,如果我们要在静态内部类中访问外部类中的非静态属性的话,我们要先实例化一个外部类对象。通过引用来访问外部类中的非静态属性,如以下代码:

//外部类
class OutClass {//外部类成员public int num1 = 10;private int num2 = 20;protected int num3 = 30;public static int num4 = 40;//静态内部类static class NeiBuClass {public void show() {//实例化一个外部类对象OutClass outClass = new OutClass();//通过外部类对象来引用外部类属性System.out.println(outClass.num1);System.out.println(outClass.num2);System.out.println(outClass.num3);System.out.println(num4);}}
}public class Test {public static void main(String[] args) {//创造一个静态内部类对象OutClass.NeiBuClass neiBuClass = new OutClass.NeiBuClass();neiBuClass.show();}
}

运行后输出:

以上代码展示了静态内部类如何访问外部类中的非静态成员。我们在类和对象中学到了,一个类中的静态成员我们可以直接使用类名来访问该成员。因此在上述实例化静态内部类时,我们不用像普通内部类那样得先实例化外部类在实例化内部类。我们直接通过外部类引用静态内部类来创建一个静态内部类对象。


外部类访问静态内部类:

//外部类
class OutClass {//实例化一个惊天内部类对象NeiBuClass neiBuClass = new NeiBuClass();//外部类方法public void show() {System.out.println(neiBuClass.num1);System.out.println(neiBuClass.num2);System.out.println(neiBuClass.num3);neiBuClass.fun();}//静态内部类static class NeiBuClass {//静态内部类中的成员变量int num1 = 1;int num2 = 2;int num3 = 3;//静态内部类中的方法public void fun() {System.out.println("今天天气很糟糕!");}}
}public class Test {public static void main(String[] args) {//实例化一个外部类对象OutClass outClass = new OutClass();//引用外部类中的show方法outClass.show();}
}

运行后输出:

以上代码展示了外部类访问静态内部类属性的方法,就是实例化一个静态内部类对象即可访问。

总结:

  • 静态内部类无法访问外部类中的非静态成员变量或成员方法
  • 静态内部类要访问外部类中非静态属性时可创建一个外部类对象来访问
  • 静态属性不依赖于类,因此可以使用类名来引用静态属性
  • 外部类想访问静态内部类属性时,可以实例化一个静态内部类对象即可访问
  • 静态内部类不能直接实例化,要通过外部类名的引用来实例化

1.3匿名内部类

匿名内部类,简单的来说就是没有类名的内部类。一般在是在接口对象中定义的内部类。

//定义一个名为IUSB的接口
interface IUSB {void show();
}
//Try类使用了这个接口
class Try implements IUSB{//重写了接口中的show方法@Overridepublic void show() {System.out.println("今天你开心吗?");}
}public class Test {public static void main(String[] args) {//new一个接口new IUSB() {@Overridepublic void show() {System.out.println("这就是一个匿名内部类");}}.show();}
}

运行后输出:

以上代码展示了,匿名类内部类的用法。这种内部类我们几乎不用,大家可以看到我们必须在一个接口中定义一个方法,并且要有一个类使用这个接口并实现重载接口中的方法才能达到这个方法的可用性,然后我们再才能new一个接口对象这个对象没有类名没有修饰,这就是匿名内部类。可见这种内部类我们使用的非常之少。


1.4局部内部类

局部内部类是在方法里面的定义的类,例如:

public class Test {//一个名为show的方法public void show() {//这是一个局部内部类class Dog {//局部内部类的成员变量public int num = 10;//局部内部类中的成员方法public void fun() {System.out.println("这是局部内部类中的fun()方法");}}//实例化一个局部内部类对象Dog dog = new Dog();//通过dog引用来方法这两个属性System.out.println(dog.num);dog.fun();}public static void main(String[] args) {//再通过实例化一个主类才能调用show方法Test test = new Test();test.show();}
}

运行后输出:

我们发现,在一个方法里面定义一个类然后去创建一些属性我们还得在这个方法中实例化对象和main方法中实例化对象才能访问到这些属性,真是脱裤子放弃多费手续。因此,这种内部类我们也是不怎么常用的。


好了,今天的博文到这里就结束了,感谢你的阅读。

 下期预告:图书管理系统的实现、通讯录的实现

相关文章:

Java开发 | 内部类 | 静态内部类 | 非静态内部类 | 匿名内部类

目录 1.内部类 1.1内部类的简单创建 1.2内部类的分类 1.2.1普通内部类 1.2.2静态内部类 1.3匿名内部类 1.4局部内部类 1.内部类 内部类就是一是一个类里面装着另外一个类,就像俄罗斯套娃一样。最外层的类我们叫外部类,内层的类我们叫内部类。 1…...

Portal认证

Portal认证Portal认证简介Portal认证协议Portal认证方式Portal认证流程Portal认证用户下线Portal认证简介 定义: Portal认证通常也称作Web认证,一般将Portal认证网站成为门户网站。用户上网时,必须在门户网站进行认证,如果没有认…...

论文解读:ChangeFormer | A TRANSFORMER-BASED SIAMESE NETWORK FOR CHANGE DETECTION

论文地址:https://arxiv.org/pdf/2201.01293.pdf 项目代码:https://github.com/wgcban/ChangeFormer 发表时间:2022 本文提出了一种基于transformer的siamese网络架构(ChangeFormer),用于一对共配准遥感图…...

Redis 内存优化技巧

这次跟大家分享一些优化神技如何用更少的内存保存更多的数据?我们应该从 Redis 是如何保存数据的原理展开,分析键值对的存储结构和原理。从而继续延展出每种数据类型底层的数据结构,针对不同场景使用更恰当的数据结构和编码实现更少的内存占用…...

【java】笔试强训Day2【​倒置字符串​与排序子序列】

目录 ⛳选择题 1.A 派生出子类 B , B 派生出子类 C ,并且在 java 源代码有如下声明: 2.下面代码将输出什么内容:( ) 3.阅读如下代码。 请问,对语句行 test.hello(). 描述正确的有&…...

【Linux】基础IO(一) :文件描述符,文件流指针,重定向

🍎作者:阿润菜菜 📖专栏:Linux系统编程 码字不易,请多多支持😘😘 这是目录重新认识文件系统内部的文件操作我们C语言的文件操作系统内部的文件操作OS一般会如何让用户给自己传递标志位的&#x…...

【C语言】通讯录的实现(静态版)

【C语言】通讯录的实现(静态版一.前言1.前期准备a.菜单实现b.联系人结构体的构建c.菜单选项的功能d.#define 的定义2.功能的实现a.初始化通讯录b.增加联系人c.显示通讯录d.查找联系人e.修改联系人d.删除联系人3. 总代码test.ccontact.ccontact.h一.前言 本文将会用c语言实现一…...

IDEA一键构建Docker镜像

效果 Idea右击Dockerfile文件,直接在服务器构建docker镜像 开整 1、下载docker插件 2、编写Dockerfile文件 # 基础镜像 FROM openjdk:8-jdk-alpine # 工作目录 WORKDIR /opt/apps/gateway/logs/ # 文件拷贝,把target目录下的jar报拷贝到镜像的/APP/目录下 ADD…...

QT的使用3:鼠标事件

鼠标事件0 事件1 需求2 查看控件的事件处理函数3 UI设计4 新建一个类,继承QLabel5 对已有对象进行类型提升6 重写事件处理函数7 项目进一步拓展(1)获取鼠标按键(2)鼠标移动(3)显示多个按键&…...

线程安全之单例模式

文章目录前言一.什么是单例模式二.在java中的单例模式2.1 饿汉式的介绍2.2 懒汉式的介绍三 懒汉式的单例模式,线程不安全的解决方式3.1 造成线程不安全的原因3.2 解决方案3.3 总结前言 这篇文章,我们会介绍一下单例模式,但这里的单例模式,不是我们所说的设计模式,当然听到设计…...

“二分”带来“十分”快感——二分思想的奥秘解析

文章目录无处不在的二分思想二分查找惊人的查找速度二分查找的递归与非递归实现1.循环退出条件2.mid的取值3.low和high的更新最后说一句🐱‍🐉作者简介:大家好,我是黑洞晓威,一名大二学生,希望和大家一起进…...

一台服务器最大能支持多少条 TCP 连接?问倒一大片。。。

一台服务器最大能打开的文件数 限制参数 我们知道在Linux中一切皆文件,那么一台服务器最大能打开多少个文件呢?Linux上能打开的最大文件数量受三个参数影响,分别是: fs.file-max (系统级别参数)&#xf…...

蓝桥杯嵌入式RTC实时时钟

文章目录 前言一、RTC是什么二、cubemx的配置三、函数的使用总结前言 本篇文章将给大家介绍RTC实时时钟。 一、RTC是什么 STM32的实时时钟RTC是一个独立的定时器,RTC时钟内部依靠BCD码计数。RTC实时时钟提高时钟、闹钟、日历功能。RTC功耗较低,可以使用在低功耗设备上。 …...

Centos7 挂载 ISO镜像

切到mnt目录:cd /mnt mkdir iso确保centos镜像在服务上存在,磁盘挂载mount -o loop /home/xx.iso /mnt/iso查看是否挂载成功df -h出现红色的部分表示挂载成功修改源切目录并修改yum源:cd /etc/yum.repos.dllvim Centos-Base.repo修改后yum clean allyum list安装lrz…...

三级数据库备考--数据库应用系统开发方法第一次练习(刷题库知识点记录)

1.数据库的三级模式由外模式、模式、内模式构成。外模式是用户可见的部分数据的存在形式;模式可以等价为全体数据的逻辑结构且用户不可见,是三级模式的中间部分;内模式对应数据库的物理结构和存储方式。当模式改变时,由数据库管理…...

免费空间主机是什么?怎么申请免费空间主机

随着网络的普及,越来越多的人开始使用免费空间。这种新的商业模式也让一些商家得以获利。 1:免费空间的概念 免费空间是指允许您自由使用的网络服务。这意味着它可以被任何人用来创建、编辑和发布网站内容或应用程序,而无需考虑任何付费业务协…...

网络安全文章汇总导航(持续更新)

网络安全文章汇总导航(持续更新)1.基础篇(已完结):2.工具篇(持续更新):3.靶场安装(持续更新,但不确定):4.权限提升(持续更…...

AI-TestOps —— 软件测试工程师的一把利剑

写在前面软件测试的前世今生测试工具开始盛行AI-TestOps 云平台● AI-TestOps 功能模块● AI-TestOps 自动化测试流程写在前面 最近偶然间看到一句话:“软件测试是整个 IT 行业中最差的岗位”。这顿时激起了我对软件测试领域的兴趣,虽然之前未涉及过软件…...

Linux内核进程管理原理详解

前言:Linux内核里大部分都是C语言。建议先看《Linux内核设计与实现(Linux Kernel Development)》,Robert Love,也就是LKD。Linux是一种动态系统,能够适应不断变化的计算需求。Linux计算需求的表现是以进程的通用抽象为中心的。进程可以是短期…...

通过Linux串口实现树莓派与电脑通信

目录 一 串口说明 二 USB—TTL模块 ● usb-ttl模块接口 三 串口通信常用的API 四 修改串口的配置文件 五 串口通信代码验证 ● 发送一个字符/字符串到串口 ● 树莓读取串口数据(字符) ● 代码拓展(双方) 一 串口…...

全球变暖 蓝桥杯 178

题目描述你有一张某海域 NxN 像素的照片,"."表示海洋、"#"表示陆地,如下所示:........##.....##........##...####....###........其中"上下左右"四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有 2 座…...

Java现在好找工作吗?

Java到2023年已经28岁了,可能你会怀疑它是否还一如当年一样的强大,在应用层领域独占鳌头。但是基于Java庞大的市场占有率和需求,它依然在保持着更新迭代,依然是最常用的底层开发语言,基于其安全性、开放性、稳定性和跨…...

Flink 第1章 基础介绍和特性

一 Flink概念 1.1 Flink的概念 Flink是一个框架和分布式处理引擎,用于对无界和有解数据流进行状态计算。如下图所示: 1.2 Flink的应用场景 1.3 Flink的目标 1.高吞吐量 2.低延迟 3,结果的准确性和良好的容错性。 1.4 Flink与spark的区别…...

docker 安装 nginx无坑版

一. 拉取镜像 docker pull nginx二. 创建挂载目录 mkdir -p /usr/local/nginx/conf mkdir -p /usr/local/nginx/log mkdir -p /usr/local/nginx/html三. 从nginx容器里复制nginx的配置文件到主机里 创建个容器 docker run --name nginx -p 80:80 -d nginx将容器内的配置文件…...

自己动手做chatGPT:向量的概念和相关操作

chatGPT的横空出世给人工智能注入一针强心剂,它是历史上以最短时间达到一亿用户的应用。chatGPT的能力相当惊人,它可以用相当流利的语言和人对话,同时能够对用户提出的问题给出相当顺畅的答案。它的出现已经给各个行业带来不小冲击&#xff0…...

【洛谷刷题】蓝桥杯专题突破-深度优先搜索-dfs(7)

目录 写在前面: 题目:P1596 [USACO10OCT]Lake Counting S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题目描述: 输入格式: 输出格式: 输入样例: 输出样例: 解题思路: …...

Python嵌套函数(Nested function)和闭包(closure)

Python嵌套函数(Nested function)和闭包(closure) 闭包(closure)是建立在嵌套函数基础上的,是一种特殊的嵌套函数结构。 先看嵌套函数(Nested function)。 Python允许…...

【实战】React 必会第三方插件 —— Cron 表达式生成器(qnn-react-cron)

文章目录一、引子二、配置使用1.安装2.使用(1)直接调用(2)赋值到表单(Form)(3)自定义功能按钮(4)隐藏指定 Tab(5)其他三、常见问题及解…...

C# 教你如何终止Task线程

我们在多线程中通常使用一个bool IsExit类似的代码来控制是否线程的运行与终止,其实使用CancellationTokenSource来进行控制更为好用,下面我们将介绍CancellationTokenSource相关用法。C# 使用 CancellationTokenSource 终止线程使用CancellationTokenSo…...

整合SpringCache

整合SpringCache 1、引入依赖cache还有redis <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId> </dependency>2、写配置 spring:cache:type: redis3、测试使用缓存 Cache…...