Java核心技术--内部类
1.内部类
1 package innerClass; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import java.util.*; 6 import javax.swing.*; 7 import javax.swing.Timer; 8 9 /** 10 * This program demonstrates the use of inner classes. 11 * @version 1.11 2015-05-12 12 * @author Cay Horstmann 13 */ 14 public class InnerClassTest 15 { 16 public static void main(String[] args) 17 { 18 TalkingClock clock = new TalkingClock(1000, true); 19 clock.start(); 20 21 // keep program running until user selects "Ok" 22 JOptionPane.showMessageDialog(null, "Quit program?"); 23 System.exit(0); 24 } 25 } 26 27 /** 28 * A clock that prints the time in regular intervals. 29 */ 30 class TalkingClock 31 { 32 private int interval; 33 private boolean beep; 34 35 /** 36 * Constructs a talking clock 37 * @param interval the interval between messages (in milliseconds) 38 * @param beep true if the clock should beep 39 */ 40 public TalkingClock(int interval, boolean beep) 41 { 42 this.interval = interval; 43 this.beep = beep; 44 } 45 46 /** 47 * Starts the clock. 48 */ 49 public void start() 50 { 51 ActionListener listener = new TimePrinter(); 52 Timer t = new Timer(interval, listener); 53 t.start(); 54 } 55 56 public class TimePrinter implements ActionListener 57 { 58 public void actionPerformed(ActionEvent event) 59 { 60 System.out.println("At the tone, the time is " + new Date()); 61 if (beep) Toolkit.getDefaultToolkit().beep(); 62 } 63 } 64 }
2.匿名内部类
1 package anonymousInnerClass; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import java.util.*; 6 import javax.swing.*; 7 import javax.swing.Timer; 8 9 /** 10 * This program demonstrates anonymous inner classes. 11 * @version 1.11 2015-05-12 12 * @author Cay Horstmann 13 */ 14 public class AnonymousInnerClassTest 15 { 16 public static void main(String[] args) 17 { 18 TalkingClock clock = new TalkingClock(); 19 clock.start(1000, true); 20 21 // keep program running until user selects "Ok" 22 JOptionPane.showMessageDialog(null, "Quit program?"); 23 System.exit(0); 24 } 25 } 26 27 /** 28 * A clock that prints the time in regular intervals. 29 */ 30 class TalkingClock 31 { 32 /** 33 * Starts the clock. 34 * @param interval the interval between messages (in milliseconds) 35 * @param beep true if the clock should beep 36 */ 37 public void start(int interval, boolean beep) 38 { 39 ActionListener listener = new ActionListener() 40 { 41 public void actionPerformed(ActionEvent event) 42 { 43 System.out.println("At the tone, the time is " + new Date()); 44 if (beep) Toolkit.getDefaultToolkit().beep(); 45 } 46 }; 47 Timer t = new Timer(interval, listener); 48 t.start(); 49 } 50 }
第二种方法比第一种更为简洁,多年来,Java程序员习惯的做法是用匿名内部类实现事件监听器和其他回调。
上述两种方法可以用lambda来实现,更为简洁
1 public void start(int interval, boolean beep) { 2 Timer t = new Timer(interval, event -> { 3 System.out.println("At the tone, the time is " + new Date()); 4 if (beep) Toolkit.getDefaultToolkit().beep(); 5 }); 6 t.start(); 7 }
3.匿名内部类的一个使用技巧--“双括号初始化”
假设你想构造一个数组列表,并将它传递到一个方法:
1 ArrayList<String> friends = new ArrayList<>(); 2 friends.add("Harry"); 3 friends.add("Tony"); 4 invite(friends);
如果不在需要这个数组列表,最好让他作为一个匿名列表,方法如下:
invite(new ArrayList<String>() {{ add("Harrry"); add("Tony"); }});
外层括号建立了ArrayList的一个匿名子类,内层括号则是一个对象构造块。
4.静态内部类
1 package staticInnerClass; 2 3 /** 4 * This program demonstrates the use of static inner classes. 5 * @version 1.02 2015-05-12 6 * @author Cay Horstmann 7 */ 8 public class StaticInnerClassTest 9 { 10 public static void main(String[] args) 11 { 12 double[] d = new double[20]; 13 for (int i = 0; i < d.length; i++) 14 d[i] = 100 * Math.random(); 15 ArrayAlg.Pair p = ArrayAlg.minmax(d); 16 System.out.println("min = " + p.getFirst()); 17 System.out.println("max = " + p.getSecond()); 18 } 19 } 20 21 class ArrayAlg 22 { 23 /** 24 * A pair of floating-point numbers 25 */ 26 public static class Pair 27 { 28 private double first; 29 private double second; 30 31 /** 32 * Constructs a pair from two floating-point numbers 33 * @param f the first number 34 * @param s the second number 35 */ 36 public Pair(double f, double s) 37 { 38 first = f; 39 second = s; 40 } 41 42 /** 43 * Returns the first number of the pair 44 * @return the first number 45 */ 46 public double getFirst() 47 { 48 return first; 49 } 50 51 /** 52 * Returns the second number of the pair 53 * @return the second number 54 */ 55 public double getSecond() 56 { 57 return second; 58 } 59 } 60 61 /** 62 * Computes both the minimum and the maximum of an array 63 * @param values an array of floating-point numbers 64 * @return a pair whose first element is the minimum and whose second element 65 * is the maximum 66 */ 67 public static Pair minmax(double[] values) 68 { 69 double min = Double.POSITIVE_INFINITY; 70 double max = Double.NEGATIVE_INFINITY; 71 for (double v : values) 72 { 73 if (min > v) min = v; 74 if (max < v) max = v; 75 } 76 return new Pair(min, max); 77 } 78 }
优点:1.避免编写两个函数,一个计算最小值,一个计算最大值,只需要遍历一次就可以了。
2.Pair是一个十分大众化的名字,其他程序员很有可能会使用这个名字,这样就会产生名字冲突,解决这个问题的办法是将Pair定义为ArrayAlg的内部公有类,通过ArrayAlg.Pair来访问它。