【JAVA】笔记(5)--- final;抽象方法;抽象类;接口;解析继承,关联,与实现;
final:
1.理解:凡是final修饰的东西都具有了不变的特性;
2.修饰对象:
1)final+类--->类无法被继承;
2)final+方法--->方法无法被覆盖;
3)final+变量--->只能被赋值一次;
eg:被 final 修饰的引用,由于只能被赋值一次,所以其储存的地址不变,所以它的指向也就不会改变,但不代表其指向的对象内部的数据不会改变;
注意:
被 final 修饰的变量为实例变量时,必须手动初始化(否则报错),不能系统自动赋值了;
final 修饰的静态变量一般与static联合使用,称为常量,eg:public static final double PI = 3.1415926 ;
抽象方法:
1.概念:被 abstract 修饰的方法,无方法体( { } 也不能写 ),而且不以 ” } “结尾,以 ” ;“ 结尾;
2.格式:public abstract void fangFa ( ) ;
3.注意:抽象方法可以有参数列表;
当抽象类中的抽象方法被在普通类中被重写时,abstract 要去掉,参数列表不能改变,并且加上方法体;
抽象类与接口:
一、抽象类:
1、概念:将类之间的共同特征提取出来,抽象为一个类,这种类就叫抽象类;
2、格式:abstract + class + 类名
3、抽象类可以被继承,子类可以为抽象类,也可以不是,但如果不是抽象类,必须对抽象类(父类)中的所有抽象方法进行覆盖;
4、意义:降低接口实现类与接口之间实现难度;
5、注意:抽象类无法实例化为对象;
若抽象之间有共同特征,也可将其进一步抽象为一个抽象类;
抽象类中也有构造方法,意义:给子类使用;
抽象类中可以有普通方法,也可以有抽象方法,但是抽象方法必须出现在抽象类中,不能出现在非抽象类中;
二、接口:
1、定义: interface + 接口名
2、特性:
接口支持多继承;// interface A extends B,C,D { }
接口中所有的方法都是默认被 public abstract 修饰的,且可以省略,eg: 返回值类型 + 方法名(参数列表);
接口中的方法都是抽象的(没有方法体),如果需要定义具体方法实现,此时方法需要使用 default 修饰;
接口中的所有量都是默认被 public static final 修饰的,且可以省略,所以接口中只有常量,没有变量;
接口被“继承”不用 extends 用 implements(实现),接口之间可以相互继承,但是不能相互实现;
接口的完全抽象的性质,可以进一步使程序的耦合性降低,拓展性提高;
3、注意;
1)extends 可以与 implements 共存,extends 在前,implements 在后;
2)接口由于是完全抽象的,所以被实现时,也与抽象类遵循相同的规则,若子类不为抽象类,则需要对接口中的所有抽象方法都进行方法覆盖
分析原因:因为继承与实现都相当于将类体中或接口内的代码复制粘贴到子类中,所以遵循” 抽象方法只能出现在 抽象类 / 接口中 “的原则,必须要对 抽象/接口 中的所有抽象方法进行方法覆盖-->即将抽象方法转化为普通方法 ;
3)抽象类实现接口时,不需要对接口方法进行重写;
4)抽象类有构造方法,但是不能使用(实例化对象);
三、抽象类与接口的区别;
1)构造方法:前有,后无;
2)继承机制:前单“继承”,后多“继承”(implement 后可以加多个接口,extends 后只可以加一个类)
注意:接口也可以 extends 多个接口;
3)抽象类中的方法与量都无限制,接口中的方法只能是抽象方法,量只能是常量;
解析继承,关联,与实现:
1.继承:” is a “, 例如:猴子是一种动物,则 猴子 extends 动物;
---使猴子继承动物该有的特性
2.关联:” has b “,例如:我有一双鞋类,则 class 我 { 鞋 鞋 ; }
---将鞋类作为一种属性写在 我类 中,因为我穿鞋呀,所以利用关联来使” 我 拥有了 鞋“
3.实现:” like c “,例如:厨师像一个菜单一样,则 class 厨师 interfaces 菜单 { 重写菜单中的方法 }
---对于” 顾客利用菜单来点菜 “的机制来说,厨师类来实现接口,顾客来调用接口
辅助理解代码:
public class 顾客点西式柿子炒鸡蛋 {
public static void main(String[] args) {
//利用多态机制创建美国厨师对象
FoodMenu cooker=new AmericanCooker();
//调用构造方法使 顾客拿到了菜单,并将对象美国厨师传到了菜单中
Customer customer=new Customer(cooker);
//调用顾客中的点菜方法(顾客中的点菜方法调用菜单中的柿子炒鸡蛋方法,此时菜单中的方法已被美国厨师中的方法覆盖了,所以顾客吃到的是西式柿子炒鸡蛋)
customer.order();
}
}
interface FoodMenu{
void shiZiChaoJiDan();
}
class ChinaCooker implements FoodMenu{
public void shiZiChaoJiDan(){
System.out.println("中国师傅做的柿子炒鸡蛋!");
}
}
class AmericanCooker implements FoodMenu{
public void shiZiChaoJiDan(){
System.out.println("美国师傅做的柿子炒鸡蛋!");
}
}
class Customer{
private FoodMenu foodMenu;
public Customer() {
}
public Customer(FoodMenu foodMenu) {
this.foodMenu = foodMenu;
}
public FoodMenu getFoodMenu() {
return foodMenu;
}
public void setFoodMenu(FoodMenu foodMenu) {
this.foodMenu = foodMenu;
}
public void order(){
foodMenu.shiZiChaoJiDan();
}
}
运行结果:
美国师傅做的柿子炒鸡蛋!
Process finished with exit code 0
代码解析;
1.菜单是一个接口(菜单上有一个抽象的照片:柿子炒鸡蛋);
2.顾客面向菜单点菜,调用接口;
3.后台的厨师负责把柿子炒鸡蛋做好,是接口的是实现者;
4.接口作用:这个饭馆的菜单,让顾客和后厨解耦合了,顾客不用找后厨,后厨不用找顾客,他们之间完全依靠这个抽象的菜单沟通;
5.总结:面向接口编程,可以降低程序的耦合度,提高程序的拓展力;接口的使用离不开多态机制(接口+多态才可以达到降低耦合度);任何一个接口都有调用者和实现者,接口可以将调用者与实现者解耦合,调用者面向接口调用,实现者面向接口编写实现;
随笔:
1、Java语言中凡是没有方法体的方法都是抽象方法?
错,Object 类中就有很多方法都没有方法体,都是以 ” ;“ 结尾的,但他们 都不是抽象方法,eg:public native int hashCode( ) ;
此方法底层是调用了C++写的动态链接库程序,native 表示调用 JVM 本地程序;
2、final 与 abstract 不能联合修饰一个东西;
由于博主目前只是一只猿宝宝,所以有些地方可能说的有些片面,若前辈们能够指点一二就更好了 (~ ̄(OO) ̄)ブ
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步