抽象类的基本概念(无法实例化)
在所有的普通方法上面都会有一个“{}”,这个表示方法体,有方法体的方法一定可以被对象直接使用。而抽象方法,是指没有方法体的方法,同时抽象方法还必须使用关键字abstract做修饰,而拥有抽象方法的类就是抽象类,抽象类要使用abstract关键字声明。
//定义一个抽象类 abstract class A{ //普通方法 public void fun(){ System.out.println("存在方法体的方法"); } public abstract void print();//抽象方法,没有方法体,有abstract关键字做修饰 }
抽象类的使用原则:
1.抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public;
2.抽象类不能直接实例化,需要依靠子类采用向上转型的方式处理;
3.抽象类必须有子类,使用extends继承,一个子类只能继承一个抽象类;
4.子类(如果不是抽象类)则必须覆写抽象类之中的全部抽象方法(如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类。);
接口(interface)
接口可以理解为一种特殊的类,里面全部是由全局常量和公共的抽象方法所组成。接口是解决Java无法使用多继承的一种手段,但是接口在实际中更多的作用是制定标准的。或者我们可以直接把接口理解为100%的抽象类,既接口中的方法必须全部是抽象方法
特点
1.接口指明了一个类必须要做什么和不能做什么,相当于类的蓝图
2. 就像一个类一样,一个接口也能够拥有方法和属性,但是在接口中声明的方法默认是抽象的。(即只有方法标识符,而没有方法体)
- 3.如果一个类实现了一个接口中要求的所有的方法,然而没有提供方法体而仅仅只有方法标识,那么这个类一定是一个抽象类。(必须记住:抽象方法只能存在于抽象类或者接口中,但抽象类中却能存在非抽象方法,即有方法体的方法。接口是百分之百的抽象类)
接口和抽象类的区别
1.1 抽象类概念:
一个方法无法给出具体明确的,该方法可以声明为抽象方法
拥有抽象类方法的类,叫做抽象类
1.2 抽象类特点
继承了抽象类的子类,要么对父类的抽象方法进行重写,要么自己也是抽象类
抽象类也可以拥有普通方法
抽象类不能创建对象
抽象类也有构造方法,但是是为了子类创建对象使用
1.3 抽象类存在价值
模板模式:由于抽象类既能拥有普通的方法,又有抽象的方法,这样,抽象类既能自己完成一些功能,又给子类提供无限的可能。
二、接口
关键字:interface
2.1 接口的概念
比抽象还抽象,或者说是一种特殊的抽象类
2.2 接口的特点
不能实例化
没有构造方法
方法默认public abstract修饰
变量默认public static final修饰
2.3 接口存在价值
定义了规则:一个类可以同时实现多个接口
拓展了程序
多态(提高代码拓展性)
同一个行为具有多种表达形式
前提:
1.继承或实现
2.要有方法重写
3.父类引用指向子类对象
多态调用静态(成员变量,成员方法):
编译看左边运行也看左边(因为在编译的时候会自动变成类名调用直接使用父类的逻辑)
定义父类 Person 类
public class Person {
public void work() {
System. out.println("...!");
}
}
定义子类 Student 类
public class Student extends Person {
@Override
public void work() {
System.out.println("学生工作学习!");
}
}
定义子类 Teacher 类
public class Teacher extends Person {
@Override
public void work() {
System.out.println("老师工作教书!");
}
}
体现多态性
//多态性
public class Test01 {
public static void main(String[] args) {
//多态形式,创建对象
//注意编译类型看等号左边,运行类型看等号右边
Person p1 = new Student();
//此时调用的是 Student 类 的 work() 方法
p1.work();
//多态形式,创建对象
Person p2 = new Teacher();
//此时调用的是 Teacher 类 的 work() 方法
p2.work();
}
}
多态的转型
1 向上转型
父类的引用指向子类的对象
- 编译类型看左边,运行类型看右边
- 可以调用父类的所有成员(需遵守访问权限)
- 不能调用子类的特有成员
- 运行效果看子类的具体实现
语法: 父类类型 引用名 = new 子类类型(); //右侧创建一个子类对象,把它当作父类看待使用
2 向下转型
一个已经向上转型的子类对象,将父类引用转为子类引用
- 只能强制转换父类的引用,不能强制转换父类的对象
- 要求父类的引用必须指向的是当前目标类型的对象
- 当向下转型后,可以调用子类类型中所有的成员
语法: 子类类型 引用名 = (子类类型) 父类引用; //用强制类型转换的格式,将父类引用类型转为子类引用类型
instanceof 比较操作符
为了避免上述类型转换异常的问题,我们引出 instanceof 比较操作符,用于判断对象的类型是否为XX类型或XX类型的子类型。
- 格式:对象 instanceof 类名称
- 得到一个boolean值结果,也就是判断前面的对象能不能当作后面类型的实例
模板设计模式
优势
1.只需要关注不同的流程,相同的交给父类(模板类)去做
2.解耦:各司其职,一个类只关注自己的事情
固定的流程已经写好了,变化的流程定义成了抽象方法,被子类重写。
模板设计就是一种编码风格,把抽象类看作是一个模板,模板中不能决定的东西定义成抽象方法,让使用模板的去重写抽象方法实现需求
简单来说:模板设计就是提前搭建好了一些框架,但是更细节的东西需要实现类再去实现
public abstract class TextTemplateDemo {
public final void write(){
System.out.println("hahahh");
body();
System.out.println("hahahhahah");
}
public abstract void body();
}
public class tom extends TextTemplateDemo{
@Override
public void body() {
System.out.println("哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈啊哈哈哈哈哈哈啊哈哈啊哈哈哈");
}
}
public class test {
public static void main(String[] args) {
tom t=new tom();
t.write();
}
}
适配器设计模式
注:JDK1.8中对接口增加了新的特性:
(1)默认方法(default method):JDK 1.8允许给接口添加非抽象的方法实现,但必须使用default关键字修饰;定义了default的方法可以不被实现子类所实现,但只能被实现子类的对象调用;如果子类实现了多个接口,并且这些接口包含一样的默认方法,则子类必须重写默认方法;(2)静态方法(static method):JDK 1.8中允许使用static关键字修饰一个方法,并提供实现,称为接口静态方法。接口静态方法只能通过接口调用(接口名.静态方法名)。