一、抽象类
- 基本介绍:
-
- 抽象类:用abstract关键字修饰一个类
-
- 抽象方法:使用abstract关键字来修饰一个方法
-
- 抽象类的价值更多作用是在于设计,是设计者设计好后,让子类继承并实现抽象类
-
- 抽象类,是考官比较爱问的知识点,在框架设计模式使用较多
-
访问修饰符 abstract 类名{
}
- 抽象类的注意事项和使用细节
-
- 抽象类不能被实例化
-
- 抽象类不一定要包含抽象方法
-
- 一旦一个类包含了抽象方法,则这个类必须声明为抽象类
-
- abstract只能修饰类和方法,不能修饰属性和其他的
-
- 抽象类可以有任意的成员(即抽象类本质还是一个类),所以可以有类的各种成员
-
- 抽象方法不能有主体,即不能实现,不能创建对象实例
-
- 如果一个类继抽象承了抽象类,则它必须实现抽象类的所有抽象方法,除非它自己也声明为抽象类
-
- 抽象方法不能使用private,final,static 来修饰,因为这些关键字都是和重写相违背的
-
抽象类和方法的应用:
1,员工类(Employee)抽象类
abstract public class Employee {
private String name;
private int id;
private double salary;
public Employee(String name, int id, double salary) {
this.name = name;
this.id = id;
this.salary = salary;
}
public abstract void work();
public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
}
2,manager类
public class Manager extends Employee{
private double bonus;
public Manager(String name, int id, double salary) {
super(name, id, salary);
}
public double getBonus() {
return bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
@Override
public void work() {
System.out.println("经理 "+getName()+"工作中");
}
}
3,普通员工类(CommonEmployee)
public class CommonEmployee extends Employee{
public CommonEmployee(String name, int id, double salary) {
super(name, id, salary);
}
@Override
public void work() {
System.out.println("普通员工"+getName()+"在工作中");
}
}
4,测试类
public class AbstractExercise01 {
public static void main(String[] args) {
Manager jack = new Manager("jack", 999, 5000);
jack.setBonus(7000);
jack.work();//经理 jack工作中
CommonEmployee tom = new CommonEmployee("tom", 888, 6000);
tom.work();//普通员工tom在工作中
// abstract final class A();不能通过编译:final不能继承
// abstract public static void A();不能编译通过,static关键字和方法重写无关
// abstract private void A();不能编译通过,private的方法不能重写
}
}
一、1、抽象类的最佳实践-模板设计模式
-
需求
- 有多个二类,完成不同的任务job
- 要求能够得到各自的完成任务的实践
-
最佳实践: 设计一个抽象类(Template),完成如下功能
-
- 编写方法calculateTime(),可以计算某段代码的耗时时间
-
- 编写抽象方法
-
- 一个子类AA,和一个子类BB,继承抽象类Template,并实现job方法
-
- 编写一个测试类Test
-
1,AA类
public class AA extends Template {
// public void calculate(){
// long start=System.currentTimeMillis();
// job();
// long end=System.currentTimeMillis();
// System.out.println("开始时间:"+start+"结束时间:"+end+"执行时间:"+(end-start));
//
// }
public void job(){
long num=0;
for (long i = 1; i <= 800000; i++) {
num+=i;
}
}
}
2,BB类
public class BB extends Template{
// public void calculate(){
// long start2=System.currentTimeMillis();
// job();
// long end=System.currentTimeMillis();
// System.out.println("BB开始时间:"+start2+"结束时间:"+end+"执行时间:"+(end-start2));
//
// }
public void job(){//这里也是重写了Template的方法
long num=0;
for (long i = 1; i <= 80000; i++) {
num*=i;
}
}
}
3,Template类
abstract public class Template {//抽象类
// 模板设计模式
public abstract void job();
public void calculate(){
long start=System.currentTimeMillis();
job(); //这里实现动态绑定机制
long end=System.currentTimeMillis();
System.out.println("开始时间:"+start+"结束时间:"+end+"执行时间:"+(end-start));
}
}
4,测试类
public class Test {
// 弄一个父类出来——————模板设计模式
public static void main(String[] args) {
AA aa = new AA();
aa.calculate();
BB bb = new BB();
bb.calculate();
}
}
二、接口
- 接口就是给出一些没有实现的方法,封装到一起,起到某个类要使用的时候,再根据具体情况把这些方法写出来。
- 语法:
interface 接口名{
//属性
//方法(1.抽象方法;2.默认方法(需要用default修饰(并且要在jdk8及以上版本才行));3.静态方法
}
- 在jdk7前,接口里的所有方法都没有方法体
- jdk8以后接口类可以有静态方法,默认方法,也就是说接口中可以有方法的具体实现
public interface AInterface {
// 在接口中,抽象方法,可以省略abstract关键字
public void hi();
// 默认方法(jdk8及以上版本)
default public void you(){
System.out.println("you well");
}
// 静态方法
public static void cry(){
System.out.println("静态方法可以");
}
}
- 应用场景
- 1、规范代码
- 2、方便统一管理
声明接口:(统一方法名称,让其他类实现)
public interface DBInterface {
public void connect();
public void close();
}
mysql类
public class mySql implements DBInterface {
@Override
public void connect() {
System.out.println("连接mysql");
}
@Override
public void close() {
System.out.println("关闭mysql");
}
}
oracle类
public class oracleDb implements DBInterface {
@Override
public void connect() {
System.out.println("连接oracle");
}
@Override
public void close() {
System.out.println("关闭Oracle");
}
}
测试类
public class InterfaceTest {
public static void main(String[] args) {
// 操作mysql
mySql mySql = new mySql();
work(mySql);
// 操作oracle
oracleDb oracleDb = new oracleDb();
work(oracleDb);
}
public static void work(DBInterface dbInterface){
dbInterface.connect();
dbInterface.close();
}
}
- 接口的注意事项和细节
-
- 接口不能被实例化
-
- 接口中所有方法是public方法,接口中的抽象方法可以不用abstract关键字修饰
-
- 一个普通类实现接口,必须将该接口的所有的抽象方法实现,默认方法和静态方法没有强制要求
-
- 抽象类实现接口,可以不用实现接口里面的抽象方法
-
- 一个类同时可以实现多个接口
-
- 接口中的属性只能是被final修饰的,而且是public static final 修饰的
-
- 接口中的访问形式:接口名.属性名
-
- 一个接口不能继承其他的类,但是可以继承多个别的接口
-
- 接口的修饰符只能是public和默认
-
public class interfaceDetail {
public static void main(String[] args) {
// 1.接口不能被实例化,就是不能(new。。。。)
C c = new C();
//下面三句可以看出b是对象共享的
System.out.println(IB.b);
System.out.println(C.b);
System.out.println(c.b);
c.say();
// c.b=200;//这里会报错,final不能修改它的值
}
}
interface IB{
public int b=10;//======public static final int b=10;
// 接口中的属性!!!!!只能!!!!!!!是final 的,而且是 public static final int d=100; final修饰的属性必须(赋初值)
//
// 2.接口中的所有方法都是public方法,接口中抽象方法可以不用abstract修饰
void say();
}
//3.一个接口不能继承其他的类,但是能继承多个别的接口
interface IC extends IA,IB{}
class C implements IB{
// 4.一个普通类实现接口,就必须将该接口的所有方法都实现
@Override
public void say() {
}
}
abstract class D implements IB{
// 5.抽象类实现接口,可以不用实现接口的方法
}
二、1、接口与继承的比较
- 实现接口是java对单继承的一种补充
- 举例理解继承和接口的差别:小猴子要想学习爬树,可以继承老猴子的特性;但是小猴子想学飞行,它就只能通过实现小鸟的飞行特性来学习了(因为猴子是不会飞行的)…
public class ExtendsVsInterface {
public static void main(String[] args) {
LittleMonkey wuKong= new LittleMonkey("悟空");
wuKong.climbing();
wuKong.swimming();
wuKong.fly();
}
}
class Monkey{
private String name;
public Monkey(String name) {
this.name = name;
}
public void climbing(){
System.out.println(name+"会爬树");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//接口
interface Fish{
void swimming();
}
interface Bird{
void fly();
}
//继承
//小结:当子类继续了父类,就自动地拥有父类的功能
// 如果子类需要扩张功能,可以通过实现接口的方式扩展
// 可以理解,实现接口 是对 java的 单继承机制的一种补充
class LittleMonkey extends Monkey implements Fish,Bird{
public LittleMonkey(String name) {
super(name);
}
@Override
public void swimming() {
System.out.println(getName() + "通过学习,可以像鱼儿一样游泳");
}
@Override
public void fly() {
System.out.println(getName()+"通过学习,可以像小鸟一样飞翔");
}
}
小结:当子类继续了父类,就自动地拥有父类的功能
// 如果子类需要扩张功能,可以通过实现接口的方式扩展
// 可以理解,实现接口 是对 java的 单继承机制的一种补充
- 接口和继承解决的问题不同
- 1)继承的价值主要在于:解决代码的复用性和可维护性
- 2)接口的价值主要在于:设计,设计好各种规范(方法),让其他类去实现这些方法
- 接口比继承更加灵活
- 1)接口比继承更加灵活,继承是满足is - a 的关系,而接口只需满足 like - a的关系
- 2)接口在一定程度上实现代码解耦【即接口的规范性+动态绑定机制】
二、2、接口多态
多态数组代码演示:
public class Arr {
public static void main(String[] args) {
// 多态数组
Usb[] usb=new Usb[2];
usb[0]=new Phone();
usb[1]=new camera();
for (int i = 0; i < usb.length; i++) {
usb[i].work();//动态绑定机制
// 和前面一样,我们仍然需要向下转型
if(usb[i] instanceof Phone){ //判断它的 !!运行类型!!
((Phone) usb[i]).call();
}
}
}
}
interface Usb{
void work();
}
class Phone implements Usb{
public void call(){
System.out.println("手机可以用来打电话");
}
@Override
public void work() {
System.out.println("手机在工作中");
}
}
class camera implements Usb{
@Override
public void work() {
System.out.println("相机在工作中");
}
}
接口多态传递:
//演示多态传递现象
public class Pass {
public static void main(String[] args) {
// 接口类型的变量可以 指向,实现了 该接口 的对象实例
IG ig=new Teacher();
// 如果IG继承了IH这个接口,而我们的Teacher 类实现了 IG接口
// 那么,实际上就相当于Teacher 类也实现了IH接口
// 这就是所谓的 : 接口多态传递
IH ih=new Teacher();
}
}
interface IH{
void hh(); //这里建立了一个方法,然后下面的类会出现错误
}
interface IG extends IH{}
class Teacher implements IG{
@Override
public void hh() {
}
}
接口例题一:
public class work01 {
public static void main(String[] args) {
C c = new C();
c.pX();
}
}
interface A{
int x=0;
}
class B{
int x=1;
}
class C extends B implements A{
public void pX(){
// System.out.println(x);//错误,原因是x不明确
// 可以明确的指定x
// 访问接口的x 就用 A.x;
// 访问父类的x 就用 super.x;
System.out.println("A.x="+A.x+ "super.x="+super.x);
}
}