今日重点:
一、抽象
(1)概念
当我们在做子类共性功能抽取时,有些方法在父类中并没有具体的体现,这个时候就需要抽象类了!在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类。
比如短袖类和衬衫类都继承衣服类,短袖类和衬衫类都有颜色属性,抽取共性,衣服类就有颜色这个属性,具体是什么颜色衣服类不管,只要有颜色这个抽象方法就行了,具体是什么颜色有短袖类和衬衫类去实现。
//抽象类的定义 public abstract class 类名 {} //抽象方法的定义 public abstract void eat();
(2)抽象方法
1.基本概念
- 在所有的普通方法上面都会有一个“{}”,这个表示方法体,有方法体的方法一定可以被对象直接使用。
- 而抽象方法,是指没有方法体的方法,同时抽象方法还必须使用关键字abstract做修饰。
- 抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public。
2.语法结构
public abstract void 方法名();
3.特点
关键字:abstract
抽象方法在方法体内不写任何方法体,没有大括号
4.抽象方法存在的意义
抽象方法的意义在于,约定----自定义的规则,约定了返回值,访问权限,参数列表,需要在重写的时候去定义方法体,约定大于配置,配置大于编码。规定了他的所有子类必须拥有一个这样子的方法,或者提供一个这样子的服务,但是实现这个方法的方式,会因为子类的不同的结构而有所不同。 之所以需要继承,是因为这个方法是这些子类的一个共同属性。 或者说,父类要通过这些抽象的方法,提供某种特定的服务,但是实现方式在子类中有所不同,所以在父类中写了抽象方法强制子类实现,保证能够提供这种服务。
(3)抽象类---有抽象方法的类
1.基本概念
abstract(抽象)能修饰类、方法---抽象方法必须在一个抽象类里。抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类。
- 众所周知,父类是将子类所共同拥有的属性和方法进行抽取,这些属性和方法中,有的是已经明确实现了的,有的还无法确定,那么我们就可以将其定义成抽象,在后日子类进行重用,进行具体化。所以,抽象类是为了把相同的但不确定的东西的提取出来,为了以后的重用。定义成抽象类的目的,就是为了在子类中实现抽象方法。
- 简单说,拥有抽象方法的类就是抽象类(但抽象类中也可以不包含抽象方法),抽象类要使用abstract关键字声明。
2.抽象类的特性和使用
- 抽象类不能被实例化。因为抽象类中方法未具体化,这是一种不完整的类,所以直接实例化也就没有意义了。
- 抽象类不能被直接实例化,需要依靠子类采用向上转型的方式处理
- 抽象类的使用必须有子类,使用extends继承,一个子类只能继承一个抽象类。
- 子类(如果不是抽象类)则必须覆写(重写)抽象类之中的全部抽象方法(如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类)。简单来说就是,继承一个抽象类,必须实现抽象类中的抽象方法,除非子类也是抽象类。
- 抽象类可以不包含抽象方法,但如果类中包含抽象方法,就必须将该类声明为抽象类。
3.抽象类的成员特点
①成员变量:
既可以是变量
也可以是常量
②构造方法:
既可以空参构造
也可以有参构造
③成员方法:
既可以抽象方法
也可以普通方法4.抽象类示例
创建一个A类(做父类)
public abstract class A { //普通方法 public void fun(){ System.out.println("存在方法体的方法"); } //抽象方法,没有方法体,有abstract关键字做修饰 public abstract void print(); }
创建一个B类(作为子类)
public class B extends A{//B类是抽象类A的子类,是一个普通类 //强制要求覆写 @Override public void print() { System.out.println("溜溜盈要继续努力!!!"); } public static class Test{ public static void main(String[] args) { //向上转型 A a=new B(); //被子类所覆写过的方法 a.print(); } } }
运行结果
5.抽象类的好处
抽象方法是一个模板或约束,避免了子类的随意性,需要实现它的类必须重写它的抽象那个方法。
(3)抽象的思考问答
1.抽象方法能不能用private修饰?
不能。开发中,抽象方法基本上都是public
2.抽象方法能不能用final修饰?不能。用final修饰的方法是不允许重写,抽象类必须有子类,而final定义的类不能有子类
3.抽象类能不能用final修饰?不能。用final修饰的类是不允许被继承的。
4.当我们定义一个抽象类,这个抽象类中可以有哪些结构?
属性,成员方法,构造器(构造方法),抽象方法,常量
由于抽象类里会存在一些属性,那么抽象类中一定存在构造方法,其存在目的是为了属性的初始化。并且子类对象实例化的时候,依然满足先执行父类构造,再执行子类构造的顺序。
示例如下:
创建一个C类(做父类)
public abstract class C { public C(){ System.out.println("C类的构造方法"); } public abstract void print(); }
创建一个D类(做子类)
public class D extends C{ public D(){ System.out.println("D类的构造方法"); } @Override//重写父类的抽象方法 public void print() { } } class Test{//测试类 public static void main(String[] args) { C c=new D();//向上转型 } }
运行结果
5.抽象类中能不能没有抽象方法?
抽象类可以没有抽象方法
6.抽象类是不能被实例化的。抽象类不能创建对象。
7.抽象类的构造器存在的意义为了约定子类的构造器必须和父类要匹配
8.抽象类能否使用static声明吗?
外部抽象类不允许使用static声明,而内部的抽象类可以使用static声明。使用static声明的内部抽象类相当于一个外部抽象类,继承的时候使用“外部类.内部类”的形式表示类名称。
内部抽象类使用示例:
创建一个A类,static定义的内部类B类属于外部类
public abstract class A { //static定义的内部类属于外部类 public static abstract class B{ public abstract void print(); } } //class C extends A.B{//C类也可以写在这里 // public void print(){ // System.out.println("didididii"); // } //} //class Test {//测试类可以写在这地方,没有public // // public static void main(String[] args) { // A.B ab = new C();//向上转型 // ab.print(); // } //}
创建一个C类
public class C extends A.B{ public void print(){ System.out.println("didididii"); } }
创建一个Test测试类
public class Test {//测试类 public static void main(String[] args) { A.B ab = new C();//向上转型 ab.print(); } }
测试结果
抽象类中的static方法可以直接调用。
示例代码
public abstract class A { public static void print(){ System.out.println("不要气馁继续加油"); } } class TestDemo { public static void main(String[] args) { A.print(); } }
测试结果
有时候由于抽象类中只需要一个特定的系统子类操作,所以可以忽略掉外部子类。这样的设计在系统类库中会比较常见,目的是对用户隐藏不需要知道的子类。
示例代码
public abstract class A { public abstract void print(); //内部抽象类子类 private static class B extends A{ //覆写抽象类的方法 public void print(){ System.out.println("啦啦啦 !"); } } //这个方法不受实例化对象的控制 public static A getInstance(){ return new B(); } } class TestDemo { public static void main(String[] args) { //此时取得抽象类对象的时候完全不需要知道B类这个子类的存在 A a = A.getInstance(); a.print(); } }
测试结果
![]()
以上的内容参考链接为:https://www.jianshu.com/p/0530e14192b4
(4)课上案例练习
还没有消化完!!!!!!!!!!!!!!!!!!!
二、接口
(1)概念
比抽象类更高级的抽象
接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用。Java中的接口更多的体现在对行为的抽象。接口是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
(2)接口结构中的特点
接口中的结构必须是public
1.接口用关键字interface修饰
public interface 接口名 {}
接口的声明
public interface 接口名称 [extends 其他的接口名] { // 声明变量 // 抽象方法 }
2.类实现接口用implements表示
public class 类名 implements 接口名 {}
3.接口不能直接实例化,通过接口实现类对象来实例化,叫做接口多态
4.接口的子类,要么重写接口中的所有抽象方法,要么子类也是抽象类5. 接口中的抽象方法默认是public abstract
6.接口中的常量默认是public static final
(3)接口的成员特点
1.成员变量
只能是常量
默认修饰符:public static final2.构造方法
没有,因为接口主要是扩展功能的,而没有具体存在
3.成员方法
只能是抽象方法
默认修饰符:public abstract
(4)Java中接口的变化
* JDK1.7之前:接口中只能定义抽象方法,不能有属性,不能有方法。
* (静态的常量)
* JDK8及以后:接口中只能定义抽象方法,不能有属性,可以有默认方法和静态方法
* 静态常量。
* JDK7---JDK8:默认方法,静态方法。
(5)接口存在的意义
约定----自定义的规则:接口其实就是一种约定,实现接口的类就必须遵守这个接口的约定
1.使用抽象类或抽象方法不可避免继承问题。,一些功能性的抽象类或抽象函数随着项目的扩展中和类体系的膨胀进而影响了整个系统类结构的清晰性,所以进行约定。
2.接口其实相当于一个标准,接口中的每一个方法、属性等对象,使用接口可以规范一个项目的源码,接口中的定义为抽象定义,不需要 public private 等关键字,但是在实现的类中必须使用这些关键字去描述。
3.接口的作用简单一点就是:接口是用来标记类的,不同的类属于不同的接口(通过向上转型),管理接口比管理各种各样的类方便多了,接口体现了抽象的观点
(6)面试题
1.继承抽象类和实现接口的异同
参考链接:https://blog.youkuaiyun.com/u011033906/article/details/103182094
2.抽象类和接口的区别与联系
1、抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。
2、抽象类要被子类继承,接口要被类实现。
3、接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现
4、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
5、抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,一个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。
6、抽象方法只能申明,不能实现,接口是设计的结果 ,抽象类是重构的结果
7、抽象类里可以没有抽象方法
8、如果一个类里有抽象方法,那么这个类只能是抽象类
9、抽象方法要被实现,所以不能是静态的,也不能是私有的。
10、接口可继承接口,并可多继承接口,但类只能单根继承。
接口与类的区别
1.接口不能用于实例化对象。
2.接口没有构造方法。
3.接口中所有的方法必须是抽象方法。
4.接口不能包含成员变量,除了 static 和 final 变量。
5.接口不是被类继承了,而是要被类实现。
6.接口支持多继承。
3.在java中只有单继承吗
在java中是存在多继承的,发生在接口之间, java类与类之间只有单继承。
(7)练习小案例
要求;
1.定义一个接口CanFly,描述会飞的方法public void fly();
2.分别定义类飞机和鸟,实现CanFly接口。
3.定义一个测试类,测试飞机和鸟,在main方法中创建飞机对象和鸟对象,再定义一个makeFly()方法,其中让会飞的事物飞。并在main方法中调用该方法,让飞机和鸟起飞。public interface CanFly {//定义一个接口 public void fly(); }
package com.jr.lianxi; public class Bird implements CanFly{//Bird类 public void fly(){ System.out.println("小鸟起飞"); } }
package com.jr.lianxi; public class Plane implements CanFly{//飞机类 public void fly(){ System.out.println("飞机起飞"); } }
package com.jr.lianxi; public class Test { public static void main(String[] args) { //实例化对象 Plane p=new Plane(); new Test().fly(p); Bird b=new Bird(); new Test().fly(b); } private void fly(CanFly f) { f.fly(); } }
结果为:
以上的内容参考链接为:
https://blog.youkuaiyun.com/s001125/article/details/110140965
https://blog.youkuaiyun.com/cjs990204/article/details/121029487
(8)课上案例练习
还没有消化完!!!!!!!!!!!!!!!!!!!
(9)匿名实现类
三、栈和队列
(1)概念
栈和队列就是建立在两个最基础的数据结构的基础上构建的两个受限制的线性表