CoreJava读书笔记--接口、lambda表达式与内部类(二)--接口示例

接口示例

(一)接口与回调

回调(callback)是一种常见的程序设计模式。在这种模式中,可以指出某个特定事件发生时应该采取的动作。

假设我们需要做一个定时器,每隔10秒可以发出一个公告,该如何做呢?

package timer;

import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;

import javax.swing.JOptionPane;
import javax.swing.Timer;

public class TimerTest {
	public static void main(String[] args) {
		ActionListener listener = new TimePrinter();
		Timer t = new Timer(10*1000,listener);
		t.start();
		JOptionPane.showMessageDialog(null, "Quit program");
		System.exit(0);
	}
}
class TimePrinter implements ActionListener{

	@Override
	public void actionPerformed(ActionEvent e) {
		System.out.println("At the tone,the time is "+new Date());
		Toolkit.getDefaultToolkit().beep();
	}
	
}

从 上面代码中可以看到,TimePrinter类实现了ActionListener接口,覆盖了actionPerformed方法,去打印时间。在main方法中,创建了listener对象,并且创建一个定时器t,t每隔10秒会调用一次接口方法,从而打印时间。

(二)Comparator接口

使用Comparator接口进行排序:

package comparator;

import java.util.Arrays;
import java.util.Comparator;

public class StringLengthSortTest {
	public static void main(String[] args) {
		Comparator<String> comp = new LengthComparator();
		String[] s = {"abcde","bcd","cde"};
		Arrays.sort(s, comp);
		for(String e : s) {
			System.out.println(e);
		}
	}
	
}
class LengthComparator implements Comparator<String>{

	@Override
	public int compare(String o1, String o2) {
		int num =o1.length()-o2.length();
		if(num==0) {
			return o1.compareTo(o2);
		}
		return num;
	}
	
}

我们认识了Comparator和Comparable两种比较器接口,讨论一下两种比较器的区别:

相同点:实现Comparator接口和Comparable接口都是为了调用Arrays.sort方法,来自定义排序

不同点:

①排序规则实现的方法不同

Comparable接口是实现compareTo(Object obj)

Comparator接口是实现compare(Object o1,Object o2)

②类设计前后不同

comparable接口是在设计类时,就考虑排序问题

comparator接口是在类设计已经完成,还想再对其进行排序

(三)对象克隆

什么是克隆?

克隆就是根据已经有的数据,来创建一份新的完全一样的数据拷贝。

实现克隆的方式?

①使用更改器方法,将原对象中的信息获得后全部set到新的对象中

②使用clone方法,要想使用clone方法也必须满足两个条件:一、要实现Clonable接口;二、使用public修饰符重新定义clone方法

为什么会有浅克隆和深克隆之分?

因为在Java中,分为基本类型数据和引用类型数据,基本类型数据存在于栈内存中,而引用类型数据的地址是在栈内存中,其数据却是在堆内存中。

如果某个对象中全都是基本类型数据,并没有克隆对象中引用的其他对象或者是不可变对象,如String,那么就可以使用默认的克隆操作,也就是浅克隆。

但是通常子对象都是可变的,不全是基本类型数据,那就必须重新定义clone方法来建立一个深拷贝,也就是深克隆。而深克隆的实现就是在引用类型所在的类实现Cloneable接口,并使用public访问修饰符重写clone方法。

package clone;

import java.util.Date;
import java.util.GregorianCalendar;

public class Employee implements Cloneable{//①声明要实现Cloneable接口
	private String name;
	private double salary;
	private Date hireDay;
	
	public Employee(String name,double salary) {
		this.name = name;
		this.salary=salary;
		hireDay = new Date();
	}
	
	public Employee clone() throws CloneNotSupportedException{//②使用public修饰,并重新定义clone方法
		Employee cloned = (Employee) super.clone();//③对于基本数据类型,使用默认的浅克隆,
		
		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().getName()+"[name="+name+
				",salary="+salary+",hireDay"+hireDay+"]";
	}
}
package clone;

/**
 * This program demonstrates cloning.
 * @author 弓长小月
 *
 */
public class CloneTest {
	public static void main(String[] args) {
		try {
			Employee original = new Employee("John Q. Public",78000);
			original.setHireDay(2000, 1, 1);
			System.out.println("original="+original.toString());
			Employee copy = original.clone();
			System.out.println("copy="+copy.toString());
			System.out.println("---------------------------------------------------");
			copy.raiseSalary(10);
			copy.setHireDay(2002, 12, 31);
			System.out.println("original="+original.toString());
			System.out.println("copy="+copy.toString());
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
	}
}

猜你喜欢

转载自blog.csdn.net/zxyy2627/article/details/82657142