抽象类
抽象类作为派生其他类的基类,而不作为特定的实现类,可以将通用方法放在继承关系高层次的抽象类中。创建抽象类使用abstract关键字,包含一个或多个抽象方法的类本身必须声明为抽象的。
除了抽象方法之外,抽象类还可以包含具体数据和具体方法。
抽象方法充当着占位的角色,它们的具体实现在子类中,扩展抽象类时,一种情况是在抽象类中定义部分抽象类方法或不定义抽象类方法,这样,必须将子类也声明为抽象的;另一种情况是定义全部的抽象方法,这样,子类就不是抽象的了。
- 类即使不含抽象方法,也可以将类声明为抽象类;
- 抽象类不能被实例化,但是可以创建一个具体子类的对象。
接口
在java中,一个类可以实现多个接口,接口不是类,而是对类的一组需求描述,任何实现接口的类都要实现接口中包含的方法。
- 接口中的方法默认为public;
- 接口不能含有实例域;
- 1.8之前,接口中不能实现方法,现在可以在接口中提供简单方法;
- 类似于抽象类,不能构造接口对象,但是可以声明接口变量引用实现了接口的类对象;
- 一个接口可使用extends扩展另一个接口;
- 接口中不能包含实例域或静态方法(1.8以后可以在接口中增加动态方法),但是可以包含常量,接口中的域默认为public static final。
默认方法
default修饰接口的方法可以为方法提供一个默认实现,这样就可以忽略对该方法的实现。
当一个接口定义了一个默认方法,然后又在超类或另一个接口中定义了同样的方法,会发生冲突,解决冲突的规则是:
1.超类优先;
2.类优先:在实现类中覆盖这个方法。
回调(callback)
回调是一种常见的设计模式,在这种模式中,可以指出某个特定事件发生时应该采取的动作。
把使用某一接口的类创建的对象的引用赋给该接口声明的接口变量,那么该接口变量就可以调用被类实现的接口方法,实际上,当接口变量调用被类实现的接口中的方法时,就是通知相应的对象调用接口的方法,这个调用的过程称为接口的回调。
一个回调的示例如下:
public class TimeTest {
public static void main(String[] args) {
ActionListener actionListener = new TimePrinter();
Timer t = new Timer(10000, actionListener);
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();
}
}
Comparator接口
Comparable接口:
public interface Comparable<T> {
public int compareTo(T o);
}
comparator接口:
public interface Comparator<T> {
int compare(T o1, T o2);
其它方法
}
对对象数组排序时,需要实现Comparable接口,对String类排序时,compareTo方法默认按字典顺序比较字符串,若要按长度比较字符串,可以定义一个实现了Comparator接口的类,实现compare方法。示例:
public static void main(String[] args) {
String[] s = {"do","Rew","Mijsa","djsFa","ashdkjaSo","Lahd","Xis"};
Arrays.sort(s);
for (String l : s)
System.out.print(l+", ");
System.out.println();
//实现比较器
Comparator<String> comparator = new LengthComparator();
Arrays.sort(s, comparator);
for (String l : s)
System.out.print(l+", ");
}
static class LengthComparator implements Comparator<String>{
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
}
输出结果:
Lahd, Mijsa, Rew, Xis, ashdkjaSo, djsFa, do,
do, Rew, Xis, Lahd, Mijsa, djsFa, ashdkjaSo,
Comparator接口包含很多静态方法构建比较器。
Cloneable接口
Cloneable接口是一组标记接口,它不包含任何方法,唯一的作用是允许在类型查询中使用instanceof。
拷贝:
如果希望新创建一个对象,它的初始状态与原对象相同,但之后的改变不会影响到原状态,就可以使用Object的clone()方法拷贝一个对象(必须实现Cloneable接口,再调用super.clone())。
浅拷贝:
当一个类中包含其它类对象时,调用默认的clone方法并不能拷贝这些对象域,想要拷贝它们就要深拷贝。
深拷贝:
重新定义克隆方法,不知拷贝原对象,也拷贝原对象中的子对象(拷贝可变的实例域即可)。
下面是一个深拷贝的示例:
class Student implements Cloneable{
String name;
Double score;
Major major;
public Student clone() throws CloneNotSupportedException{
Student cloned = (Student) super.clone();
cloned.major = (Major) major.clone();
return cloned;
}
}
class Major implements Cloneable{
String mName;
public Major(String s){
this.mName = s;
}
public Major clone() throws CloneNotSupportedException{
return (Major)super.clone();
}
}
函数式接口
只有一个抽象方法的接口称为函数式接口,当需要这种接口对象时,可以提供一个lambda表达式。
示例(lambda表达式实现函数式接口Comparator):
Arrays.sort(s,(first,second) -> first.length()-second.length());
功能等同于上面。