第二部分
***主要知识点
l 抽象类&抽象方法
l 接口
l super和this关键字
l static关键字
l final关键字
1.抽象类&抽象方法
1.1抽象类与抽象方法概念
抽象类用来描述一种类型应该具备的基本特征与功能, 具体如何去完成这些行为由子类通过方法重写来完成,如:
犬科均会吼叫,但属于犬科的狼与狗其吼叫内容不同。所以犬科规定了有吼叫功能,但并不明确吼叫的细节。吼叫的细节应该由狼与狗这样的犬科子类重写吼叫的方法具体实现。
类似上边犬科中的吼叫功能,并不明确实现细节但又需要声明的方法可以使用抽象方法的方式完成。即抽象方法指只有功能声明,没有功能主体实现的方法。
具有抽象方法的类一定为抽象类。
那么犬科就可以定义为抽象类,吼叫方法为抽象方法,没有方法体。
1.2抽象类的定义格式
使用abstract修饰抽象类与抽象方法
l abstract在class前修饰类
l abstract在访问权限后,返回值类型前修饰方法,方法没有方法体。
如:
abstract class Person {
public abstract void eat();
}
1.3抽象类&抽象方法的使用
l 抽象类无法直接创建对象,只能被子类继承后,创建子类对象。
l 子类定义时继承抽象类
l 抽象类是事物的描述,子类需要继承父类完成最终的功能实现细节(即重写方法,完成方法体)。
l 将一个抽象方法重写的过程也叫实现方法的过程。
l 类定义后创建实例对象子
在定义好子类后,可以直接创建子类对象。在所有使用子类的地方可以传入子类对象,在所有使用父类的地方也可以传入子类对象,因为属性与方法在子父类中都是相同的。
l 继承抽象类时抽象父类中的抽象方法一定要重写,抽象类中的抽象方法只是一个共性的功能,但是没有方法体,所以就需要我们的子类重写这个方法来具体实现。
示例1:定义一个抽象类Animal,在类中定义抽象方法eat(),定义Dog类继承Animal,重 写eat()方法,在测试类中打印出吃什么? abstract class Animal{ public abstract void eat(); } class Dog extends Animal{ @Override public void eat() { System.out.println("狗吃屎~"); } } public class Test { public static void main(String[] args) { Dog d = new Dog(); d.eat(); } }
|
1.4抽象类注意事项
l 抽象类的意义
抽象类往往用来表示对问题领域进行分析、设计中得出的抽象概念。其存在的意义在于其设计性、复用性与扩展性。
抽象类方便了具体类的定义。
抽象类仅是对功能和属性的声明,表示这类事物应该具备这些内容。限制程序员不能直接创建该抽象类对象,必须定义其子类才可使用。如我们可以听一只狼的叫声,也可以听一只狗的叫声,但是如果我们听一只犬科的叫声就显然不合适了。
l 抽象类继承细节
只有覆盖了抽象类中所有的抽象方法后,其子类才可以实例化。如果存留未实现的抽象方法则该子类仍为一个抽象类,无法创建对象。
抽象类不一定包含抽象方法。
抽象类可以有非抽象方法。
1.4.1抽象类&抽象方法案例1:
题干 |
定义一个父类 门类,包含2个抽象方法:开门和关门
定义一个木头门类,继承抽象类门类,重写开门和关门方法 重写后的开门方法,直接输出"直接推开" 重写后的关门方法,直接输出"关门不牢"
定义一个防盗门,继承抽象类 门类, 包含 打开防盗 和 关闭防盗 的方法,并重写父类的开门、关门方法 重写后的开门方法,需要先调用关闭防盗的方法后再输出"门已经打开,请进!" 重写后的关门方法,需要先调用打开防盗的方法后再输出"门已经关上,非常安全!" 定义一个测试类。 分别创建 木头门 和 防盗门 对象,调用开门 和 关门 方法。 |
所属知识点 |
抽象类与抽象方法的使用 |
题目类型 |
代码题 |
答案 |
public class Demo04_chouXiang { public static void main(String[] args) { // 创建木头门对象 WoodDoor02 wd = new WoodDoor02(); wd.open(); wd.close(); System.out.println("======================="); //创建防盗门对象 FangdaoDoor fdm = new FangdaoDoor(); fdm.open(); fdm.close(); } } abstract class Door03 { //开门方法 abstract void open(); //关门方法 abstract void close(); } //木头门 class WoodDoor02 extends Door03 { //开门方法 void open() { System.out.println("直接推开"); } //关门方法 void close() { System.out.println("关门不牢"); } } //防盗门 class FangdaoDoor extends Door03 { //开门 public void open() { closeFangdao(); System.out.println("门已经打开,请进!"); } //关门 public void close() { openFangdao(); System.out.println("门已经关上,非常安全!"); } //打开防盗锁 public void openFangdao(){ System.out.println("打开防盗锁"); } //关闭防盗锁 public void closeFangdao(){ System.out.println("加上防盗锁"); } } |
1.4.2抽象类&抽象方法案例2:
题干 |
个抽象类Quanke,Quanke中有一个houjiao()的抽象方法, 然后分别定义一个狼类和一个狗类,都继承Quanke这个抽象类, 通过测试类打印出狗狗和狼的叫声 |
所属知识点 |
抽象类与抽象方法的使用 |
题目类型 |
代码题 |
答案 |
代码: //由于我们的方法是抽象的,所以我们的类也要定义成抽的 abstract class quanke { abstract void houjiao(); } class Dog extends quanke { @Override //由于我们抽象类的方法是抽象的,所以子类继承抽象类的时候要重写抽象类中的方法 void houjiao() { // TODO Auto-generated method stub System.out.println("汪汪汪"); } } class wolf extends quanke{ //由于我们抽象类的方法是抽象的,所以子类继承抽象类的时候要重写抽象类中的方法 @Override void houjiao() { // TODO Auto-generated method stub System.out.println("wowowowowow"); } } public class Test { public static void main(String[] args) { Dog dog = new Dog(); wolf wolf = new wolf(); dog.houjiao(); wolf.houjiao(); } } |
2.接口
2.1接口的概念
l 接口是功能的集合,同样可看做是一种数据类型,是比抽象类更为抽象的”类”。
接口只描述所应该具备的方法,并没有具体实现,具体的实现由接口的实现类(相当于接口的子类)来完成。这样将功能的定义与实现分离,优化了程序设计。
l 请记住:一切事物均有功能即一切事物均有接口。
2.2接口的代码体现
在代码体现中,接口的更为抽象表现为其内的所有方法均为抽象方法,同时不定义普通的成员变量(可以定义静态常量,在后边介绍)。
如同抽象类,接口在使用时同样不能创建对象。
类与接口的关系为实现关系,即类实现接口。实现的动作类似继承,只是关键字不同,实现使用implements。
其他类(实现类)实现接口后,就相当于声明:”我应该具备这个接口中的功能”。实现类仍然需要重写方法以实现具体的功能。
2.3接口定义及使用格式
l 接口的定义:
① 定义关键字
与定义类的class不同,接口定义时需要使用interface关键字。
定义接口所在的仍为.java文件,虽然声明时使用的为interface关键字的编译后仍
然会产生.class文件。这点可以让我们将接口看做是一种只包含了功能声明的特殊类。
② 定义格式
使用interface代替了原来的class,其他步骤与定义类相同:
l 方法均为公共访问的抽象方法
l 无法定义普通的成员变量
public interface 接口名 {
抽象方法1;
抽象方法2;
抽象方法3;
}
如:
public interface Usb{g
public abstract void usb();
}
}
l 接口的使用
在具体定义类时实现接口,必须重写(实现)所有抽象方法
class 类 implements 接口1,接口2{}
示例1:定义一个Animal接口,让Dog类实现接口中的吃的功能。并在测试类中打印怎么吃 代码: interface Animal { public abstract void eat(); } class Dog implements Animal { @Override public void eat() { System.out.println("狗狗趴着吃~"); } } public class Test { public static void main(String[] args) { Dog d = new Dog(); d.eat(); } }
|
2.3.1接口案例1:使用java编写以下程序,要求:
定义一个抽象类 门类,包含2个抽象方法:开门和关门
定义一个报警器的接口,包含方法:报警
定义一个防盗门,继承抽象类 门类,并实现报警器接口
包含打开防盗的和关闭防盗的方法,并重写父类的开门、关门方法和报警器的报警方法
重写后的开门方法,需要先调用关闭防盗的方法后再输出"门已经打开,请进!"
重写后的关门方法,需要先调用打开防盗的方法后再输出"门已经关上,非常安全!"
定义测试类,创建 防盗门对象,调用 开门方法、关门方法、报警方法
定义一个抽象类 门类,包含2个抽象方法:开门和关门 定义一个报警器的接口,包含方法:报警 定义一个防盗门,继承抽象类 门类,并实现报警器接口 包含打开防盗的和关闭防盗的方法,并重写父类的开门、关门方法和报警器的报警方法 重写后的开门方法,需要先调用关闭防盗的方法后再输出"门已经打开,请进!" 重写后的关门方法,需要先调用打开防盗的方法后再输出"门已经关上,非常安全!"
定义测试类,创建 防盗门对象,调用 开门方法、关门方法、报警方法 |
|
所属知识点 |
接口、抽象 |
题目类型 |
代码题 |
答案 |
public class Demo05_jieKou { public static void main(String[] args) { //创建 防盗门对象 FangdaoDoor fdm = new FangdaoDoor(); //调用方法 fdm.open(); fdm.close(); fdm.baojin(); } } abstract class Door { //开门方法 abstract void open(); //关门方法 abstract void close(); } //报警器接口 interface Baojingqi { //报警 public abstract void baojin(); } //防盗门 class FangdaoDoor extends Door implements Baojingqi{ //开门 public void open() { closeFangdao(); System.out.println("门已经打开,请进!"); } //关门 public void close() { openFangdao(); System.out.println("门已经关上,非常安全!"); } //打开防盗锁 public void openFangdao(){ System.out.println("打开防盗锁"); } //关闭防盗锁 public void closeFangdao(){ System.out.println("加上防盗锁"); } //报警 public void baojin() { System.out.println("警报,有入侵者!"); } } |
2.3.2接口案例2:
题干 |
私有属性包括:姓名、年龄 公共的行为包括:获取属性值/为属性赋值功能(get/set);学习功能(抽象)。
定义接口:内有管理班级方法。 定义班长类:(班长类是学生类的子类),这里规定班长可以管理班级。
定义测试类。 创建班长类对象 分别用 构造方法 为班长赋值为 “大哥” 20 调用 班长类的方法 |
所属知识点 |
接口、抽象 |
题目类型 |
代码题 |
答案 |
public class Demo06_jieKou { public static void main(String[] args) { //创建班长类 Monitor m = new Monitor("大哥",20); m.setName("大哥"); m.setAge(20); System.out.println("班长的姓名是:" + m.getName() + ",年龄是:" + m.getAge()); //调用方法 m.study(); m.manageClass(); } } /** * 抽象类 - 学生类 */ abstract class Student { private String name;//姓名 private int age;//年龄 public Student(String name, int age) { super(); this.name = name; this.age = age; } public Student() { super(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } //学习功能(抽象) public abstract void study(); } /** * 管理班级功能 接口 */ interface Manage { public abstract void manageClass(); } /** * 具体类 - 班长类 */ class Monitor extends Student implements Manage { public Monitor() { super(); } public Monitor(String name, int age) { super(name, age); } @Override public void manageClass() { System.out.println("班长管理班级"); } @Override public void study() { System.out.println("班长学习"); } } |
2.3.3接口案例3:
题干 |
笔记本(NoteBook)具有运行(run)、关闭(shutDown)和使 备(USB)的功能,其中: useUSB(USB b){ b.open(); } 笔记本运行:在控制台输出“笔记本运行”; 笔记本关闭:在控制台输出“笔记本关闭”; 笔记本使用USB设备:调用usb的开启和关闭功能。 鼠标(Mouse )和键盘(KeyBoard )要能在电脑上使用,即鼠标和键盘必须遵守USB规范; USB设备具有开启(open)和关闭(close)的功能,其中: USB设备开启功能:在控制台打印“XXX开启”; USB设备关闭功能:在控制台打印“XXX关闭”。 根据以上描述写出相关的类和方法。 |
所属知识点 |
接口 |
题目类型 |
代码题 |
答案 |
public class Demo06_jieKou { public static void main(String[] args) { // 创建笔记本实体对象 NoteBook nb = new NoteBook(); // 创建鼠标实体对象 Mouse m = new Mouse(); // 创建键盘实体对象 KeyBoard kb = new KeyBoard(); // 笔记本开启 nb.run(); // 笔记本关闭 nb.shutDown(); // 笔记本使用鼠标 nb.useUSB(m); // 笔记本使用键盘 nb.useUSB(kb); } } //USB接口 interface USB { public abstract void open();// 开启功能 public abstract void close();// 关闭功能 } //鼠标类 class Mouse implements USB{ public void open() { System.out.println("鼠标开启"); } public void close() { System.out.println("鼠标关闭"); } } //键盘类 class KeyBoard implements USB{ public void open() { System.out.println("键盘开启"); } public void close() { System.out.println("键盘关闭"); } } //笔记本类 class NoteBook { // 笔记本开启运行功能 public void run() { System.out.println("笔记本运行"); } //笔记本 关闭功能 public void shutDown() { System.out.println("笔记本关闭"); } // 笔记本使用usb设备,这时当笔记本实体调用这个功能时,必须给其传递一个符合USB规则的USB设备 public void useUSB(USB usb) { usb.open(); usb.close(); } } |
|
|
2.4接口注意事项
l Java支持一个类同时实现多个接口。
l 类可以在继承一个类的同时,实现多个接口。
l 接口中的成员是有固定修饰符的,如果没有写,也会自动加入:
“变量”修饰符为:public static final(static与final面向对象第5天讲解)
方法修饰符为:public abstract(所以依据方法重写的访问权限注意事项,重写接口方
法时,必须使用public)
l 当一个类实现了接口时,必须实现其所有的方法
2.5接口使用辨析
l 类继承类extends,只能单继承
接口继承接口extends可以多继承
类实现接口implements可以多实现
接口不可以继承类!
l 抽象类中可以有非抽象方法
接口中全部为抽象方法
l 抽象类具有成员变量
接口没有普通的成员变量
l 抽象类中的成员无固定修饰符
接口中的成员有固定修饰符
3.this和super关键字
3.1this和super的区别:
l this:
访问本类对象成员变量 this.变量名
调用本类普通方法 this.方法名(参数)
本类构造方法调用本类其他构造 本类构造方法第一行this(参数)
l super:
访问父类对象成员变量 super.变量名
调用父类普通方法 super.方法名(参数)
本类构造方法调用父类构造 本类构造方法第一行super(参数)
l 注意:
this与super在调用构造方法时,均必须在第一行,只能调用其中的一个,所以两个关键字不能同时出现,正所谓一山不容二虎。
3.1.1this和super关键字案例1:
题干 |
this关键字 和 super关键字 |
所属知识点 |
this关键字 和 super关键字 |
题目类型 |
代码题 |
答案 |
public class Demo08_guanJianZi { public static void main(String[] args) { //创建父类对象 //Fu fu = new Fu("小明"); Fu fu = new Fu(); fu.show(); fu.show2(); System.out.println("==============="); //创建子类对象 Zi zi = new Zi(); zi.show(); } } class Fu{ String name ; public void show(){ // this.变量名 ----- 访问本类成员变量 System.out.println(this.name); } public void show2(){ // this.方法名(参数) ----- 调用本类普通方法 this.show(); } //无参构造 public Fu() { //本类构造方法第一行this(参数)----- 本类构造方法调用本类其他构造 this("小花"); } //带参构造 public Fu(String name) { this.name = name; System.out.println("这是父类的有参构造" + name); } } class Zi extends Fu{ public Zi() { super(); } public Zi(String name) { // 本类构造方法第一行super(参数) ----- 本类构造方法调用父类构造super(name); } public void show(){ //super.变量名 ----- 访问父类的成员变量 System.out.println(super.name); //super.方法名() ----- 调用父类普通方法 super.show(); } } |
4.static 关键字
l static是静态修饰符,一般修饰成员。被static修饰的成员属于类,建议通过类名直接访问。也可以通过某个对象访到属于类的静态成员。
l 格式:
类名.静态成员变量名
类名.静态成员方法名(参数)
特点: 2、静态优先于对象存在,被对象共享。 3、因为静态先存在于内存中无法访问后来的对象的中的数据,所以静态无法访问非静态。而且内部无法书写this。因为这时对象有可能不存在,this没有任何-se指向。
静态方法使用注意事项: 1、静态方法不能访问非静态的成员。但是非静态可以访问静态成员的。 说明:静态的弊端在于访问出现局限性。好处是可以直接被类名调用。 2、静态方法中不允许出现this,super关键字。
|
5.final关键字
l final是最终修饰符,可以修饰类、成员方法、成员变量。
l final修饰的类无法被继承。
l final修饰的方法无法被重写。
l final修饰的变量无法被再次赋值,变为了常量。
继承的出现提高了代码的复用性,并方便开发。但随之也有问题,有些类在描述完之后,不想被继承,或者有些类在中的部分方法功能是固定的,子类不能重写。可是当子类继承了这些特殊类之后,就可以对其中的方法进行重写,那怎么解决呢? 要解决上述的这些问题,需要使用到一个关键字final,final的意思为最终,不可变。final是个修饰符,它可以修饰类,类的成员,以及局部变量。 final修饰类不可以被继承,但是可以继承其他类。 final修饰的方法不可以被覆盖,但父类中没有被final修饰方法,子类覆盖后可以加final。 final修饰的变量称为常量,这些变量只能赋值一次。 final修饰的引用类型变量,表示该引用变量的引用不能变,引用所指的对象中的数据还是可以变化的; 什么时候会在程序中定义final常量呢? 当程序中一个数据是固定不变的,这时为了增加阅读性,可以给该数据起个名字。为了保证这个变量的值不被修改,加上final修饰,变量就为阅读性很强的常量。 书写规范,被final修饰的常量名所有的字母都是大写的。如果由多个单词组成单词间通过 _ 连接。 通常规范中:常量名称所有字母大写,若有多个单词组成,单词间使用下划线连接。 public static final修饰的常量称为全局常量;
public static final double PI = 3.14159265358979323846; public static final String APP_SEPARATOR = "/"; |
5.1.1 static&final案例1:
题干 |
* (1)定义一个成员变量pai,赋值为3.14. 要求用static和final来修饰该成员变量pai,即把pai变为常量。 * (2)定义一个成员方法 zhouChang(int r), 用来求圆的周长并把周长返回。提示:圆的周长= 2 * pai * r. * 要求:把该方法用static修饰,即定义为静态方法。 * (3)定义一个成员方法mianJi(int r),用来求圆的面积并把面积返回。提示:圆的面积 = pai * r * r. * 要求:把该方法用static修饰,即定义为静态方法。 * 定义测试类。 定义圆的半径r为整数,键盘录入。 调用zhouChang方法和mianJi方法,测试,分别定义double类型的变量来接收方法的返回值。并打印出周长和面积的值 |
所属知识点 |
static、final |
题目类型 |
代码题 |
答案 |
public class Demo11_static { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入圆的半径:(要求为整数)"); //接收键盘录入的半径 int r = sc.nextInt(); //调用 求周长的方法 double zhch= Circle.zhouChang(r); System.out.println(zhch); //调用求面积的方法 double mj= Circle.mianJi(r); System.out.println(mj); } } class Circle{ //定义 pai private static final double pai = 3.14; //定义静态方法zhouChang public static double zhouChang(int r){ double zhch = 2 * pai * r; return zhch; } //定义静态方法mianJi public static double mianJi(int r){ double mj = pai * r * r; return mj; } } |