java的四种内部类,从0讲清楚

什么是内部类?

为什么要学习内部类?

可以发现,发动机虽然跟汽车相关,但发动机不像车龄或颜色一样,只用一个变量就可以描述,而是要有发动机品牌,发动机年限,多个变量描述发动机。那么这样写Car类是不合适的

所以要用上内部类描述发动机

内部类的访问特点

1.内部类可以直接访问外部类,包括私有

2.外部类要访问内部类,必须创建对象

这里的this指针用法要复习一下,

如果Car.this没写,this.carName直接写成carName也是没错的,因为就算不写编译器也会自动添加this关键字。这个过程被称为隐式引用。

内部类的分类

成员内部类

举个例子

可以看到,我们把内部类理解当成成员属性就好了。

1.成员内部类的修饰符

着重介绍一个,private修饰成员内部类,怎么理解呢?

把他当成成员变量一样就好了。即只能在类内(Car类里)访问,只能在外部类内实例化对象(比如说第二个红框的位置),外部类以外是操作不到的

那如果用static修饰成员内部类呢?实际上这就叫静态内部类了,后面会介绍

2.获取成员内部类的对象

实例化方法1:

class Outer{
	class Inner{
		;
	}
	
}

public class Main {
	
	public static void main(String[] args) {
		Outer o = new Outer();
		Outer.Inner io1 = o.new Inner();
		
		//可以简写成这样
		Outer.Inner io2 = new Outer().new Inner();
		
   }
}

实例化方法2:

如果成员内部类是私有的,外部就访问不到了,就不能用方法1来实例化对象

要怎么改呢?写一个对外提供内部类的方法

class Outer{
	private class Inner{
		;
	}
	
	public Inner getInner() {//对外提供Inner
		return new Inner();
	}
	
}

如何接收呢?

这样是错的

下面是对的

或者直接使用也可以。此处打印的是地址

静态内部类

1)注意:静态内部类只能访问外部类中的静态变量和静态方法,如果想要访问非静态的,需要创建对象。

2)创建静态内部类的格式:外部类名.内部类名 对象名 = new 外部类名.内部类名()。因为是静态的,所以就不用先创建一个外部类对象,再创建内部类。

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

3)调用非静态方法的格式:先创建内部类的对象,用对象调用

4)调用静态方法的格式:外部类名.内部类名.方法名()

只要是静态的东西,都可以用类名点直接获取!

对于(1)

class Outer{
	int a = 10;
	static int b = 20;
	
	static class Inner{
		public void show1() {
			
			System.out.println(new Outer().a);//此时是报错的,因为不能直接访问非静态的变量
			System.out.println(b);//但是b可以,因为b是静态的
		}
		
		static public void show2() {
			System.out.println(new Outer().a);
			System.out.println(b);
		}
		
	}
	
}


public class Main {
    public static void main(String[] args){
    	Outer o = new Outer();
    	Outer.Inner io = new Outer.Inner();
    	io.show1();
    	Outer.Inner.show2();
    	
    	
    }
  
}

局部内部类

1)将内部类定义在方法里就叫局部内部类,类似与方法里的局部变量

2)外界是无法直接使用的,要在方法内部创建并调用。

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

class Outer{
	int a = 10;
	void show() {
		int b = 20;
		class Inner{//注意!把局部内部类当成局部变量就行了!
			        //public等修饰符不能修饰局部变量,那么也不能修饰局部内部类
			public void test1() {
				System.out.println(a);
				System.out.println(b);
			}
			
		}
		Inner i = new Inner();
		i.test1();
		
	}
	
}


public class Main {
    public static void main(String[] args){
    	Outer o = new Outer();
    	o.show();
    	
    	
    }
  
}

匿名内部类

怎么写匿名内部类?

interface Swim{
	public void swim();
}

abstract class Animal{
	abstract void eat();
}



public class Solve {
	public static void main(String[] args) {
		
		//编写匿名内部类代码
		
		new Swim(){//Swim是接口,这里是实现关系
			public void swim() {
				System.out.println("重写swim");
			}
		};
		
		new Animal() {//Animal是类,这里是继承关系

			@Override
			void eat() {
				// TODO Auto-generated method stub
				System.out.println("重写eat");
			}
			
		};
		
		
	}
	
}

进一步了解什么是匿名内部类

实际上,红圈内的内容才是匿名内部类,因为它是没有名字的。

而蓝圈在做的是是创建一个匿名内部类

为什么要学习匿名内部类?


class Animal{
	void shout() {}
}
class Dog extends Animal{

	@Override
	void shout() {
		// TODO Auto-generated method stub
		System.out.println("dog is barking");
	}
	
}



public class Main {
	public static void method(Animal a) {//多态
		a.shout();
	}

    public static void main(String[] args){
    	//假设我们现在要调用method函数实现dog的行为,该怎么办呢?
    	//以前的方法:
    	//创建一个狗的类,实例化一个狗的类,类内重写方法
    	Dog d = new Dog();
    	method(d);
    	
    	//以前的方法有点麻烦,因为如果我们只需要使用一次dog,那么单独再写一个Dog类就太麻烦了
    	//所以可以用匿名内部类,用完一次就丢。
    	//跟以前的办法相比,这个只要重写并创建匿名对象就行了
    	method(
    			new Animal(){
    				void shout() {
    					System.out.println("dog2 is barking");
    				}
    			}
    			
    			
    	);
    	
    }
}

匿名内部类的一些实用小技巧

1.创建的对象可以被接收

class Animal{
	void shout() {}
}




public class Main {
	public static void method(Animal a) {//多态
		a.shout();
	}

    public static void main(String[] args){
    	
    	//我们知道,new Animal()其实是创建对象的过程,只不过是匿名的
    	//那么我们可不可以用一个对象来接收呢?可以!
    	//那这样有什么好处呢?
    	//这样我们就不用单独再写一个Dog类,省去了不必要的类,
    	//而且调用比上一段代码更灵活(个人感觉)
    	Animal a =  new Animal(){
    		//注意,因为经过重写,所以实际上是创建了一个子类的对象
    		//但这里用父类的对象接收,所以这里也是多态!
			void shout() {
				System.out.println("dog is barking");
			}
		};
    	
		method(a);
		method(a);
		method(a);
    	//...
		//想用几次就用几次,代码比上一段简洁一些
    			
    	
    }
}

2.直接调用方法

public class Main {
	

    public static void main(String[] args){	
    	new Animal(){
			void shout() {
				System.out.println("dog is barking");
			}
		}.shout();//还可以这样去调用方法
    	
		
    			
    	
    }
}

小结

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

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

相关文章

从“芯”到云,看亚马逊云科技如何让未来“平等”发生

文章目录 业界最全面算力选择,有效解决多样性需求多年自研芯片积累,带来性能与性价比双重优势全球基础设施与独特的业务模式,让创新不受限 “科幻作家威廉吉布森说‘未来已至,只是还没有均匀分布’。”2023年6月底,当亚…

【开源存储】minio对象存储部署实践

文章目录 一、前言1、介绍说明2、部署方式3、冗余模式4、约束限制4.1、规格参数4.2、API支持a、minio不支持的Amazon S3 Bucket APIb、minio不支持的Amazon S3 Object API 二、部署说明1、软件安装2、minio单机部署3、minio分布式部署3.1、前置条件3.2、开始运行3.3、操作说明 …

Linux 进程(三)

Linux进程状态的查看: 这是Linux内核源代码对于进程状态的定义: R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。 S睡眠状态(sleeping): 意味着进程在…

ipvlan介绍

最近使用docker,涉及到需要跨多台物理机部署系统,查了好多资料,最后查到了ipvlan。那什么是vlan,什么又是ipvlan。 交换机层面的vlan,是按802.1Q规范,在链路层中加了4字节的标识vlan的数据,交换…

如何在WordPress中批量替换图片路径?

很多站长在使用WordPress博客或者搬家时,需要把WordPress文章中的图片路径进行替换来解决图片不显示的问题。总结一下WordPress图片路径批量替换的过程,方便有此类需求的站长们学习。 什么情况下批量替换图片路径 1、更换了网站域名 有许多网站建设初期…

灯光开不了了,是不是NVIDIA的问题

如果你跟我一样灯光亮度调节不了了,然后显示适配器又没有了,你看一下是不是和我这个大怨种一样把NVIDIA卸了,为了这个东西,这屏幕亮瞎我的眼镜😢😢。只需要进入官网,你就可以直接找到&#xff0…

SSM框架(五):Maven进阶

文章目录 一、分模块开发1.1 分模块开发的意义1.2 步骤 二、依赖管理2.1 依赖传递2.2 可选依赖和排除依赖 三、继承与聚合3.1 聚合3.2 继承3.3 聚合和继承区别 四、属性4.1 pom文件的依赖使用属性4.2 资源文件使用属性 五、多环境开发六、跳过测试七、私服7.1 下载与使用7.2 私…

前端面试灵魂提问(1)

1.自我介绍 2.在实习中,你负责那一模块 3.any与unknow的异同 相同点:any和unkonwn 可以接受任何值 不同点:any会丢掉类型限制,可以用any 类型的变量随意做任何事情。unknown 变量会强制执行类型检查,所以在使用一个…

Redis RDB

基于内存的 Redis, 数据都是存储在内存中的。 那么如果重启的话, 数据就会丢失。 为了解决这个问题, Redis 提供了 2 种数据持久化的方案: RDB 和 AOF。 RDB 是 Redis 默认的持久化方案。当满足一定条件的时候, 会把当前内存中的数据写入磁盘, 生成一个快照文件 dump.rdb。Redi…

各类声音数据集大合集—乐器、车辆、鸟鸣、蜜蜂声音、歌曲、喇叭、人类声音不同等类型的声音数据集

最近收集了一大波关于各类声音的数据集,包含乐器、车辆、鸟鸣、蜜蜂声音、歌曲、喇叭、人类声音不同等类型的声音数据集,废话不多说,给大家逐一介绍!! 1、吉他和弦大调、小调数据集 吉他和弦大调、小调数据集&#x…

Hive数据倾斜之:数据类型不一致导致的笛卡尔积

Hive数据倾斜之:数据类型不一致导致的笛卡尔积 目录 Hive数据倾斜之:数据类型不一致导致的笛卡尔积一、问题描述二、原因分析三、精度损失四、问题解决 一、问题描述 如果两张表的jion,关联键分布较均匀,没有明显的热点问题&…

无桌面版docker在Ubuntu系统上安装

目录 注意 系统要求 卸载旧版本 安装 使用apt存储库安装 1. 设置 Docker 的apt存储库。 2. 安装Docker软件包 3. 通过运行镜像来验证Docker Engine安装是否成功 hello-world。 从包中安装 1. 进入 https://download.docker.com/linux/ubuntu/dists/。 2. 在列表中选择…

阿里云MySQL从 2003->1251->1396

目的 由于需要在阿里云的实例中装MySQL数据库,安装前期(本地访问)还是挺顺利的,但是到了远程连接的时候,却出现了一系列的Bug,以为是没有 实名认证没有备案 的原因导致的,但是后来…

在Spring Boot中使用@Async实现一个异步调用

在使用异步注解之前,我们需要先了解,什么是异步调用? 异步调用对应的事同步调用,同步调用是值程序按照我们定义的顺序依次执行,每一行程序都必须等待上一行的程序执行完成之后才执行,而异步是指在顺序执行…

动态规划------方法汇总

核心: 状态定义 状态转移方程 启发思路(两种情况):选 或 不选 / 选哪个 DP三步:先写回溯,时间复杂度 指数级别;递归的过程中会重复计算,要保存计算结果,递归搜索…

uniapp是否可以用elementUI等前端UI库、使用步骤以及需要注意的问题

文章目录 uniapp是否可以用elementUI等前端UI库使用方法和步骤问题如何解决 uniapp是否可以用elementUI等前端UI库 在PC端开发uniapp,可以用elementUI,因为elementUI就是PC端的。 在使用uniapp,选择vue2.0时,实测可以用nodejs16的…

Linux部署HDFS集群

(一)VMware虚拟机中部署 ps、其中node1、node2、node3替换为自己相应节点的IP地址,或者host文件中配置过的主机名,或者看前置准备 或者查看前置准备:Linux部署HDFS集群前置准备 1.下载压缩包 https://www.apache.or…

管理类联考-性质

性质 ——性质—— 一、是什么 (1)本质:判断一定范围内的对象是否具备某个性质的命题就是性质命题(直言命题)。直言命题是断定事物/对象是否具有某种性质的命题。直言命题在结构上由主项、谓项、联项和量项组成。 &am…

对Spring框架的一些总结

对Spring框架的一些总结 在文章开头我真心推荐大家一个优秀的编程老师:孙帅老师(孙哥suns),孙帅老师在哔哩哔哩的Spring5教学视频时长接近33个小时,从0基础到一步一步手把手的教你抽丝剥茧分析Spring框架的所有知识,孙帅老师的教…

打印元素绘制协议Java实现

我一直提倡的面向接口和约定编程,而打印元素绘制协议一直是我推荐的打印实现方式,我以前只是强调按打印元素绘制协议输出数据就行了,有实现程序按协议控制打印,说是可以用任何语言实现客户端程序而不影响打印业务,那么…