Lecture:波哥
Java
是第一大编程语言和开发平台。它有助于企业降低成本、缩短开发周期、推动创新以及改善应用服务。如今全球有数百万开发人员运行着超过 51 亿个 Java
虚拟机,Java
仍是企业和开发人员的首选开发平台。
生活中的接口的特点:
接口是抽象方法和常量的集合,JDK1.8之后接口中可以包含静态方法和默认方法。
语法规则
关键字 接口名{
常量;
抽象方法;
}
interface 接口名{
....
}
案例代码:
package com.bobo.oop01;
public class OOPDemo03 {
/**
* 接口
* @param args
*/
public static void main(String[] args) {
// 接口是不能被实例化的
// InterfaceDemo01 d = new InterfaceDemo01() ;
// InterfaceDemo01.NAME = "aaa";
}
}
// 第一个接口案例 常量和抽象方法的集合
interface InterfaceDemo01{
// 静态常量 可以省略 static和final关键字
public static final String NAME= "张三";
// 抽象方法 可以省略abstract关键字
public void eat();
/**
* 在JDK1.8之后可以在接口中声明静态方法
*/
public static void sleep(){
System.out.println("sleep ... ");
}
/**
* 在JDK1.8之后可以在接口中声明 default方法
*/
default void run(){
System.out.println("run .... ");
}
}
常量:默认接口中所有的成员的变量都是省略 public static final 这几个关键字的,一般接口的成员变量都是大写的
抽象方法:默认接口中的所有成员方法都是省略 public abstract的
在这里我们建议大家在写的时候都加上
JDK1.8之后增加的 静态方法和default方法也要注意
接口中存在抽象方法,那就表明接口本身也是一个抽象类,所以肯定不能被实例化,那么此时我们只能通过接口的实现类来实现,要实现接口的实现类我们要通过 Implements
关键字来实现
/**
* 创建的Person类实现 InterfaceDemo01接口
*
* @author dpb
*
*/
class Person implements InterfaceDemo01{
@Override
public void eat() {
System.out.println("Person ... eat");
}
}
接口实现类的特点:
a. 如果一个类实现了接口,那么该类就必须实现接口中定义的所有的抽象方法
b. 如果一个接口不想实现接口的方法,那么子类必须定义为一个接口或者抽象类
/**
* 子类不想实现父接口中定义的抽象方法那么可以定义本身为一个接口,
* 然后通过 extends 继承父接口的所有的抽象方法和常量
* @author dpb
*
*/
interface Student extends InterfaceDemo01{
}
abstract class User implements InterfaceDemo01{
}
相比较继承
的单继承而言,接口在这方面就显得很灵活,支持多实现
package com.bobo.oop02;
public interface Person {
public void sleep();
}
package com.bobo.oop02;
public interface Police extends Person {
public void zhuxiaotou();
}
package com.bobo.oop02;
public interface Student extends Person{
public void study();
}
package com.bobo.oop02;
public class User implements Student,Police{
@Override
public void sleep() {
// TODO Auto-generated method stub
}
@Override
public void zhuxiaotou() {
// TODO Auto-generated method stub
}
@Override
public void study() {
// TODO Auto-generated method stub
}
}
此处要额外注意,在Java中接口与接口是可以多继承的!!!
接口是一种规范,一种标准,同时接口也是灵活的。
类和类:单继承,不可以实现
类和接口:单继承,多实现
接口和接口:多继承,不可以多现实
当我们设计一个非常复杂而又无法实现的类的时候可以使用继承
当我们重新开始编写一些简单的功能或者指定一些标准的时候使用接口
开发中一般采用面向接口编程,抽象类是模板,接口是规范
比较点 | 抽象类 | 接口 |
---|---|---|
定义 | 用abstract关键字来修饰的类 | interface关键字来修饰 |
组成 | 抽象方法,普通方法,构造方法、成员变量,常量 | 抽象方法,静态常量,JDK1.8注意 |
使用 | 子类继承(extends) | 实现类实现(implements) |
关系 | 抽象类可以实现接口 | 接口是不能继承抽象类的 |
对象 | 都是通过对象的多态类实现的 | 都是通过对象的多态类实现的 |
局限 | 不能多继承,不能实例化 | 可以多继承,不能实例化 |
选择 | 建议选择接口,避免单继承 | 建议选择接口,避免单继承 |
实际 | 模板 | 标准 |
要求如下: (1) 所有的可以拨号的设备都应该有拨号功能 (Dailup) (2) 所有的播放设备都可以有播放功能(Play)。 (3) 所有的照相设备都有拍照功能(takePhoto)。 (4) 定义一个电话类 Telephone,有拨号功能。 (5) 定义一个Dvd类有播放功能。 (6) 定义一个照相机类 Camera, 有照相功能。 (7) 定义一个手机类 Mobile, 有拨号,拍照,播放功能。 (8) 定义一个人类 Person, 有如下方法: <1> 使用拨号设备 use (拨号设备) <2> 使用拍照设备 use(拍照设备) <3> 使用播放设备 use(播放设备) <4> 使用拨号 播放 拍照设备 use(拨号播放拍照设备) (9) 编写测试类Test 分别创建人,电话,Dvd,照相机,手机对象,让人使用这些对象
案例代码
public interface IDailup {
/**
* 拨号
*/
void dailup();
}
public interface IPlay {
/**
* 播放
*/
void play();
}
public interface ITakePhone {
/**
* 拍照的功能
*/
void takePhone();
}
public interface IMobile extends IDailup,IPlay,ITakePhone {
}
// 定义一个电话类 Telephone,有拨号功能。
public class Telephone implements IDailup{
@Override
public void dailup() {
System.out.println("电话拨号...");
}
}
// 定义一个Dvd类有播放功能。
public class Dvd implements IPlay{
@Override
public void play() {
System.out.println("DVD播放功能");
}
}
// 定义一个照相机类 Camera, 有照相功能。
public class Camera implements ITakePhone{
@Override
public void takePhone() {
// TODO Auto-generated method stub
System.out.println("照相机拍照...");
}
}
// 定义一个手机类 Mobile, 有拨号,拍照,播放功能。
public class Mobile implements IMobile{
@Override
public void dailup() {
System.out.println("手机拨号");
}
@Override
public void play() {
// TODO Auto-generated method stub
System.out.println("手机播放");
}
@Override
public void takePhone() {
// TODO Auto-generated method stub
System.out.println("手机照相...");
}
}
public interface IPerson {
/**
* <1> 使用拨号设备 use (拨号设备)
*/
void use(IDailup dailup);
/**
* <2> 使用拍照设备 use(拍照设备)
* @param play
*/
void use(IPlay play);
/**
* <3> 使用播放设备 use(播放设备)
* @param takePhone
*/
void use(ITakePhone takePhone);
/**
* <4> 使用拨号 播放 拍照设备 use(拨号播放拍照设备)
* @param mobile
*/
void use(IMobile mobile);
}
public class Person implements IPerson {
@Override
public void use(IDailup dailup) {
dailup.dailup();
}
@Override
public void use(IPlay play) {
play.play();
}
@Override
public void use(ITakePhone takePhone) {
takePhone.takePhone();
}
@Override
public void use(IMobile mobile) {
mobile.dailup();
mobile.play();
mobile.takePhone();
}
}
public class OOPDemo01 {
/**
* 要求如下:
(1) 所有的可以拨号的设备都应该有拨号功能 (Dailup)
(2) 所有的播放设备都可以有播放功能(Play)。
(3) 所有的照相设备都有拍照功能(takePhoto)。
(4) 定义一个电话类 Telephone,有拨号功能。
(5) 定义一个Dvd类有播放功能。
(6) 定义一个照相机类 Camera, 有照相功能。
(7) 定义一个手机类 Mobile, 有拨号,拍照,播放功能。
(8) 定义一个人类 Person, 有如下方法:
<1> 使用拨号设备 use (拨号设备)
<2> 使用拍照设备 use(拍照设备)
<3> 使用播放设备 use(播放设备)
<4> 使用拨号 播放 拍照设备 use(拨号播放拍照设备)
(9) 编写测试类Test 分别创建人,电话,Dvd,照相机,手机对象,让人使用这些对象
* @param args
*/
public static void main(String[] args) {
IPerson person = new Person();
// 电话
IDailup telePhone = new Telephone();
// Dvd
IPlay play = new Dvd();
// 照相机
ITakePhone takePhone = new Camera();
// 手机对象
IMobile mobile = new Mobile();
person.use(telePhone);
person.use(play);
person.use(telePhone);
System.out.println("----------");
person.use(mobile);
}
}
什么是多态:父类的引用指向了子类的实例
多态的实现方法:
继承多态:当这个作为参数的父类是普通类或者抽象类时
接口多态:当这个作为参数的父类是一个接口时,构成接口多态
基本数据类型作为形参,就是我们讲的 值传递
这块没什么区别,也不涉及到多态
普通类
当一个形参希望我们传递的是一个普通类时,我们实际传递的是该类的对象/匿名对象
package com.bobo.oop04;
public class OOPDemo01 {
public static void main(String[] args) {
Student stu = new Student();
Person p = new Person();
p.run(stu);
System.out.println("*********");
p.run(new Student());// 将匿名对象当做实参传递
}
}
class Student{
public void study(){
System.out.println("好好学习,天天向上....");
}
}
class Person{
public void run(Student stu){
stu.study();
System.out.println("person ... run");
}
}
抽象类
当一个形参希望我们传入的是一个抽象类时,我们实际上传入的是该类的子类对象/子类的匿名对象
package com.bobo.oop05;
public class OOPDemo01 {
public static void main(String[] args) {
// 多态的体现
AbsStudent stu = new Student();
Person p = new Person();
p.run(stu);
System.out.println("*****1****");
p.run(new Student());// 将匿名对象当做实参传递
System.out.println("*****2****");
AbsStudent stu2 = new AbsStudent(){
public void study() {
// TODO Auto-generated method stub
System.out.println("好好学习,天天向上....run");
}
};
// 抽象类不能被实例化的原因是因为有没有被实现的抽象方法
// 那么既然是这样的话。那么我们就来实现抽象类中的抽象方法即可
// AbsStudent1 s1 = new AbsStudent1(){};
p.run(stu2);
p.run(new AbsStudent(){
public void study() {
// TODO Auto-generated method stub
System.out.println("好好学习,天天向上....run 666");
}
});
}
}
/**
* 定义了一个抽象类
* @author dpb
*
*/
abstract class AbsStudent{
public abstract void study();
}
abstract class AbsStudent1{
}
class Student extends AbsStudent{
@Override
public void study() {
System.out.println("好好学习,天天向上....");
}
}
class Person{
/**
* 形参要求传递进来一个 抽象类型
*
* AbsStudent stu = new Student();
* @param stu
*/
public void run(AbsStudent stu){
stu.study();
System.out.println("person ... run");
}
}
接口
当一个形参希望我们传入的是一个接口时,我们实际上传入的是该接口的实现类对象/实现类匿名对象
package com.bobo.oop06;
public class OOPDemo01 {
public static void main(String[] args) {
IStudent stu = new Student();
Person p = new Person();
p.run(stu);
System.out.println("*********");
p.run(new Student());// 将匿名对象当做实参传递
IStudent stu2 = new IStudent(){
@Override
public void study() {
// TODO Auto-generated method stub
System.out.println("好好学习,天天向上....接口");
}
};
p.run(stu2);
p.run(new IStudent(){
@Override
public void study() {
// TODO Auto-generated method stub
System.out.println("好好学习,天天向上....接口1");
}
});
}
}
class Student implements IStudent{
public void study(){
System.out.println("好好学习,天天向上....");
}
}
interface IStudent{
void study();
}
class Person{
public void run(IStudent stu){
stu.study();
System.out.println("person ... run");
}
}
基本数据类型作为返回值,就是我们讲的 值传递
这块没什么区别,也不涉及到多态
普通类
当一个方法的返回值是一个普通类,实际返回的就是该类的对象,我们可以使用该类的对象类接收
package com.bobo.oop07;
public class OOPDemo01 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Student s = new Student();
Person p1 = s.study();
Person p2 = s.eat();
System.out.println(p1);
System.out.println(p2);
}
}
class Person{
}
class Student{
public Person study(){
return new Person();
}
public Person eat(){
Person p = new Person();
return p;
}
}
抽象类
当一个方法的返回值是一个抽象类时,实际返回的是该抽象类的子类对象,我们可以使用该抽象类接收。如果用该类的子类来接收那么就要考虑类型的强制转换问题
package com.bobo.oop08;
public class OOPDemo01 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Student s = new Student();
AbsPerson p1 = s.study();
AbsPerson p2 = s.eat();
// 子类接收 父类的返回 那么需要强制类型转换
Person p3 = (Person)s.study(); // 强制转换有可能出现 ClassCastException异常
if(p2 instanceof Person){
Person p4 = (Person)p2;
}
System.out.println(p1);
System.out.println(p2);
}
}
abstract class AbsPerson{
}
class Person extends AbsPerson{
}
class Student{
public AbsPerson study(){
return new Person();
}
public AbsPerson eat(){
//AbsPerson p = new AbsPerson(){};
return new AbsPerson(){};
}
}
接口
当一个方法的返回值是一个接口时,实际返回的是该接口的实现类对象,我们可以使用接口来接收,同样的如果我们使用实现类来接收的话,那么同样有可能出现ClassCastException的问题,也就是强制类型转换的问题。
package com.bobo.oop09;
public class OOPDemo01 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Student s = new Student();
// IPerson p1 = new Person();
IPerson p1 = s.study();
IPerson p2 = s.eat();
// 子类接收 父类的返回 那么需要强制类型转换
Person p3 = (Person)s.study(); // 强制转换有可能出现 ClassCastException异常
if(p2 instanceof Person){
Person p4 = (Person)p2;
}
System.out.println(p1);
System.out.println(p2);
}
}
interface IPerson{
}
class Person implements IPerson{
}
class Student{
public IPerson study(){
return new Person();
}
public IPerson eat(){
//AbsPerson p = new AbsPerson(){};
return new IPerson(){};
}
}
补充:当方法的返回值类型是引用类型的时候,可以使用链式调用
interface IPerson{
IPerson sleep();
IPerson run();
IPerson eat();
}
class Person implements IPerson{
@Override
public IPerson sleep() {
// TODO Auto-generated method stub
return this;
}
@Override
public IPerson run() {
// TODO Auto-generated method stub
return this;
}
@Override
public IPerson eat() {
// TODO Auto-generated method stub
return this;
}
}
public static void main(String[] args) {
IPerson p1 = s.study();
// 链式调用
IPerson p5 = p1.eat().sleep().run().eat().run().sleep();
}