零基础学JAVA--Day23(final关键字+抽象类及应用模板设计模式) - 详解
final关键字
final 可以修饰类、属性、方法和局部变量.
在某些情况下,程序员可能有以下需求,就会使用到final:
1)当不希望类被继承时,可以用final修饰.
2)当不希望父类的某个方法被子类覆盖/重写(override)时,可以用final关键字修饰。
3)当不希望类的的某个属性的值被修改,可以用final修饰.
4)当不希望某个局部变量被修改,可以使用final修饰【案例演示: final doubleTAX RATE=0.08
一些细节
final使用注意事项和细节讨论
1) final修饰的属性又叫常量,一般用大写英文字母来命名
2)final修饰的属性在定义时,必须赋初值,并且以后不能再修改,赋值可以在如下位置之一【选择一个位置赋初值即可】:
①定义时:如 public final double TAX_RATE=0.08;
②在构造器中
③在代码块中
public final double TAX_RATE
3)如果final修饰的属性是静态的,则初始化的位置只能是:
①定义时②在静态代码块,不能在构造器中赋值。
4)final类不能继承,但是可以实例化对象是可以的。
如果类不是final类,但是含有final方法,则该方法虽然不能重写,但是可以被继承。
5)一般来说,如果一个类已经是final类了,就没有必要再将方法修饰成final方法。
6)final不能修饰构造方法(即构造器)
7)final和static往往搭配使用,效率更高,底层编译器做了优化处理。
//主程序调用
Systom.out.println(BBB.num);
//情况一
class BBB {
public static int num = 10000;//静态变量不被final修饰
static{
System.out.println("BBB静态代码块被执行");
}
}
//输出
BBB代码块被执行
10000
=>会导致静态代码块执行
//情况一
class BBB {
public final static int num = 10000;//静态变量被final修饰
static{
System.out.println("BBB静态代码块被执行");
}
}
//输出
10000
=>不会导致静态代码块执行,实现代码优化,效率提升
7)包装类,String类都是final类
抽象类
当父类的某些方法,需要声明,但是又不确定如何实现时,可以将其声明为抽象方法,那么这个类就是抽象类。
class Animal {
private String name;
public Animal(string name){
this.name = name;
}
//思考:这里eat这里你实现了,其实没有什么意义
//即:父类方法的不确定性
public void eat(){
Systom.out.println("动物吃东西,但吃什么不知道")
}
}
//改为抽象类和抽象方法
abstract class Animal {
private String name;
public Animal(string name){
this.name = name;
}
//抽象方法
//由子类实现具体的eat方法
public abstract void eat();
}
抽象类的介绍
1)用abstract关键字来修饰一个类时,这个类就叫抽象类
访问修饰符 abstract 类名();
2)用abstract关键字来修饰一个方法时,这个方法就是抽象方法
访问修饰符 abstract 返回类型 方法名(参数列表) ;//没有方法体
3)抽象类的价值更多作用是在于设计,是设计者设计好后,让子类继承并实现抽象类
4)抽象类,是考官比较爱问的知识点,在框架和设计模式使用较多
抽象类的细节
1)抽象类不能被实例化,不能被new
2)抽象类不一定要包含abstract方法。也就是说,抽象类可以没有abstract方法
3)一旦类包含了abstract方法,则这个类必须声明为abstract
4)abstract只能修饰类和方法,不能修饰属性和其它的
5)抽象类可以有任意成员【抽象类还是类】,比如:非抽象方法、构造器、静态属性等等
6)抽象方法不能有主体,即不能实现,如图所示
7)如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,除非它自己也声明为abstract类。
8)抽象方法不能使用private、final和static来修饰,因为这些关键字都是和重写相违背的。本质上抽象类的存在就是为了子类或者其他,对其重写,使得方法更加灵活,而上述关键字抑制了方法重写的性质,与抽象类相违背。
抽象类的最佳实践---模板设计模式
优化前
package com.abstractDetail;
public class Job {
public static void main(String[] args) {
AA aa = new AA();
BB bb = new BB();
aa.jobaa();
bb.jobbb();
}
}
class AA{
public void jobaa(){
long start = System.currentTimeMillis();//记录程序开始时间
long num = 0;
for (int i = 1; i < 10000000; i++) {
num+=i;
}
long end = System.currentTimeMillis();//记录程序结束时间
System.out.println("AA执行时间为"+(end-start));
}
}
public class BB {
public void jobbb() {
long start = System.currentTimeMillis();//记录程序开始时间
long num = 0;
for (int i = 1; i < 10000000; i++) {
num *= i;
}
long end = System.currentTimeMillis();//记录程序结束时间
System.out.println("BB执行时间为" + (end - start));
}
}
//问题:代码冗余,重复代码太多需要优化
优化后
//创建一个父类,用于存放模板
public abstract class TimeTemple {
public abstract void job();
public void time() {
long start = System.currentTimeMillis();//记录程序开始时间
job();//这里放抽象方法便于子类对其重写,同时动态绑定,找子类的重写
long end = System.currentTimeMillis();//记录程序结束时间
System.out.println("执行时间为" + (end - start));
}
}
//AA和BB都继承父类,并且按照各自的任务重写job方法
package com.abstractDetail;
class AA extends TimeTemple {
@Override
public void job() {//实现了父类的抽象job方法
long num = 0;
for (int i = 1; i < 10000000; i++) {
num += i;
}
}
}
package com.abstractDetail;
public class BB extends TimeTemple {
@Override
public void job() {
long num = 1;
for (int i = 1; i < 100000; i++) {
num *= i;
}
}
}
//测试
package com.abstractDetail;
public class Job {
public static void main(String[] args) {
AA aa = new AA();
BB bb = new BB();
aa.time();
bb.time();
}
}
________________________________________
Day23 End
整个课程已经过半了,说实话,掌握的可能还是比较欠,这两周应该是我这学期最忙的时候,很多考试,还要对论文进行复现,这些都没学,还要健身......加油吧!
离回家还有67天~
浙公网安备 33010602011771号