Java第七天
重写(Override)
定义:当子类继承父类时,子类的成员方法和父类的成员方法相同,但方法体不同,这种子类的成员方法将父类的成员方法覆盖的写法叫重写。
判断依据:访问限定修饰符、返回值类型、成员方法名、参数列表。
重写与重载的区别:
重写(override):在父子类的继承中有相同的方法,唯一不同的是方法体,一般是父类的成员方法满足不了之类的需求才会重写。
重载(overload):在同一个类中,有相同的成员方法名,但是参数列表的数据类型或个数不同,这样的两个成员方法就是重载,重载可以提高代码的可读性,节省类中的命名资源。
class Father{
String name = "李四";
public void print() {
System.out.println("父类方法被调用!");
}
}
class Son extends Father{
//这里就是重写
public void print() {
System.out.println(super.name + "重写方法成功!");
System.out.println("子类方法被调用!");
}
}
public class Test{
public static void main(String[] args) {
Son son = new Son();
son.print();
}
}
final关键字
对成员方法
被final关键字修饰的成员方法不能被重写。
语法:
访问限定修饰符 final 返回值类型 成员方法名 (参数列表){
方法体;
}
错误示范:
下方父类成员方法由于被final修饰了,
所以子类无法重写父类的成员方法,并且代码运行后会报错!
class Father{
String name = "李四";
//父类成员方法被final所修饰
public final void print() {
System.out.println("父类方法被调用!");
}
}
class Son extends Father{
//这个方法将不能被重写
public void print() {
System.out.println(super.name + "重写方法成功!");
System.out.println("子类方法被调用!");
}
}
public class Test{
public static void main(String[] args) {
Son son = new Son();
son.print();
}
}
对属性
被final修饰的成员变量,其值不可被修改,常被用来定义常量。
语法:
// static可省略不写 也可以不用赋值
访问限定修饰符 static final 数据类型 成员变量名 = 值;
public static final int PI;
public static final int PI = 3.14;
被final修饰的成员变量名一般采用大写,多个单词使用下划线分隔,例:XXX_YYY_ZZZ。这种常量多定义在接口中。
对类
被final修饰的类将不可被继承。
语法:
final class 类名{
成员变量;
成员方法;
}
抽象类(abstract)
对方法
定义:当多个具体的实体类存在着共同的成员方法,但有不同的表现,其中当子类在继承父类时,子类的成员方法具体实现不同,但是能确定子类都有这种成员方法,这种成员方法称为抽象方法。
如果一个类中存在一个抽象方法,那么这个类一定是抽象类,这个类必须要使用 abstract 来进行修饰。
抽象方法没有方法体。
语法:
//返回值类型可为void 参数列表可有可无
public abstract 返回值类型 成员方法名(参数列表);
public abstract void Example();
对类
抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
语法:
abstract class 类名{
成员变量;
成员方法;
}
注意:
①抽象类也可以继承抽象类,这样就可以不用实现父抽象类的抽象方法。
②抽象类中可以没有抽象方法,但有抽象方法的类一定是抽象类。
③抽象类不能直接被创建对象,需要被子类继承才能使用子类创建对象(创建子类对象)。
④继承抽象类的非抽象类中必须实现抽象类中的所有抽象方法。
⑤继承抽象类A的抽象类B可以不用实现抽象类A中的抽象方法,但抽象类B不能直接创建其对象。
⑥抽象类的抽象方法中不能与private、final、static共存 。
//定义一个抽象学生类
abstract class Student{
//学生有成员变量,姓名
String name;
//学生都有学习这个成员方法
public abstract void study();
}
class StudentA extends Student{
//非抽象学生A类继承了抽象学生类,所以要实现学习这个成员方法
@Override
public void study() {
System.out.println("学生"+ name +"在听课");
}
}
//非抽象学生B类继承了抽象学生类,所以要实现学习这个成员方法
class StudentB extends Student{
@Override
public void study() {
System.out.println("学生"+ name +"边听课,边记笔记");
}
}
public class Test{
public static void main(String[] args) {
StudentA studentA = new StudentA();
studentA.name = "A";
studentA.study();
StudentB studentB = new StudentB();
studentB.name = "B";
studentB.study();
}
}
输出结果:
学生A在听课
学生B边听课,边记笔记
上述代码中虽然学生A和学生B都是学生,也都有study这个成员方法,但学生A在学习时只是在听课记笔记,而学生B在学习时变听课变记笔记。这就是多个具体类存在共同成员方法,但有不同的表现。
接口(interface)
定义:如果一个抽象类中所有的方法都是抽象方法,那么可以把这个类定义定义成接口。
作用:
1.接口定义的是一种标准,可以使代分层开发、分模块开发。
2.使用接口可以降低代码耦合度,提高代码的可拓展性和可维护性。
3.接口改进了单继承的局限。
接口是对成员方法的抽象(不存在成员变量)。 类是对成员方法和成员属性的抽象。
接口中可以省略abstract,默认是抽象的。
接口不能直接被实例化,需要有类来实现接口。
接口定义语法:
interface 接口名{
抽象方法;
}
接口实现类定义语法:
class 类名 implements 接口名1,接口名2,...{
实现接口的方法;
}
注意:
①接口中的抽象方法不能和private、static、final共存。
②接口实现类必须实现接口中的所有方法。
③在接口中可以定义成员变量。访问方法:
1.通过接口的实现类的对象访问。
2.通过接口名访问(推荐)。
④接口中成员变量的值不可修改,并作为常量使用,默认使用public final static修饰。
⑤接口可以继承接口,支持多继承(jdk1.7特性)和多级继承。
通过接口名访问语法:
接口名.常量名;
接口多继承语法:
interface C extends A,B{
常量;
抽象方法;
}
接口多实现语法:
class C implements A,B{
常量;
实现抽象方法;
}
//定义接口A
interface A{
// 定义常量PI
public final static double PI = 3.14;
// 定义抽象方法print
public void print();
}
//定义接口B
interface B{
// 定义抽象方法print1
public void print1();
}
//定义接口D并多继承接口A、接口B
interface D extends A,B{
// 定义常量P,并使用“接口名.常量名”将常量PI的值赋给常量P
public final static double P = A.PI;
}
//定义接口实现类C,并多实现接口A、B、D
class C implements A,B,D{
public void print() {
System.out.println("接口A被实现类C已实现!"+P);
}
public void print1() {
System.out.println("接口A和接口B被实现类C已多实现!"+PI);
}
}
public class InterfaceTest {
public static void main(String[] args) {
C c = new C();
c.print();
c.print1();
}
}
输出结果:
接口A被实现类C已实现!3.14
接口A和接口B被实现类C已多实现!3.14
接口与抽象类的区别
| 接口 | 抽象类 |
|---|---|
| 接口中的所有方法都是抽象的 | 抽象类中的成员方法既可以是抽象的也可以不是抽象的 |
| 接口需要类来实现,然后创建实现类的对象 | 抽象类需要类来继承,然后创建子类的对象 |
| 接口既可以多实现、多级继承接口,也可以多继承接口 | 抽象类只能单继承和多级继承 |
接口中的成员变量为static final类型 | 抽象类中的成员变量与一般类中的成员变量没有区别 |
接口中的成员方法默认是抽象的,不需要使用abstract修饰 | 抽象类中的抽象方法需要使用abstract修饰 |
多态
定义:同一个成员方法具有多个不同表现形式或形态的能力。
继承多态
定义:我们通常使用抽象类来抽象要使用多态的方法。
特点:
1.必须要有继承关系,在抽象类中可以定义多态的抽象方法,通过自理来继承这个抽象类,然后在子类中可以复写抽象类中的抽象方法,以达到多态的效果。
2.多态子类的对象可以赋给父类的引用,但子类中特有的成员方法不能通过父类来调用。
使用instanceof可以判断多态的引用对象为什么类型(与if···else等配合使用),其结果为布尔类型。
父类名 对象名 = new 多态子类的对象名();
对象名 instanceof 多态子类的对象名
class Student{
String name;
//注意这里不是抽象方法
public void study() {
}
}
通常使用抽象类来抽象要使用多态的方法(下方为多态常用代码形式)
/*
abstract class Student{
String name;
//注意这里是抽象方法
public abstract void study();
}
*/
class StudentA extends Student{
@Override
public void study() {
System.out.println("继承多态!学生"+name);
}
}
class StudentB extends Student{
@Override
public void study() {
System.out.println("继承多态!学生"+name);
}
}
public class Test{
public static void main(String[] args) {
//注意,这里不是通过 “类名 对象名 = new 类名();”进行创建对象
//而是使用 “父类名 对象名 = new 多态的子类名();”进行创建对象
Student studentA = new StudentA();
studentA.name = "A";
studentA.study();
Student studentB = new StudentB();
studentB.name = "B";
studentB.study();
}
}
输出结果:
继承多态!学生A
继承多态!学生B
class Student{
String name;
//注意这里不是抽象方法
public void study() {
}
}
通常使用抽象类来抽象要使用多态的方法(下方为多态常用代码形式)
/*
abstract class Student{
String name;
//注意这里是抽象方法
public abstract void study();
}
*/
class StudentA extends Student{
@Override
public void study() {
System.out.print("学生"+name);
}
}
class StudentB extends Student{
@Override
public void study() {
System.out.print("学生"+name);
}
}
//创建老师类
class Teacher{
public void checkHomework(Student s) {
System.out.print("老师在检查");
//接收时可以将学生的成员方法一起接收
s.study();
System.out.print("的作业"+"\n");
}
}
public class Test{
public static void main(String[] args) {
//注意,这里不是通过 “类名 对象名 = new 类名();”进行创建对象
//而是使用 “父类名 对象名 = new 多态的子类名();”进行创建对象
Student studentA = new StudentA();
studentA.name = "A";
studentA.study();
Student studentB = new StudentB();
studentB.name = "B";
studentB.study();
System.out.println();
Teacher teacher = new Teacher();
//将学生对象作为参数传给checkHomework成员方法
teacher.checkHomework(studentA);
teacher.checkHomework(studentB);
}
}
输出结果:
学生A学生B
老师在检查学生A的作业
老师在检查学生B的作业
接口的多态
接口的多态基本和类的继承的多态一致。不同的是类的继承使用的是继承关系实现多态,接口采用实现的方式实现多态。
可以使用构造器进行传值。
语法:
接口名 对象名 = new 实现类名();
//定义接口A
interface A{
// 定义常量PI
public final static double PI = 3.14;
// 定义抽象方法print
public void print();
}
//定义接口实现类B,并实现接口A
class B implements A{
public void print() {
System.out.println("接口A被实现类B已实现!");
}
}
//定义接口实现类C,并实现接口A
class C implements A{
String name;
// 定义C类含参构造器
public C(String name){
this.name = name;
}
public void print() {
System.out.println("接口A被实现类C已实现!"+"\t"+name);
}
}
public class InterfaceTest {
public static void main(String[] args) {
// 接口名 对象名 = new 实现类名();
A b = new B();
b.print();
A a = new C("构造器传值测试!");
a.print();
}
}
输出结果:
接口A被实现类B已实现!
接口A被实现类C已实现! 构造器传值测试!
模板模式
步骤:
①抽象模板(定义一个抽象类)
②必须要实现的一个业务方法(定义一个抽象方法)
③定义一个可重写也可不重写的方法
④定义一个不可被重写的方法(使用final修饰)
⑤定义一个模板方法,供其他类使用(按顺序调用成员方法)
⑥具体模板(使用子类继承抽象类)
⑦实现具体的业务逻辑(实现抽象类中的抽象方法)
⑧可重写也可不重写③的成员方法
⑨在测试类中创建具体模板的对象
⑩获得具体模板中的数据(返回值)
本文深入解析Java中的重写(Override)概念,包括如何重写方法、属性及类,探讨final关键字的作用,以及抽象类和接口的使用。同时,文章详细阐述了多态的概念,包括继承多态和接口的多态,以及模板模式的设计原则。

被折叠的 条评论
为什么被折叠?



