一,接口的定义:
格式:修饰符 interface 接口名称 {接口内容}
- 解释:
- interface:就是关键字 表示就是接口
- 接口名称:自己命名。遵循见名知意、大驼峰格式
- 内容:
- 属性:接口的属性只能是常量或者被final修饰的变量
- 注意:
- 属性是默认被 public static final修饰的
- 声明属性的时候必须给他赋值
- 构造方法:接口没有构造方法,所以接口不可以创建对象
- 行为:jdk1.8之前接口只有抽象方法【抽象方法就是行为声明的表现形式】
代码示例
public interface InterfaceA {
//接口内容
//属性
/*public static final*/ int a = 10; //默认被 public static final 修饰
public static final int b = 30 ;
//行为
public abstract void run();
}
- 接口和抽象类的区别:
- 抽象类是对子类的共性行为声明的提取【子类要求是同一系列的类局限性小】
- 接口是对不同系列的事物的共性行为声明的提取【就没有局限性】
- 抽象类是被类继承的,接口只能被类实现
二,接口的实现
- 概述:接口是行为的集合,行为只是一种声明没有具体的实现,行为要想有效果必须被调用,接口自己没有对象,只有通过类对象来调用,他必须要类来实现它。
- 分为两种:单实现和多实现
- 单实现:类一次只实现一个接口
- 类单实现接口规则:使用关键字 implements 连接类和接口,就产生实现的关系必须重写接口中所有的抽象方法。
- 实现格式:类A implements 接口B {重写方法}
- 关系:类是干儿子接口是干爹
- 第一种:是一个普通类实现一个接口;类肯定全部重写了抽象方法
- 第二种:是抽象类实现一个接口;抽象类可以重写接口中的方法,也可以不重写,但是抽象类的子类必须要重写没有被重写过的所有抽象方法
代码示例
//定义接口
public interface Interface01 {
//接口内容
//属性
int a = 10; // 默认被public static final 修饰
public static final int b = 30;
//行为(抽象方法)
public abstract void run();
public abstract void eat();
public abstract void show();
public abstract void print();
}
第一种:普通类
public class ClassA implements InterfaceA{
//使用快捷键重写接口所有的方法
@Override
public void run() {
System.out.println("类A:一天跑500圈");
}
@Override
public void eat() {
System.out.println("类A:一天吃8个馒头");
}
@Override
public void show() {
System.out.println("类A:每天都跳肚皮舞");
}
@Override
public void print() {
System.out.println("类A:每天画画");
}
}
第二种:抽象类
public abstract class ClassB implements InterfaceA{
//可以不重写接口中的方法
@Override
public void run() {
System.out.println("类B:每天跑步");
}
}
//对于抽象类需要创建两外一个类去继承抽象类
public class ClassC extends ClassB{
@Override
public void eat() {
System.out.println("类c:每天吃苹果");
}
@Override
public void show() {
System.out.println("类c:每天跳操");
}
@Override
public void print() {
System.out.println("类c:每天写文章");
}
}
//定义测试类,接口单实现
public class Interface01_Test {
public static void main(String[] args) {
System.out.println(Interface01.a); //接口名可以直接访问说明 a 是静态资源
ClassA classA=new ClassA();
classA.run();
classA.eat();
classA.show();
classA.print();
ClassC classC=new ClassC();
classC.run();
classC.eat();
classC.show();
classC.print();
}
}
-
多实现
- 概述:一个类同时实现多个不同的接口
- 格式:类 A implements 接口A,接口B,接口C,...{类的内容【重写接口中的资源】}
- 原则:
3.1、所有接口中的所有不同名的抽象方法必须重写
3.2、抽象类多实现接口的时候:抽象类可以重写接口中的方法;也可以不重写,最终他的子类必须要去实现内有实现的抽象方法
3.3、多接口 中有同名的抽象方法只需重写一次
代码示例
//定义接口Num1
public interface Num1 {
//定义抽象方法
public abstract void show();
//抽象方法 【接口中抽象方法前面的 public abstract 是默认的可以省略】
void run();
}
//定义接口Num2
public interface Num2 {
void print();
}
//定义接口Num3
public interface Num3 {
//和接口num1中的show同名
void show ();
void eat();
}
//定义类链接多个接口Num1,Num2,Num3
public class ClassNum implements Num1,Num2,Num3{
//按快捷键重写所有接口里面的所有方法
@Override
public void eat() {
System.out.println("今天吃西瓜");
}
@Override
public void print() {
System.out.println("写论文");
}
//show 是 Num1和Num3接口重名方法 只需要重写一次
@Override
public void show() {
System.out.println("展示作品");
}
@Override
public void run() {
System.out.println("跑步");
}
}
//定义测试类
public class ClassNum_Test {
public static void main(String[] args) {
//创建接口的子类对象
ClassNum classNum = new ClassNum();
classNum.eat();
classNum.run();
classNum.show();
classNum.print();
}
}
三,继承和实现优先级
- 一个类既要继承另个类,同时又要实现另一个接口,谁在前?
- 先继承后实现【亲疏关系 java的一种规定】
- 当一个类,既继承一个父类,又实现若干个接口时,父类中的成员方法与接口中的抽象方法重名时,如何执行?
- 子类就不需要重写接口中的抽象方法了,执行的时候是执行的父类的方法,如果重写了意味也是重写父类的方法【对父类方法的扩展】
代码示例:
//定义接口:
public interface InterfaceA {
//接口内容
//属性
/*public static final*/ int a = 10;//默认被public static final 修饰
public static final int b = 30 ;
//行为
public abstract void run();
public abstract void eat();
public abstract void show();
public abstract void print();
}
//定义父类,链接多个接口
public abstract class ClassNum2 implements Num1,Num2,Num3{
@Override
public void show() {
System.out.println("我想跳舞");
}
}
//定义子类去继承父类链接接口
public class Demo extends ClassNum2 implements InterfaceA {
//子类中不需要重写父类的show方法
@Override
public void run() {
System.out.println("我想跑步");
}
@Override
public void eat() {
System.out.println("我想吃苹果");
}
@Override
public void print() {
System.out.println("我想写文章");
}
}
//定义测试类:
public class Demo_Test {
public static void main(String[] args) {
Demo demo = new Demo();
demo.show(); //我想跳舞
demo.run(); //我想跑步
demo.eat(); //我想吃苹果
demo.print(); //我想写文章
}
}
四,接口的特点
1、接口的属性是常量或者被final修饰的变量【静态的资源,使用接口名访问】
2、接口没有构造方法的,不能创建对象
3、jdk1.8之前接口中行为只有抽象方法,
4、接口要求子类来重写他的所有的抽象方法
5、接口只能被类多实现不能被类多层实现
五,类、接口之间的关系
- 类和类:只能出现继承关系【java中支持的单继承、多层继承】
- 类和接口:只能实现关系【java中支持单实现、多实现】
- 实现关系值存在于类和接口之间,只存在单实现和多实现;没有多层实现
- 接口和接口:只能有继承关系【java支持单继承、多继承、多层继承】
- 注意:一个接口继承了其他接口,意味着这个接口拥有所有继承的接口中的抽象法;他的实现类必须重写所有的抽象方法
六,多态
- 多态:一个事物的多种状态【一个对象可以有多种数据类型】
- 举例:一个人在学校是学生,回到家在父母面前是孩子,在女朋友面前是男票,在妻子面前是丈夫,在儿子面前是父亲等等。
- 多态的前提:必须存在继承关系【继承和实现】
- 两个类必须具有继承关系
- 子类必须重写父类方啊
- 父类对象引用指向子类对象空间
- 多态的特点:
- 【一个对象可以有多种数据类型,一个数据类型可以对应不类型的子类对象】
- 父类的引用指向子类对象【父类的类型变量中存放的是子类对象的地址值】
- 多态的格式 :父类类型 变量名 = new 子类类型(参数列表)
- 代码体现中:就是子类对象充当父类类型【儿子冒充父亲】
代码示例
//定义测试类
public class Test {
public static void main(String[] args) {
Animal animal = new Animal();
//正常创建猫类对象
Cat cat = new Cat();//猫对象类型是 Cat类型【猫类型】
//使用多态创建的猫类对象
//父类类型 变量名 = new 子类类型(参数列表)
Animal animal1 = new Cat();//猫对象类型是 Animal类型【动物类型】
}
}
//定义Animal类,父类
public class Animal {
}
//定义Cat类,子类继承父类
public class Cat extends Animal{
}
-
多态中成员变量的访问原则
- 原则:编译看左边,运行看左边【左右是以=号为基准】
- 解释:
2.1 编译的时候先到左边的父类中去找这个变量,存在就编译通过,不存在编译报错
2.2 运行的时候只会使用父类中的资源,使用的不是父类中的资源就会报错
代码示例
//定义父类
public class Animal {
int a = 10;
int b = 20;
}
//定义子类继承父类
public class Cat extends Animal{
int c = 30;
int d = 50;
}
//定义测试类
public class Test {
public static void main(String[] args) {
Animal animal = new Animal();
//正常创建猫类对象
Cat cat = new Cat();//猫对象类型是 Cat类型【猫类型】
//使用多态创建的猫类对象
Animal animal1 = new Cat();//Cat 对象类型是 Animal类型【动物类型】
System.out.println(animal1.a);// 10 编译这行代码的时候 首先到Animal中看有没有a属性
System.out.println(animal1.b);//20
//System.out.println(animal1.c);//访问不了 现在猫对象冒充的父类Animal只能使用父类的资源
//System.out.println(animal1.c);//编译这行代码的时候 首先到Animal中看有没有c属性 没有报错
//System.out.println(animal1.d);//编译这行代码的时候 首先到Animal中看有没有d属性 没有报错
}
}
-
多态中成员方法的访问原则
- 原则:编译的时候看左边,运行的时候看右边
- 解释:
2.1 编译代码的时候看左边父类中是否有这个方法,有编译通过,没有编译报错
2.2 运行的时候首先到子类中看是否有这个方法有执行子类的方法,没有去执行父类的方法
【为什么不会报错,编译的时候已经判断了父类肯定有这个方法,子类如果也有就是方法重写方法的归属还是父类的】
代码示例
//定义测试类
public class Test {
public static void main(String[] args) {
Animal animal = new Animal();
//正常创建猫类对象
Cat cat = new Cat();//猫对象类型是 Cat类型【猫类型】
//使用多态创建的猫类对象
Animal animal1 = new Cat();//猫对象类型是 Animal类型【动物类型】
System.out.println(animal1.a);// 10 编译这行代码的时候 首先到Animal中看有没有a属性
System.out.println(animal1.b);//20
//System.out.println(animal1.c);//访问不了 现在猫对象冒充的父类Animal只能使用父类的资源
//System.out.println(animal1.c);//编译这行代码的时候 首先到Animal中看有没有c属性 没有报错
//System.out.println(animal1.d);//编译这行代码的时候 首先到Animal中看有没有d属性 没有报错
//方法
animal1.show();//输出结果:我是子类的show,编译这行代码的时候先到Animal类中看有么有这个方法 有通过 没有报错
animal1.print();//输出结果:456,编译这行代码的时候先到Animal类中看有么有这个方法 有通过 没有报错
//animal1.run();//编译这行代码的时候先到Animal类中看有么有这个方法 没有这个方法,所以报错
}
}
//定义子类继承父类
public class Cat extends Animal{
int c = 30;
int a = 50;
public void run() {
System.out.println("跑得快");
}
public void show() { // show 方法
System.out.println("我是子类的show");
}
}
//定义父类
public class Animal {
int a = 10;
int b = 20;
public void show() { // show 方法
System.out.println(123);
}
public void print() {
System.out.println(456);
}
}
七,引用数据类型的向上向下转型
- 向上转型:就是子类对象赋值给父类类型的变量【多态就是向上转型】
- 向下转型:父类类型的对象赋值给子类类型的变量【多态对象回归原有的类型】
需要使用(子类类型)进行强制转换
- 格式:子类类型 变量名 = (子类类型)父类类型的对象
- 注意事项:
- 向下转型的时候,
- 父类类型的对象肯定是一个多态对象 比如: Animal a = new Dog()。
- 要转的子类对象必须是多态对象之前的类型。所以转换之前需要进行判断
java中提供了一个判断的词:instanceof
代码
//定义子类继承父类
public class Cat extends Animal{
int c = 30;
int a = 50;
public void run() {
System.out.println("跑得快");
}
public void show() {
System.out.println("我是子类的show");
}
}
//定义父类
public class Animal {
int a = 10;
int b = 20;
public void show() {
System.out.println(123);
}
public void print() {
System.out.println(456);
}
}
//向上向下向上转型的代码:
Animal animal1= new Cat();//多态向上转型
animal1.show();
子类类型 变量名 = (子类类型)父类类型的对象
Cat cat2 = (Cat)animal1;//向下转型
cat2.run(); //返回到子类自己本身
Animal animal2 = cat2;//向上转型
//animal2.run();
animal1.show();
代码示例2
//定义测试类
public class Animal_Test {
public static void main(String[] args) {
//向上转型
Animal animal1 = new Cat();
Animal animal2 = new Dog();
//向下转型
//Dog dog = (Dog)animal1;//运行报错
// animal1是 cat对象充当的父类,回归原来类型的时候得回归到猫 回归成狗 成立吗?
//animal1要向下转型必须转为 Cat
System.out.println(animal1 instanceof Cat);//true
Cat cat= null;
if (animal1 instanceof Cat) {
cat = (Cat)animal1;
//cat 变量随着if语句执行完毕消失 if语句的外面无法使用 if语句外面想要使用把这个变量定义到外面
}
Dog dog = null;
if (animal2 instanceof Dog) {
dog = (Dog)animal2;
}
//回归了自己的类型,就可以使用自己的资源也可以使用父类的资源
cat.run();
cat.show();
System.out.println(cat.c);
cat.print();
}
}
八,多态的好处
- 提高代码的扩展性和灵活性。
- 体现: 主要体现在方法参数的使用【使一个方法由单一性变得多功能起来】
代码示例
//定义父类:
public class Animal {
int a = 10;
int b = 20;
public void show() {
System.out.println(123);
}
public void print() {
System.out.println(456);
}
}
//定义子类:
package com.ujiye.demo01;
public class Cat extends Animal{
int c = 30;
int a = 50;
public void run() {
System.out.println("跑得快");
}
public void show() {
System.out.println("我是子类的show");
}
}
//定义子类:
public class Dog extends Animal{
int d = 40;
}
//定义测试类:
public class Demo02 {
public static void getCat(Cat cat) {
System.out.println("获取到一只猫");
cat.show();
}
//不使用多态一个方法使用的时候就只能传一种数据类型数据进来
public static void getDog(Dog dog) {
System.out.println("获取到一只猫");
dog.show();
}
//有了多态技术,就不需要每获取一个动物就写一个方法 只需要写一个方法就可以了
//方法使用的时候就可以传多种数据类型的数据进来,方法的使用功能就拓展了
public static void getAnimal(Animal animal) {
System.out.println("获取到一只猫");
animal.show();
}
//测试
public static void main(String[] args) {
Cat cat = new Cat();
getCat(cat);
Dog dog = new Dog();
getDog(dog);
Animal cat1 = new Cat();
getAnimal(cat1);
Animal dog1 = new Dog();
getAnimal(dog1);
}
}
九,综合案例
-
电脑USB案例
- 需求:定义笔记本类,具备开机,关机和使用USB设备的功能。具体是什么USB设备,笔记本并不关心,只要符合USB规格的设备都可以。鼠标和键盘要想能在电脑上使用,那么鼠标和键盘也必须遵守USB规范,不然鼠标和键盘的生产出来无法使用;
- 进行描述笔记本类,实现笔记本使用USB鼠标、USB键盘
- USB接口,包含开启功能、关闭功能
- 笔记本类,包含运行功能、关机功能、使用USB设备功能
- 鼠标类,要符合USB接口
- 键盘类,要符合USB接口
代码
定义笔记本类:
public class Computer {
public void open() {
System.out.println("笔记本开机了可以使用");
}
public void useUSB(USB usb) {
usb.openUSB();
usb.closeUSB();
}
public void close() {
System.out.println("笔记本关机了停止使用使用");
}
}
定义接口:
public interface USB {
void openUSB();
void closeUSB();
}
定义鼠标类连接USB接口
public class Mouse implements USB{
@Override
public void openUSB() {
System.out.println("鼠标开启了正在滴滴滴滴滴滴的工作");
}
@Override
public void closeUSB() {
System.out.println("鼠标停止工作了您可以拔出");
}
}
定义键盘类连接USB接口
public class Keyboard implements USB{
@Override
public void openUSB() {
System.out.println("键盘开始工作了,噼里啪啦的打字");
}
@Override
public void closeUSB() {
System.out.println("键盘累了,需要休息了,您放开他吧");
}
}
定义测试类:
public class Test {
public static void main(String[] args) {
//使用笔记本工作
Computer computer = new Computer();
//开机工作
computer.open();
//需要一个USB对象 USB是接口 要他的实现类对象 方法要的是USB 类型 使用多态
//使用鼠标工作
USB mouse = new Mouse();
computer.useUSB(mouse);
//使用键盘工作
USB keyboard = new Keyboard();
computer.useUSB(keyboard);
//关机
computer.close();
}
}