Java核心技术-内部类(下)
Day8
局部内部类
优势:
- 对外部完全隐蔽
- 可以访问外部类字段和局部变量
package cn.gyk;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Instant;
/**
* @author xg
* @version V1.0
* @date 2022/5/29 11:08
*/
public class LocalInnerClass {
public static void main(String[] args) {
var clock = new TalkingClock2();
clock.start(1000,true);
JOptionPane.showMessageDialog(null,"Quit program?");
System.exit(0);
}
}
class TalkingClock2{
//局部内部类可以访问局部变量和外部私有变量
public void start(int interval,boolean beep){
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();
}
}
var listener = new TimePrinter();
var timer = new Timer(interval,listener);
timer.start();
}
}
匿名内部类
🐕构造器的名字必须与类名相同,而匿名内部类没有名字,所以匿名内部类不能有构造器,构造器的参数要传递给超类构造器。
package cn.gyk;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Instant;
/**
* @author xg
* @version V1.0
* @date 2022/5/29 11:02
*/
public class AnonymousInnerClassDemo {
public static void main(String[] args) {
var clock = new TalkingClock1();
clock.start(1000,true);
JOptionPane.showMessageDialog(null,"Quit program?");
System.exit(0);
}
}
class TalkingClock1{
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();
}
};
var timer = new Timer(interval,listener);
timer.start();
}
}
双括号初始化
假设一个数组列表只是用一次,还是向方法中传递参数,就可以使用双括号初始化,这里利用了内部类的🐟法。
//普通方法
var friend = new ArrayList<>();
friend.add("Harry");
friend.add("Tony");
invite(friend);
//双括号初始化
invite(new ArrayList<String>{{add("Harry");add("Tony");}});
//外括号是一个继承了ArrayList类的匿名内部类
//内括号是匿名内部类的对象初始化块
静态内部类
只起到隐藏效果,并不会内部类中有一个外部类对象的引用。把内部类声明为static就不会生成那个引用。
只有内部类可以声明为static,静态内部类类似于其他的内部类,只不过静态内部类的对象没有生成他🐍的外围类对象的引用。再静态方法中的内部类必须表示为static。
只要内部类不需要访问外围类对象,就应该使用静态内部类。
静态类内部可以有静态的方法和字段。
在接口中的类自动的是static和public。
package cn.gyk;
/**
* @author xg
* @version V1.0
* @date 2022/5/29 20:19
*/
public class staticInnerClassDemo {
public static void main(String[] args) {
var values = new double[20];
for(int i = 0;i<values.length;i++){
values[i] = 100 * Math.random();
}
ArrayAlg.Pair p = ArrayAlg.minmax(values);
System.out.println("min = "+p.getFirst());
System.out.println("max = "+p.getSecond());
}
}
class ArrayAlg{
// 静态内部类
public static class Pair{
private double first;
private double second;
public Pair(double f,double s){
first = f;
second = s;
}
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;
}
return new Pair(min,max);
}
}
服务加载器
动态选择实现了一个接口的不同的实现类
代理
利用代理可以再运行时🐟创建实现了一组给定接口的新类。只有在编译的时候无法确定需要实现那个接口时才有必要使用代理。
浙公网安备 33010602011771号