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);
    }
}

服务加载器

动态选择实现了一个接口的不同的实现类

代理

利用代理可以再运行时🐟创建实现了一组给定接口的新类。只有在编译的时候无法确定需要实现那个接口时才有必要使用代理。

posted @ 2022-05-29 21:59  破忒头头  阅读(54)  评论(0)    收藏  举报