《JAVA核心技术卷①》
内部类
为什么使用内部类?
- 内部类方法可以访问该类定义所在的作用域中的数据,包括私有数据
- 内部类可以对同一个包中的其他类隐藏
- 匿名内部类可以 定义一个回调函数又不用写大量代码
匿名内部类
静态内部类
package classLoader;
/**
* Created by IntelliJ IDEA.
* User: luna
* Date: 2022/4/10
*/
public class StaticInnerClassTest {
public static void main(String[] args) {
double d[]=new double[20];
for(int i=0;i<d.length;i++){
d[i]=Math.random();
}
ArrayAlg.Pair minmax = ArrayAlg.minmax(d);
System.out.println(minmax.getFirst());
System.out.println(minmax.getSecond());
}
}
class ArrayAlg{
public static class Pair{
private double first ;
private double second;
public Pair(double first, double second) {
this.first = first;
this.second = second;
}
public double getFirst() {
return first;
}
public void setFirst(double first) {
this.first = first;
}
public double getSecond() {
return second;
}
public void setSecond(double second) {
this.second = second;
}
}
public static Pair minmax(double []values){
double min = Double.POSITIVE_INFINITY;
double max = Double.NEGATIVE_INFINITY;
for(double v:values){
if(min>v){
min=v;
}
if(max<v){
max=v;
}
}
//没有可用的隐式ArrayAlg类型对象初始化内部类参数
return new Pair(min,max);
}
}
外部类是ArrayAlg类,内部类是隐藏在ArrayAlg类的内部,即Pair类。ArrayAlg的主要功能是计算double数组的最大值和最小值,并将最值使用Pair封装,于是把Pair类定义为ArrayAlg的内部公有类,使用ArrayAlg.Pair()在访问Pair对象。
于是提到了核心部分静态内部类的对象没有对生成它的外围类对象的引用特权。
外围类对象是ArrayAlg对象,静态内部类对象是Pair对象,即Pair对象没有引用ArrayAlg对象,什么意思❓
同时发现,将Pair对象的static修饰去掉,会报错没有可用的隐式ArrayAlg类型对象初始化内部类对象
内部类
package classLoader;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
/**
* Created by IntelliJ IDEA.
* User: luna
* Date: 2022/4/10
*/
public class InnerClassTest {
}
class TalkingClock{
private int interval;
private boolean beep;
public TalkingClock(int interval, boolean beep) {
this.interval = interval;
this.beep = beep;
}
public void start(){
ActionListener actionListener = new TimePrinter();
Timer timer = new Timer(interval, actionListener);
timer.start();
}
public class TimePrinter implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("the time is "+new Date());
if(beep){
Toolkit.getDefaultToolkit().beep();
}}
}
}
这是一个常规内部类TimePrinter和他的外围类TalkingClock
关键点在于内部类的beep。
TimePrinter类中没有beep的实例域或变量,即beep引用的创建TimePrinter的TalkingClock对象的域。
即内部类既可以访问自身数据域 也可以访问创建他的外围类对象的数据域。
因此TimePrinter对象总有一个隐式引用,指向创建他的外部类对象(TalkingClock,这个引用不可见。
该引用等价于内部类的构造器中加入一个引用outer指向外部类对象 (outer只是为了说明内部类机制
public TimePrinter(TalkingClock clock) {
outer=clock;
}
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("the time is "+new Date());
//发出铃声之前检查beep
if(beep){
//将外围类对象的引用称为outer
//if(beep)=====if(outer.beep)
Toolkit.getDefaultToolkit().beep();
}}
}
总结
通过举出常规内部类的例子,可以大致明白所谓的内部类对象对外部类的引用,内部类对象可以通过此引用访问外部类对象的属性。
而第一个例子Pair类并不需要引用外围类对象ArrayAlg,他作为内部类只是赋值ArrayAlg类更好的返回最值结果,此时不需要引用的存在,因此规定为静态内部类,使用static修饰,取消产生的引用。
原因
可以看这个大佬的博客https://blog.csdn.net/zhang_yanye/article/details/50344447