Java的四种内部类详解

成员内部类

  • 就是位于外部类成员位置的类。与外部类的属性、方法并列。
  • 成员内部类作为外部类的成员,可以访问外部类的私有成员或属性。(即使将外部类声明为private,但是对于处于其内部的内部类还是可见的。)
  • 用成员内部类定义在外部类中不可访问的属性。这样就在外部类中实现了比外部类的private还要小的访问权限。
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Instant;

import javax.swing.JOptionPane;
import javax.swing.Timer;

public class InnerClass {
	public static void main(String[] args) {
		TalkingClock clock = new TalkingClock(1000, true);
		clock.start();
		
		JOptionPane.showMessageDialog(null, "Quit program?");
		System.exit(0);
	}
}
class TalkingClock{
	private int interval;
	private boolean beep;
	
	public TalkingClock(int interval,boolean beep) {
		this.interval = interval;
		this.beep = beep;
	}
	
	public void start() {
		var listener = new TimePrinter();
		var timer = new Timer(interval,listener);
		timer.start();
	}
	
	// 公共内部类
	public class TimePrinter implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent e) {
			System.out.println("at the tone,the time is "+Instant.ofEpochMilli(e.getWhen()));
			if(beep) {
				Toolkit.getDefaultToolkit().beep();
			}
		}
	}
}

内部类的特殊语法规则

表达式 OuterClass.this 表示外围类引用。
例如,可以像下面这样编写TimePrinter内部的actionPerformed方法:

public void actionPerformed(ActionEvent e){
	...
	if(TalkingClock.this.beep){
		...
	}
}

内部类的实例化:

外部类 对象1 = new 外部类();
外部类.内部类 对象2=对象1.new 内部类();

例如:由于TimePrinter是一个公共内部类,对于任意的语音时钟都可以构造一个TimePrinter:

var jabberer = new TalkingClock(1000,true);
TalkingClock.TimePrinter listener = jabberer.new TimePrinter();

局部内部类

外部类中的方法中定义的内部类是局部内部类。
在以上实例代码中,类型TimePrinter的名字只出现了一次:只是在start方法中创建这个类型的对象时使用了一次。在这种情况下,可以使用局部内部类。

public void start() {
		// 局部内部类
		class TimePrinter implements ActionListener{
			@Override
			public void actionPerformed(ActionEvent e) {
				System.out.println("at the tone,the time is "+Instant.ofEpochMilli(e.getWhen()));
				if(beep) {
					Toolkit.getDefaultToolkit().beep();
				}
			}
		}
		
		TimePrinter listener = new TimePrinter();
		Timer timer = new Timer(interval,listener);
		timer.start();
	}

声明局部内部类时不能有访问修饰符(即public或private)

匿名内部类

使用局部内部类时,通常还可以再进一步。假如只想创建这个类的一个对象,甚至不需要为类指定名字。这样一个类被称为匿名内部类

public void start(int interval,boolean beep) {
		// 匿名内部类
		var listener = new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				System.out.println("at the tone,the time is "+Instant.ofEpochMilli(e.getWhen()));
				if(beep) {
					Toolkit.getDefaultToolkit().beep();
				}
			}
		};
		
//		TimePrinter listener = new TimePrinter();
		Timer timer = new Timer(interval,listener);
		timer.start();
	}

这段代码的含义是:创建一个类的新对象,这个类实现了ActionListener接口,需要实现的方法actionPerformed在括号{}内定义。
一般地,语法如下:

new SuperType(construction parameters){
	inner class methods and data;
}

其中,SuperType可以是接口,如ActionListener,如果是这样,内部类就要实现这个接口。SuperType也可以是一个类,如果是这样,内部类就要扩展这个类。

  • 研究一下构造一个类的新对象构造一个扩展了那个类的匿名内部类的对象之间有什么差别。
var queen = new Person("Marry");
var count = new Person("Dracula"){...}

如果构造参数列表的结束小括号后面跟一个开始大括号,就是在定义匿名内部类。
以下给出一个含有匿名内部类的语音时钟程序的全部代码。

import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Instant;

import javax.swing.JOptionPane;
import javax.swing.Timer;

public class InnerClass {
	public static void main(String[] args) {
		TalkingClock clock = new TalkingClock();
		clock.start(1000,true);
		
		JOptionPane.showMessageDialog(null, "Quit program?");
		System.exit(0);
	}
}
class TalkingClock{
	public void start(int interval,boolean beep) {
		// 匿名内部类
		var listener = new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				System.out.println("at the tone,the time is "+Instant.ofEpochMilli(e.getWhen()));
				if(beep) {
					Toolkit.getDefaultToolkit().beep();
				}
			}
		};
		

		Timer timer = new Timer(interval,listener);
		timer.start();
	}
	
}

静态内部类

静态内部类就是修饰为 static 的内部类。声明为 static 的内部类,不需要内部类对象和外部类对象之间的联系,就是说,用户可以直接引用“外部类.内部类”。
静态内部类实例化如下:

外部类.内部类 对象 = new 外部类.内部类()

public class staticOuter {
	 
	public static int x=100;
	
	//静态内部类
	public static class MyInner{
		
		private String y="Hello!";
		
		public void innerMethod(){
		  System.out.println("x="+x);
		  System.out.println("y="+y);
		  
		  //通过对象调用外部非静态方法
		  staticOuter st = new staticOuter();
		  st.OuterClass();
		  
		  //用类名调用外部静态方法
		  staticOuter.Outer();
	    }
		
		public void OuterClass() {
			System.out.println("this is inner class.");
		}
    }
	
	public void OuterClass(){
		System.out.println("this is outer class.");
	}
	
	public static void Outer(){
		System.out.println("this is static outer class");
	}
	
	public static void main(String[] args) {
		//静态内部类不通过外部实例就可以创建对象;与类变量可以通过类名访问相似
		staticOuter.MyInner si = new staticOuter.MyInner();
		si.innerMethod();
		si.OuterClass();
		
		System.out.println("------ outer object----");
		staticOuter st = new staticOuter();
		st.OuterClass();
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值