VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > Java教程 >
  • 全套Java教程_Java基础入门教程,零基础小白自学Java必备教程

一、本单元知识点概述

(Ⅰ)知识点概述

 

二、本单元目标

(Ⅰ)重点知识目标

1.定义接口的格式
2.接口中成员的特点
3.接口的多实现操作
4.接口的多继承操作

(Ⅱ)能力目标

1.掌握发红包案例的代码逻辑
2.掌握定义接口的格式
3.掌握实现接口的格式
4.掌握接口中成员的特点

三、本单元知识详讲

14.1 发红包的综合案例

14.1.1 综合案例:群主发普通红包★★★

群主发普通红包。某群有多名成员,群主给成员发普通红包。普通红包的规则:

  1. 群主的一笔金额,从群主余额中扣除,平均分成n等份,让成员领取。

  2. 成员领取红包后,保存到成员余额中。

请根据描述,完成案例中所有类的定义以及指定类之间的继承关系,并完成发红包的操作。

14.1.2 案例分析 ★★★

根据描述分析,得出如下继承体系:

 

14.1.3 案例实现 ★★★

定义用户类:

复制代码
 1 public class User {
 2     // 成员变量 
 3     private String username;// 用户名
 4     private double leftMoney;// 余额 
 5     // 构造方法
 6     public User() { }
 7     public User(String username, double leftMoney) {
 8         this.username = username; 
 9         this.leftMoney = leftMoney;
10     }
11     // get/set方法
12     public String getUsername() {
13         return username; 
14     }
15     public void setUsername(String username) { 
16         this.username = username; 
17     }
18     public double getLeftMoney() {
19         return leftMoney; 
20     }
21     public void setLeftMoney(double leftMoney) {
22         this.leftMoney = leftMoney; 
23     }
24     // 展示信息的方法
25     public void show() {
26         System.out.println("用户名:"+ username +" , 余额为:" + leftMoney + "元");
27     } 
28 }

定义群主类:

复制代码
 1 public class QunZhu extends User { 
 2     // 添加构造方法 
 3     public QunZhu() { }
 4     public QunZhu(String username, double leftMoney) { // 通过super 调用父类构造方法 
 5         super(username, leftMoney); 
 6     }
 7     /*
 8       群主发红包,就是把一个整数的金额,分层若干等份。
 9         1.获取群主余额,是否够发红包. 不能则返回null,并提示. 能则继续.
10         2.修改群主余额. 
11         3.拆分红包. 
12             3.1.如果能整除,那么就平均分。
13             3.2.如果不能整除,那么就把余数分给最后一份。
14     */ 
15     public ArrayList<Double> send(int money, int count) { 
16         // 获取群主余额 
17         double leftMoney = getLeftMoney(); 
18         if(money > leftMoney) {  
19             return null; 
20         }
21         // 修改群主余额的 
22         setLeftMoney(leftMoney ‐ money); 
23         // 创建一个集合,保存等份金额 
24         ArrayList<Double> list = new ArrayList<>(); 
25         // 扩大100倍,相当于折算成'分'为单位,避免小数运算损失精度的问题 
26         money = money * 100;
27         // 每份的金额
28         int m = money / count; 
29         // 不能整除的余数 
30         int l = money % count; 
31         // 无论是否整除,n‐1份,都是每份的等额金额 
32         for (int i = 0; i < count ‐ 1; i++) {
33             // 缩小100倍,折算成 '元' 
34             list.add(m / 100.0); 
35         }
36         // 判断是否整除 
37         if (l == 0) { 
38             // 能整除, 最后一份金额,与之前每份金额一致 
39             list.add(m / 100.0); 
40         } else { 
41             // 不能整除, 最后一份的金额,是之前每份金额+余数金额 
42             list.add((m + l) / 100.00);
43         }
44         // 返回集合 
45         return list; 
46     } 
47 }

定义成员类:

复制代码
 1 public class Member extends User { 
 2     public Member() { }
 3     public Member(String username, double leftMoney) {
 4         super(username, leftMoney); 
 5     }
 6     // 打开红包,就是从集合中,随机取出一份,保存到自己的余额中 
 7     public void openHongbao(ArrayList<Double> list) {
 8         // 创建Random对象 
 9         Random r = new Random(); 
10         // 随机生成一个角标 
11         int index = r.nextInt(list.size()); 
12         // 移除一个金额
13         Double money = list.remove(index); 
14         // 直接调用父类方法,设置到余额 
15         setLeftMoney( money ); 
16     } 
17 }

定义测试类:

复制代码
 1 public class Test {
 2     public static void main(String[] args) { 
 3         // 创建一个群主对象 
 4         QunZhu qz = new QunZhu("群主" , 200); 
 5         // 创建一个键盘录入 
 6         Scanner sc = new Scanner(); 
 7         System.out.println("请输入金额:");
 8         int money = sc.nextInt(); 
 9         System.out.println("请输入个数:"); 
10         int count = sc.nextInt(); 
11         // 发送红包 
12         ArrayList<Double> sendList = s.send(money,count);
13         // 判断,如果余额不足
14         if(sendList == null){ 
15             System.out.println(" 余额不足..."); 
16             return; 
17         }
18         // 创建三个成员 
19         Member m = new Member();
20         Member m2 = new Member(); 
21         Member m3 = new Member(); 
22         // 打开红包 
23         m.openHongbao(sendList); 
24         m2.openHongbao(sendList);
25         m3.openHongbao(sendList);
26         // 展示信息 
27         qz.show();
28         m.show();
29         m2.show(); 
30         m3.show(); 
31     } 
32 }

14.2 接口

14.2.1 概述 ★★★

接口,是Java语言中一种引用类型,是方法的集合,如果说类的内部封装了成员变量、构造方法和成员方法,那么

接口的内部主要就是封装了方法,包含抽象方法(JDK 7及以前),默认方法和静态方法(JDK 8),私有方法(JDK 9)。

接口的定义,它与定义类方式相似,但是使用 interface 关键字。它也会被编译成.class文件,但一定要明确它并

不是类,而是另外一种引用数据类型。

引用数据类型:数组,类,接口。

接口的使用,它不能创建对象,但是可以被实现( implements ,类似于被继承)。一个实现接口的类(可以看做是接口的子类),需要实现接口中所有的抽象方法,创建该类对象,就可以调用方法了,否则它必须是一个抽象

类。

14.2.2 定义格式 ★★★★

复制代码
public interface 接口名称 { 
    // 抽象方法
    // 默认方法
    // 静态方法 
    // 私有方法 
}

含有抽象方法

抽象方法:使用 abstract 关键字修饰,可以省略,没有方法体。该方法供子类实现使用。

代码如下:

复制代码
public interface InterFaceName { 
    public abstract void method(); 
}

**含有默认方法和静态方法**

默认方法:使用 default 修饰,不可省略,供子类调用或者子类重写。

静态方法:使用 static 修饰,供接口直接调用。

代码如下:

复制代码
public interface InterFaceName { 
    public default void method() {
        // 执行语句 
    }
    public static void method2() { 
        // 执行语句 
    } 
}

含有私有方法和私有静态方法

私有方法:使用 private 修饰,供接口中的默认方法或者静态方法调用。

代码如下:

复制代码
public interface InterFaceName { 
    private void method() { 
        // 执行语句 
    } 
}

14.2.3 基本的实现 ★★★★

实现的概述

类与接口的关系为实现关系,即类实现接口,该类可以称为接口的实现类,也可以称为接口的子类。实现的动作类

似继承,格式相仿,只是关键字不同,实现使用 implements 关键字。

非抽象子类实现接口:

  1. 必须重写接口中所有抽象方法。

  2. 继承了接口的默认方法,即可以直接调用,也可以重写。

实现格式:

复制代码
class 类名 implements 接口名 {
    // 重写接口中抽象方法【必须】 
    // 重写接口中默认方法【可选】 
}

抽象方法的使用

必须全部实现,代码如下:

定义接口:

复制代码
public interface LiveAble { 
    // 定义抽象方法 
    public abstract void eat(); 
    public abstract void sleep(); 
}

定义实现类:

复制代码
 1 public class Animal implements LiveAble {
 2     @Override 
 3     public void eat() { 
 4         System.out.println("吃东西"); 
 5     }
 6     @Override 
 7     public void sleep() { 
 8         System.out.println("晚上睡"); 
 9     } 
10 }

定义测试类:

复制代码
 1 public class InterfaceDemo {
 2     public static void main(String[] args) { 
 3         // 创建子类对象 
 4         Animal a = new Animal(); 
 5         // 调用实现后的方法 
 6         a.eat(); 
 7         a.sleep(); 
 8     } 
 9 }
10 输出结果:
11 吃东西 
12 晚上睡

默认方法的使用

可以继承,可以重写,二选一,但是只能通过实现类的对象来调用。

  1. 继承默认方法,代码如下:

复制代码
1 public interface LiveAble { 
2     public default void fly(){
3         System.out.println("天上飞");
4     } 
5 }

定义实现类:

复制代码
public class Animal implements LiveAble {
    // 继承,什么都不用写,直接调用 
}

定义测试类:

复制代码
 1 public class InterfaceDemo { 
 2     public static void main(String[] args) { 
 3         // 创建子类对象 
 4         Animal a = new Animal(); 
 5         // 调用默认方法 
 6         a.fly(); 
 7     } 
 8 }
 9 输出结果:
10 天上飞
  1. 重写默认方法,代码如下:

定义接口:

复制代码
1 public interface LiveAble { 
2     public default void fly(){
3         System.out.println("天上飞");
4     } 
5 }

定义实现类:

复制代码
1 public class Animal implements LiveAble { 
2     @Override 
3     public void fly() { 
4         System.out.println("自由自在的飞"); 
5     }
6 }

定义测试类:

复制代码
 1 public class InterfaceDemo { 
 2     public static void main(String[] args) { 
 3         // 创建子类对象 
 4         Animal a = new Animal(); 
 5         // 调用重写方法 
 6         a.fly(); 
 7     } 
 8 }
 9 输出结果:
10 自由自在的飞

静态方法的使用

静态与.class 文件相关,只能使用接口名调用,不可以通过实现类的类名或者实现类的对象调用,代码如下:

定义接口:

复制代码
1 public interface LiveAble { 
2     public static void run(){ 
3         System.out.println("跑起来~~~");
4     } 
5 }

定义实现类:

复制代码
public class Animal implements LiveAble {
    // 无法重写静态方法 
}

定义测试类:

复制代码
1 public class InterfaceDemo {
2     public static void main(String[] args) { 
3         // Animal.run(); // 【错误】无法继承方法,也无法调用 
4         LiveAble.run(); 
5     } 
6 }
7 输出结果:
8 跑起来~~~

私有方法的使用

  • 私有方法:只有默认方法可以调用。

  • 私有静态方法:默认方法和静态方法可以调用。

如果一个接口中有多个默认方法,并且方法中有重复的内容,那么可以抽取出来,封装到私有方法中,供默认方法

去调用。从设计的角度讲,私有的方法是对默认方法和静态方法的辅助。同学们在已学技术的基础上,可以自行测

试。

定义接口:

复制代码
 1 public interface LiveAble { 
 2     default void func(){ 
 3         func1(); 
 4         func2(); 
 5     }
 6     private void func1(){ 
 7         System.out.println("跑起来~~~"); 
 8     }
 9     private void func2(){ 
10         System.out.println("跑起来~~~"); 
11     } 
12 }

14.2.4 接口的多实现 ★★★

之前学过,在继承体系中,一个类只能继承一个父类。而对于接口而言,一个类是可以实现多个接口的,这叫做接

口的多实现。并且,一个类能继承一个父类,同时实现多个接口。

实现格式:

复制代码
class 类名 [extends 父类名] implements 接口名1,接口名2,接口名3... {
    // 重写接口中抽象方法【必须】 
    // 重写接口中默认方法【不重名时可选】 
}

[ ]: 表示可选操作。

抽象方法

接口中,有多个抽象方法时,实现类必须重写所有抽象方法。如果抽象方法有重名的,只需要重写一次。代码如

下:

定义多个接口:

复制代码
1 interface A { 
2     public abstract void showA();
3     public abstract void show(); 
4 }
5 interface B { 
6     public abstract void showB();
7     public abstract void show();
8 }

定义实现类:

复制代码
 1 public class C implements A,B{
 2     @Override 
 3     public void showA() { 
 4         System.out.println("showA"); 
 5     }
 6     @Override
 7     public void showB() { 
 8         System.out.println("showB"); 
 9     }
10     @Override 
11     public void show() { 
12         System.out.println("show"); 
13     } 
14 }

默认方法

接口中,有多个默认方法时,实现类都可继承使用。如果默认方法有重名的,必须重写一次。代码如下:

定义多个接口:

复制代码
1 interface A { 
2     public default void methodA(){}
3     public default void method(){}
4 }
5 interface B { 
6     public default void methodB(){}
7     public default void method(){}
8 }

定义实现类:

复制代码
1 public class C implements A,B{ 
2     @Override 
3     public void method() {
4         System.out.println("method");
5     } 
6 }

静态方法

接口中,存在同名的静态方法并不会冲突,原因是只能通过各自接口名访问静态方法。

优先级的问题

当一个类,既继承一个父类,又实现若干个接口时,父类中的成员方法与接口中的默认方法重名,子类就近选择执

行父类的成员方法。代码如下:

定义接口:

复制代码
1 interface A { 
2     public default void methodA(){
3         System.out.println("AAAAAAAAAAAA");
4     } 
5 }

定义父类:

复制代码
1 class D { 
2     public void methodA(){ 
3         System.out.println("DDDDDDDDDDDD");
4     } 
5 }

定义子类:

复制代码
1 class C extends D implements A { 
2     // 未重写methodA方法 
3 }

定义测试类:

复制代码
1 public class Test {
2     public static void main(String[] args) {
3         C c = new C();
4         c.methodA();
5     } 
6 }
7 输出结果: 
8 DDDDDDDDDDDD

14.2.5 接口的多继承★★★

一个接口能继承另一个或者多个接口,这和类之间的继承比较相似。接口的继承使用 extends 关键字,子接口继承父接口的方法。如果父接口中的默认方法有重名的,那么子接口需要重写一次。代码如下:

定义父接口:

复制代码
 1 interface A { 
 2     public default void method(){
 3         System.out.println("AAAAAAAAAAAAAAAAAAA"); 
 4     } 
 5 }
 6 interface B { 
 7     public default void method(){ 
 8         System.out.println("BBBBBBBBBBBBBBBBBBB"); 
 9     } 
10 }

定义子接口:

复制代码
1 interface D extends A,B{ 
2     @Override 
3     public default void method() {
4         System.out.println("DDDDDDDDDDDDDD"); 
5     } 
6 }

小贴士:

子接口重写默认方法时,default关键字可以保留。

子类重写默认方法时,default关键字不可以保留。

14.2.6 其他成员特点 ★★★

  • 接口中,无法定义成员变量,但是可以定义常量,其值不可以改变,默认使用public static final修饰。

  • 接口中,没有构造方法,不能创建对象。

  • 接口中,没有静态代码块。

四、本单元知识总结

1. 接口的定义格式
2. 接口的特点
3. 接口的多实现

本文作者:会写BUG的程序员

本文链接:https://www.cnblogs.com/Z777/p/15400534.html



相关教程