本章重点:
- interface
- clone
- interface & callback
- proxy
interface
接口——如果类遵从某个特定接口,那么就履行这项服务。
接口的特征
- 可以声明接口的变量,但是不可以实例化.
- interface 支持 instanceof 语法.
- interface 同样支持 extends.
- interface 不可以包含实例域或者静态方法,但是可以包含常量(接口中默认是public static final).
- java 支持“单继承、多接口”.
clone
copy & clone
Employee original = new Employee("John Public", 50000);
Employee copy = original;
copy.raiseSalary(34); // oops -- also changed original
Employee copy = original.clone();
copy.raiseSalary(10); // OK -- original unchanged
clone
是Object
的 protected 方法,由于 Object 类对具体类的一无所知,所以默认只是对各个域浅拷贝, 这对于基本类型和不可变类型(如String类型)没有问题,但是对于可变类(mutable class)却会出问题.
重新定义 clone 方法
- 是否需要定义 clone 方法.
- 默认的 clone 方法是否满足要求.
- 默认的 clone 方法是否能够通过调用可变子对象的 clone 得到修补.
- 实现 Cloneable 接口(Cloneable 是tagging interface,没有任何方法).
- 使用 public 修饰 clone 方法.
package corejava.interfaces;
import java.util.Date;
import java.util.GregorianCalendar;
/**
* Created by guolong.fan on 15/4/26.
*/
public class CloneTest {
public static void main(String[] args) {
try {
Employee origianl = new Employee("John Q. Public", 50000);
origianl.setHireDay(2015, 4, 26);
Employee copy = origianl.clone();
copy.raiseSalary(10);
copy.setHireDay(2015, 5, 1);
System.out.println("orginal=" + origianl);
System.out.println("copy=" + copy);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
class Employee implements Cloneable {
public Employee(String n, double s) {
name = n;
salary = s;
hireDay = new Date();
}
public Employee clone() throws CloneNotSupportedException {
// call Object.clone()
Employee cloned = (Employee) super.clone();
// clone mutable fields
cloned.hireDay = (Date)hireDay.clone();
return cloned;
}
public void setHireDay(int year, int month, int day) {
Date newHireDay = new GregorianCalendar(year, month-1, day).getTime();
hireDay.setTime(newHireDay.getTime());
}
public void raiseSalary(double byPercent) {
double raise = salary * byPercent / 100;
salary += raise;
}
public String toString() {
return getClass().getSimpleName() +
"[name=" + name +
",salary=" + salary +
",hireDay=" + hireDay + "]";
}
private String name;
private double salary;
private Date hireDay;
}
interface & callback
示例:
package corejava.interfaces;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
/**
* Created by guolong.fan on 15/4/26.
*/
public class TimerTest {
public static void main(String[] args) {
ActionListener listener = new TimePrinter();
Timer t = new Timer(5000, listener);
t.start();
JOptionPane.showMessageDialog(null, "Quit program?");
System.exit(0);
}
}
class TimePrinter implements ActionListener {
@Override
public void actionPerformed(ActionEvent actionEvent) {
Date now = new Date();
System.out.println("At the tone, time is " + now);
Toolkit.getDefaultToolkit().beep();
}
}
proxy
示例:
package corejava.interfaces;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Random;
/**
* Created by guolong.fan on 15/4/26.
*
* This program demonstrates the use of proxies.
*/
public class ProxyTest {
public static void main(String[] args) {
Object[] elements = new Object[1000];
// 给 1...100 构造代理.
// fill elements with proxies for the integers 1 ... 1000
for (int i = 0; i < elements.length; ++i) {
Integer value = i + 1;
InvocationHandler handler = new TraceHandler(value); // method.invoke(target, args);
Object proxy = Proxy.newProxyInstance(null, new Class[] {Comparable.class}, handler);
// now proxy is proxy of value
elements[i] = proxy;
}
Integer key = new Random().nextInt(elements.length) + 1;
// search for the key
int result = Arrays.binarySearch(elements, key);
// print match if found
if (result >= 0) System.out.println(elements[result]);
}
}
/**
* An invocation handler that prints out the method name and parameters, then
* invokes the original method
*/
class TraceHandler implements InvocationHandler {
public TraceHandler(Object t) {
target = t;
}
@Override
public Object invoke(Object o, Method method, Object[] args) throws Throwable {
// print implicit argument
System.out.print(target);
// print mehtod name
System.out.print("." + method.getName() + "(");
if (args != null) {
for (int i = 0; i < args.length; ++i) {
if (i > 0) System.out.print(", ");
System.out.print(args[i]);
}
}
System.out.println(")");
// invoke actual method
return method.invoke(target, args);
}
private Object target;
}