三种内部类的使用(成员内部类、局部内部类、匿名内部类)

内部类是什么?

内部类(inner class)是定义在另一个类中的类,相当于在你的大书包里又放进了小钱包。那么为什么需要内部类呢?

  • 内部类可以对同一个包中的内容进行隐藏(你的钱包里有很多钱,如果装入书包里,别人就不知道你有钱包,你钱包里的钱也就得到了隐藏)。
  • 内部类方法可以访问定义在这个类的作用域的数据,包括原有的私有的数据(private)。

成员内部类

什么是成员内部类?

成员内部类,也就是最常见最普通的内部类,和它的名字一样,它是作为外部类的一个成员而存在的。相当于类中的一个成员变量。

public class Outer{
	private int a;
	...
	public class Inner{
		...
	}//Inner就是Outer的成员内部类,地位与定义变量差不多。
}

那么问题来了,每一个类中都多多少少会有一些方法,那么我们可以直接调用内部类中的方法吗?如果不行,又应该怎么办呢?👀

下面的的代码中我们看到当我们new了一个Outer后,无法找到Outer类中的show()方法。😳😳😳其实可以这么来理解,还是书包和钱包的例子:你的唯一一张银行卡在钱包里,你的钱包在书包里。当你需要在超市刷那张银行卡的时候,如果你仅仅打开书包,你无法刷你的银行卡(当然不能用手机🤣)。
在这里插入图片描述

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

public class test {
	public static void main(String[] args) {
		Outer.Inner out=new Outer().new Inner();//这样就可以啦,相当于打开了你的钱包
		out.show();
	}
}

class Outer {
	class Inner{
		public void show() {
			System.out.print("Success!");
		}
	}
}

在这里插入图片描述
现在的内部类Inner中的show()方法是public的,也就是说外部可以随意调用(相当于你的钱包没有上锁,任何人打开书包后都可以打开钱包刷你的银行卡)。如果我们将show()设为私有private会发生什么呢?👀
在这里插入图片描述
我们发现出现了这样的错误The method show() from the type Outer.Inner is not visibleInner中的show()将会变得不可见。

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

直接调用内部类中的private方法会出现The method show() from the type Outer.Inner is not visible的错误,那么我们应该怎么调用呢?
我们回想一下我们当初是怎么调用私有变量的。

public class test {
	public static void main(String[] args) {
		Outer out=new Outer();
		//System.out.print(a);  -->会报错❌
	    out.show();//调用show()方法显示私有变量a
}
}

 class Outer{
	private int a=100;//这个a不能直接用
	public void show(){
		System.out.print(a);
	}
}

对于私有变量a,我们想要在屏幕上显示出这个a的数值的时候我们需要调用一个public方法来显示它。

回过头来,似乎对如何调用这个私有方法这个问题有了一个比较明确的方向😉

public class test {
	public static void main(String[] args) {
	Outer out=new Outer();
	out.method();
}
}

class Outer {
	class Inner{
		private void show() {
			System.out.print("Success!");
		}
	}
	public void method() {
		Inner in=new Inner();
		in.show();
	}
}

在这里插入图片描述

局部内部类

什么是局部内部类?

什么是局部内部类呢?先上代码:

class Outer {

	public void method(){
		class Inner{
			...
		}
	}
	
}

在一个方法中局部地定义一个类被称为局部内部类
这里要注意的是,声明局部类时不能有访问说明符(即public或private)。局部类的作用域被限定在声明这个局部类的块中。

怎么使用局部内部类?

public class test {
	public static void main(String[] args) {
		Outer out =new Outer();
		out.method();
}
}

class Outer {
	public void method() {
		
		class Inner{
			public void show() {
				System.out.print("Success!");
			}
		}
		
		Inner in = new Inner();
		in.show();
		
	}
}

Inner in = new Inner(); in.show();这块代码不要忘了。想一下如果少了这两行代码,直接在main中调用method()方法,这时候的method()有什么作用吗?它仅仅在内部类中定义了一个方法,并没有实现。

匿名内部类

什么是匿名内部类?

使用局部内部类的时候,假如只想创建这个类的一个对象,那再另外new一下似乎变得不必要。这时候匿名内部类(annoymous inner class)就出现了。这时候甚至不用为类指定名字。【匿名内部类是一种特殊的局部内部类】

匿名内部类的本质:一个继承了该类或者接口的子类匿名对象

在这里插入图片描述
先定义一个Show接口,有一个show()方法。

package testpackage;

public interface Show {
	void show();
}

既然匿名内部类是一种特殊的局部内部类,那class当然也要写到方法里头去咯。

package testpackage;
public class test {
	public static void main(String[] args) {
		Outer out =new Outer();
		out.method();
}
}

class Outer {
	public void method() {
		new Show() {

			@Override
			public void show() {
				// TODO Auto-generated method stub
				System.out.print("Success!");
			}
			
		};//注意这里有分号
	}
}

到这一步,我们已经定义好了匿名内部类,也重写了Show接口中的show()方法,但这仅仅只是写好了,并没有真的让它show出来(这时候运行控制台上一定是空白的),那么我们应该怎么样在控制台上显示出Success呢?

怎么调用匿名内部类的方法?

我们回到匿名内部类的本质:一个继承了该类或者接口的子类匿名对象

我们之前的代码:Object obj = new Object();之后如果要调用Object中的方法,我们会这样做:obj.method();。其中obj就是一个对象变量。既然都是对象,只不过匿名内部类没有属于自己的名字(555匿名内部类好可怜居然没有名字😖)那么匿名内部类是不是也可以点一下来调用方法呢?

package testpackage;
public class test {
	public static void main(String[] args) {
		Outer out =new Outer();
		out.method();
}
}

class Outer {
	public void method() {
		new Show() {

			@Override
			public void show() {
				// TODO Auto-generated method stub
				System.out.print("Success!");
			}
			
		}.show();//注意这里有分号
	}
}

在这里插入图片描述
事实证明这样是正确的!
那么问题又来了,如果我们要输出好几次Success呢?难道我们要不停地写Ctrl+c、Ctrl+v(Command+c、Command+v)这段代码吗?显然不合理。下面是解决方法:

package testpackage;

public class test {
	public static void main(String[] args) {
		Outer out =new Outer();
		out.method();
}
}

class Outer {
	public void method() {
		Show si=new Show() {

			@Override
			public void show() {
				// TODO Auto-generated method stub
				System.out.println("Success!");
			}
			
		};
		si.show();
		si.show();
		si.show();
	}
}

在这里插入图片描述
对这个代码有一个地方一直在困扰我,虽然没怎么理解,但也只能勉强接受:Show si = new Show(){...};Show不是一个接口吗?接口为什么能用new实例化呢?我找了许多资料,最终得出这样的结论:new Show() {}实际上并没有实例化Show接口,而是创建了一个实现了Show接口的匿名内部类,从而达到调用show()的目的。. 总的来说就是:看似实例,实则没有实例。

关于匿名内部类

  • 匿名内部类不能有构造器 由于构造器的名字必须与类名相同,而可怜巴巴🥺的匿名内部类连名字都没有,何来构造器呢?
  • Lambda表达式 多年来,Java程序员习惯的做法是用匿名内部类实现事件监听器和回调。如今在Java8之后可以使用Lambda表达式简化繁琐的匿名内部类。
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Noah Blake

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值