package com.bawei.multithread;
//注意:模板方法我们通常使用抽象类或者抽象方法!这里我们为了方便在本类中使用就没有使用抽象类/抽象方法
public class TemplateThread {
//如果这个方法不想被子类或者别人随意改动[这样子类就不能覆写该方法了],这里方法就要设置为final方法
public final void println(String message){
System.out.println("#######################");
wrapPrint(message);
System.out.println("#######################");
}
//这个方法只允许被子类或者自身所覆盖,所以这里我们用protected关键字!
protected void wrapPrint(String message){ } public static void main(String[] args) {
//这里用TemplateThread类的匿名子类创建了一个对象,并覆盖了这个TemplateThread类的wrapPrint()方法!
TemplateThread t1 = new TemplateThread(){
@Override
protected void wrapPrint(String message) {
// TODO Auto-generated method stub
System.out.println("*"+message+"*");
}
};
t1.println("哈哈"); //这里实际上是TemplateThread类的匿名子类创建了一个匿名对象,然后调用这个匿名对象的println()方法!只不过在这里
//用匿名子类的时候,覆盖了父类中的wrapPrint方法,同时需要提醒大家的是,如果父类【TemplateThread】中的方法如果
//是抽象方法的话,那么子类就必须实现这个抽象方法,而如果父类中的这个方法只是一个空方法体的话,子类可以选择覆盖,也可以
//选择不覆盖!!
new TemplateThread(){
@Override
protected void wrapPrint(String message) {
// TODO Auto-generated method stub
System.out.println("======="+message+"=====");
}
}.println("哈哈");
}
}
我想我们上面的这段代码已经很好的阐释了我们的标题要讲的知识点,这里要好好体悟,再一个就是:这个通过匿名类创建的匿名对象,然后调用这个匿名对象的println()方法实际上是仿照我们的Thead线程类的start()方法实现的,也就是说:我们多线程Thread类的start()方法的源码中大家可以看到实际上是调用了start0()方法,而这个方法是native修饰的,也就是由C++写的,在这个方法内部实际上又调用了我们Thread类的run()方法,这就很像我们在上面代码中父类TemplateThread中的println()方法中调用了wrapPrint()方法,而这里的wrapPrint()方法只是一个空实现,也就是说子类可以实现也可以不实现,实际上是和我们调用Thead创建子类的时候是一致的,我们可以覆盖这个Thead类的run()方法,yekeyi 不覆盖,这是因为Thead/类本身已经为我们实现了这个run()方法,如果必须要子类覆盖或者实现的话,可以将这个方法设置为抽象方法!也就在TemplateThread中我们可以将wrapPrint设置为抽象方法,那么TemplateThread的子类就必须实现这个方法了,然后子类的对象也就可以直接调用println()方法了!就javaapi给我们提供的这个Thread类而言,我们是可以覆写它的start()方法的,因为这个方法不是final类型的,但是如果我们覆写了start()方法,那么它就不会有源码中的start0()方法来调用c++的程序了!所以我们这个说明了,为什么我命名调用的是run()方法而我们在运行程序的时候却是调用的是start()方法呢?原因就是Thead类这里用的是模板方法的一个技巧,就是和上面我们自己写的代码类似,在一个方法1中调用另一个方法2,我们需要覆写的是方法2,但是我们运行代码的时候调用的却是方法1,因为方法1为我们调用了方法2,而且在调用方法2的前后还做了其它工作!