1、继承
面对对象的三大特征:封装性、继承性、 多态性
继承是多态的前提,如果没有继承,就没有多态
在继承的关系中,“子类就是父类”。也就是说,子类可以被当做父类看待。
例如:父类是员工,子类是讲师,那么“讲师就是一个员工”。关系:is-a。
定义父类的格式:(一个普通的类定义)
public class 父类名称{
//…
}
定义子类的格式:
public class 子类名称 extends 父类名称{
//…
}
代码示例:
/
//员工类 public class Employee { public void method(){ System.out.println("方法执行"); } }
//讲师类(讲师是员工) public class Teacher extends Employee { }
public class Demo01Extends { public static void main(String[] args) { //创建一个子类对象 Teacher teacher = new Teacher(); //Teacher类当中虽然什么都没写,但是会继承来自父类的method方法 teacher.method(); } }
/
1.1继承中成员变量的访问特点
在父子类的继承关系当中,如果成员变量重名,则创建子类对象时,访问有两种方式:
1.直接通过子类对象访问成员变量:
等号左边是谁,就优先用谁,没有则向上找
2.简接通过成员方法访问成文变量:
该方法属于谁,就优先用谁,没有则向上找
1.2 区分子类方法中重名的三种
- 局部变量: 直接写
- 本类的成员变量: this.成员变量名
- 父类的成员变量: super.成员变量名
代码示例:
//父类 public class Fu { int num = 10; } 1
//子类 public class Zi extends Fu { int num = 20; public void method(){ int num = 30; System.out.println(num);// 30局部变量 System.out.println(this.num);//20 本类的成员变量 System.out.println(super.num);//10 父类的成员变量 } }
public class Demo02ExtendsField { public static void main(String[] args) { Zi zi = new Zi(); zi.method(); } }
1.3继承中构造方法的访问特点
- 子类构造方法当中有一个默认隐含的“super()”调用,所以一定是先调用父类的构造,后执行子类的构造
- 子类构造可以通过super关键字来调用父类重载构造。
- super的父类调用,必须是子类构造方法的第一个语句,不能一个子类构造调用多次super构造
- 子类必须调用父类构造方法,不写则赠送super():写了则用写的指定super调用,super只能有一个,还必须是第一个。
1.4 super关键字的三种用法
- 在子类的成员方法中,访问父类的成员变量。
- 在子类的成员方法中,访问父类的成员方法。
- 在子类的构造方法中,访问父类的构造方法。
1.5 this关键字的三种用法
- 在本类的成员方法中,访问本类的成员变量。
- 在本类的成员方法中,访问本来的另一个成员方法。
- 在本类的构造方法中,访问本类的另一个构造方法。
注意:super和this关键字不能同时使用
super和this关键字在内存中的图解如下图
1.6 java继承的三个特点
java语言是单继承的。一个类的直接父类只有一个。
java语言可以多级继承。
一个子类的直接父类是唯一的,但是一个父类可以拥有多个子类。
2、抽象类
2.1 抽象类的概念
抽象方法:就是加上abstract关键字,然后去掉大括号,直接分号结束。
抽象类:抽象方法所在的类,必须是抽象类才行,在class之前写上abstract即可。
2.2抽象方法是抽象类的使用
不能直接创建new抽象类对象。
必须用一个子类来继承抽象父类.
子类必须覆盖重写抽象父类当中所有的抽象方法。
创建子类对象使用。
注:覆盖重写(实现):子类去掉抽象方法的abstract关键字,然后补上方法体大括号
代码示例:
//
public class DemoMain { public static void main(String[] args) { cat cat = new cat(); cat.eat(); } }
//动物父类 public abstract class Animal { public abstract void eat(); }
/
/
//猫子类 public class cat extends Animal { @Override public void eat(){ System.out.println("猫吃鱼"); } }
2.3抽象方法和抽象类的注意事项
抽象类不能创建对象,如果创建,编译无法通过而报错,只能创建其抽象子类的对象
抽象类中,可以有构造方法,是提供子类创建对象时,初始化父类成员使用。
抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错,除非子类也是抽象类。
3、接口
3.1 接口的概念
接口,是Java语言中一种引用类型,是方法的集合,如果说类的内部封装了成员变量、构造方法和成员方法,那么
接口的内部主要就是封装了方法,包含抽象方法(JDK 7及以前),默认方法和静态方法(JDK 8),私有方法
(JDK 9)。
接口的定义,它与定义类方式相似,但是使用 interface 关键字。它也会被编译成.class文件,但一定要明确它并
不是类,而是另外一种引用数据类型。
3.2 定义格式:
public interface 接口名称 {
// 抽象方法:使用 abstract 关键字修饰,可以省略,没有方法体。该方法供子类实现使用。
// 默认方法:使用 default 修饰,不可省略,供子类调用或者子类重写。
// 静态方法: 使用 static 修饰,供接口直接调用。
// 私有方法:使用 private 修饰,供接口中的默认方法或者静态方法调用。
}
注意事项:
1、接口当中的抽象方法,修饰必须是两个固定的关键字:public abstract
2、 这两个关键字修饰符,可以选择性省略。
3.3 接口的使用步骤
接口不能直接使用,必须有一个“实现类”来“实现”该接口。
接口的实现类必须覆盖重写(实现)接口中所有抽象方法。
实现:去掉abstract关键字,加上方法体大括号。
创建实现类对象,进行使用。
注意事项:如果实现类并没有覆盖重写所有抽象方法,那么这个实现类自己就必须是抽象类。
3.3.1抽象方法
使用 abstract 关键字修饰,可以省略,没有方法体。该方法供子类实现使用。接口中,有多个抽象方法时,实现类必须重写所有抽象方法。如果抽象方法有重名的,只需要重写一次。
代码示例:
//定义接口 public interface MyInterfaceAbstract { //这是一个抽象方法 public abstract void methodAbs1(); //这也是一个抽象方法 abstract void methodAbs2(); //这也是抽象方法 public void methodAbs3(); //这也是抽象方法 void methodAbs4(); }
//定义实现类 public class MyInterfaceAbstractImpl implements MyInterfaceAbstract{ @Override public void methodAbs1() { System.out.println("这是第一个方法"); } @Override public void methodAbs2() { System.out.println("这是第二个方法"); } @Override public void methodAbs3() { System.out.println("这是第三个方法"); } @Override public void methodAbs4() { System.out.println("这是第四个方法"); } }
/
public class Demo01Interface { public static void main(String[] args) { MyInterfaceAbstractImpl impl = new MyInterfaceAbstractImpl(); impl.methodAbs1(); impl.methodAbs2(); } }
3.3.2默认方法
使用 default 修饰,不可省略,供子类调用或者子类重写。接口中,有多个默认方法时,实现类都可继承使用。如果默认方法有重名的,必须重写一次。
代码示例:
/
//定义接口 public interface MyInterfaceDefault { //这是一个抽象方法 public abstract void methodAbs(); //新添加一个抽象方法 // public abstract void methodAbs2(); //新添加的方法,改成默认方法 public default void methodDefault(){ System.out.println("这是新添加的默认方法"); } }
//定义实现类 public class MyInterfaceDefaultA implements MyInterfaceDefault { @Override public void methodAbs() { System.out.println("实现抽象方法,AAA"); } }
public class MyInterface { public static void main(String[] args) { //创建实现类对象 MyInterfaceDefaultA a = new MyInterfaceDefaultA(); //调用抽象方法,实现运行的是右侧实现类 a.methodAbs(); //调用默认方法,如果实现类当中没有,会向上找接口的 a.methodDefault(); } }
3.3.3静态方法
使用 static 修饰,供接口直接调用。接口中,存在同名的静态方法并不会冲突,原因是只能通过各自接口名访问静态方法。
注意事项:不能通过接口实现类的对象来调用接口当中的静态方法。
正确用法:通过接口名称,直接调用其中的静态方法
格式:
接口名称.静态方法名称(参数);
3.3.4私有方法
使用 private 修饰,供接口中的默认方法或者静态方法调用。
3.4 接口中的常量定义与使用
- 接口中,无法定义成员变量,但是可以定义常量,其值不可以改变,默认使用public static final修饰。
- 接口中,没有构造方法,不能创建对象。
- 接口中,没有静态代码块
格式:
public static final 数据类型 常量名称 = 数据值;
注意:
- 一旦使用final关键字进行修饰,说明不可改变。
- 接口中的常量,必须进行赋值,不能不赋值。
- 接口中常量的名称,使用完全大写的字母,用下划线进行分隔。(推荐)