一、枚举
1、枚举的概述
- 枚举是java中的一种特殊类型
2、枚举的作用:是为了做信息的标志和信息的分类。
定义枚举类的格式:
修饰符 enum 枚举名称{
第一行都是罗列枚举类实例的名称。
}
enum Season{
SPRING, SUMMER,AUTUMN,WINTER;
}
/**
* 枚举类
*/
public enum Season {
//枚举的第一行必须罗列枚举类的对象名称,建议全部大写。
SPRING, SUMMER,AUTUMN,WINTER;
}
//反编译后枚举的特征
public final class Season extends java.lang.Enum<Season> {
public static final Season SPRING;
public static final Season SUMMER;
public static final Season AUTUMN;
public static final Season WINTER;
public static Season[] values();
public static Season valueOf(java.lang.String);
static {};
}
枚举的特征:
枚举类都是继承了枚举类型: java.lang.Enum
枚举都是最终类,不可以被继承。
构造器的构造器都是私有的,枚举对外不能创建对象。
枚举类的第一行默认都是罗列枚举对象的名称的。
枚举相当于是多例模式
3、枚举的使用场景演示
案例说明:
- 现在开发的超级玛丽游戏需要接收用户输入的四个方向的信号( 上下左右),以便控制玛丽移动的方向。
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.util.Random;
public class EnumDemo02 {
public static void main(String[] args) {
//1、创建一个窗口对象(桌子)
JFrame win = new JFrame();
//2、创建一个面板对象(桌布)
JPanel panel = new JPanel();
//3、把桌布垫在桌子上
win.add(panel);
//4、创建四个按钮对象
JButton btn1 = new JButton("上");
JButton btn2 = new JButton("下");
JButton btn3 = new JButton("左");
JButton btn4 = new JButton("右");
//5、把按钮对象添加到桌布上去
panel.add(btn1);
panel.add(btn2);
panel.add(btn3);
panel.add(btn4);
//6、 窗口显示
win.setLocationRelativeTo(null);
win.setSize(300,400);
win.setVisible(true);
btn1.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
move(Orientation.UP); //让玛丽往上跳
}
});
btn2.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
move(Orientation.DOWN); //让玛丽往下跳
}
});
btn3.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
move(Orientation.LEFT); //让玛丽往左跳
}
});
btn4.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
move(Orientation.RIGHT); //让玛丽往右跳
}
});
}
public static void move(Orientation o){
//控制玛丽移动
switch (o){
case UP:
System.out.println("让玛丽往上飞一下~~");
break;
case DOWN:
System.out.println("让玛丽往下飞一下~~");
break;
case LEFT:
System.out.println("让玛丽往左飞一下~~");
break;
case RIGHT:
System.out.println("让玛丽往右飞一下~~");
break;
}
}
}
/**
* 枚举类
* 做信息标志分类
*/
public enum Orientation {
UP, DOWN, LEFT,RIGHT;
}
①选择常量做信息标志和分类:
- 虽然可以实现可读性,但是入参值不受约束,代码相对不够严谨。
②枚举做信息标志和分类:
- 代码可读性好,入参约束严谨,代码优雅,是最好的信息分类技术!建议使用!
二、抽象类
1、抽象类
- 在java中abstract是抽象的意思,可以修饰类、成员方法、
- abstract修饰类,这个类就是抽象类;修饰方法,这个方法就是抽象方法。
修饰符 abstract class 类名{
修饰符 abstract 返回值类型 方法名称(形参列表);
}
public abstract class Animal{
public abstract void run();
}
2、注意事项:
- 抽象方法只有方法签名,不能声明方法体。
- 一个类中如果定义了抽象方法,这个类中必须声明成抽象类,否则报错。
3、抽象的使用场景
- 抽象类可以理解成不完整的设计图,一般作为父类,让子类来继承。
- 当父类知道子类一定要完成某些行为,但是每个子类该行为的实现又不同,于是该父类就把该行为定义成抽象方法的形式,具体实现交给子类去完成。此时这个类就可以声明为抽象类。
/**
* 抽象类
*/
public abstract class Animal {
/**
* 抽象方法 有abstract 修饰 不能写方法体代码(没有中括号)
*/
public abstract void run();
}
public class Dog extends Animal{
@Override
public void run() {
System.out.println("狗跑的贼快~~");
}
}
public class Test {
public static void main(String[] args) {
//目标:认识抽象类 再了解它的使用场景
Dog d = new Dog();
d.run();
}
}
总结:
①、抽象类。抽象方法是什么样的?
- 都是用abstract修饰的,抽象方法只有方法签名,不能写方法体。
- 一个类中定义了抽象方法,这个类必须声明成抽象类。
②、抽象类基本作用是啥?
- 作为父类,用来被子类继承的。
③、继承抽象类有哪些要注意的?
- 一个类继承了抽象类,那么这个类必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类。
4、抽象类的案例
系统需求
- 某加油站推出了 2种支付卡,一种是预存10000的金卡,后续加油享受8折优惠,另一种
是预存5000的银卡,后续加油享受8.5折优惠。 - 请分别实现2种卡片进入收银系统后的逻辑,卡片需要包含主人名称,余额,支付功能。
分析实现:
●创建一张卡片父类:定义属性包括主人名称、余额、支付功能(具体实现交给子类)
●创建一张白金卡类:重写支付功能,按照原价的8折计算输出。
●创建一张银卡类:重写支付功能,按照原价的8. 5折计算输出。
public abstract class Card {
private String UserName;
private double money;
/**
* 定义抽象类支付方法
*/
public abstract void pay(double money2);
public String getUserName() {
return UserName;
}
public void setUserName(String userName) {
UserName = userName;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
}
public class GoldenCard extends Card{ //1、继承抽象类方法
@Override //2、重写抽象类的支付功能
public void pay(double money2) {
//3、计算原价8折
double rs = money2 *0.8;
//4、显示支付多少
System.out.println(getUserName()+"您一共支付了:"+rs+"元");
//5、更新账户
setMoney(getMoney() - rs);
//6、显示余额
System.out.println("您的总余额剩余:"+getMoney()+"元");
}
}
public class Test {
public static void main(String[] args) {
//7、调用方法实现
GoldenCard goldenCard = new GoldenCard();
goldenCard.setMoney(20000);
goldenCard.setUserName("王叔叔");
goldenCard.pay(3000);
}
}
5、抽象类的特征、注意事项小结
特征和注意事项:
- 类有的成员(成员变量、方法、构造器)抽象类都具备
- 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
- 一个类继承了抽象类必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类。
- 不能用abstract修饰变量、代码块、构造器。
- 最重要的特征:得到了抽象方法,失去了创建对象的能力(有得有失)
6、fanal 和abstract是什么关系?
- 互斥关系
- abstract定义 的抽象类作为模板让子类继承,final定 义的类不能被继承。
- 抽象方法定义通用功能让子类重写,final定义的方法子类不能重写。
7、抽象类的应用知识:模板方法模式
①什么时候使用模板方法模式
使用场景说明:当系统中出现同一个功能多处在开发,而该功能中大部分代码是一样的,只有其中部分可能不同的时候、
②模板方法模式实现步骤
- 把功能定义成一个所谓的模板方法,放在抽象类中,模板方法中只定义通用且能确定的代码。
- 模板方法中不能决定的功能 定义成抽象方法让具体子类去实现。
③理解模板方法:写作文案例
需求:
- 现在有两类学生,一类是中学生, -类是小学生,他们都要写《我的爸爸》>这篇作文。
- 要求每种类型的学生,标题第- -段和最后一-段,内容必须-样。正文部分自己发挥。
- 请选择最优的面向对象方 案进行设计。
import java.io.StringWriter;
public abstract class Write {
/**
* 正式:声明模板方法
*/
public final void write(){ //模板呀应该用final来修饰 防止被重写 显得更专业
System.out.println("\t\t\t\t《我的爸爸》");
System.out.println("请说说你的爸爸:");
//正文部分:每个子类都要写 每个子类写的情况又不一样
//因此。模板方法把正文部分定义成抽象法方法,交给具体的子类去实现
System.out.println(writeMain());
System.out.println("我的爸爸简直太好了~~");
}
public abstract String writeMain();
}
/**
* //中学生类
*
*/
public class StudentMiddle extends Write {
@Override
public String writeMain() {
return "我的爸爸真是太好了~~~~~~~~";
}
}
/**
* 小学生类
*/
public class StudentChild extends Write {
@Override
public String writeMain() {
return "我的爸爸真是太好了~~~~~~~~";
}
}
public class Test {
public static void main(String[] args) {
//目标:理解模板方法模式的思想和使用步骤
StudentChild s = new StudentChild();
s.write();
}
}
模板方法建议使用final修饰的,这样会更专业,那么为什么呢?
答:模板方法是给子类直接使用的,不是让子类重写的;
一旦子类重写了模板方法,则模板方法就失效了,因此,加上final后可以防止子类重写了模板方法,这样更安全、专业。
总结:
1、模板方法模式解决了什么问题?
- 提高了代码的复用性
- 模板方法已经定义了通用结构,模板方法不能确定的部分定义成抽象方法,交给子类实现,因此,使用者只需要关心自己需要实现的功
能即可。
三、接口
1、接口的定义与特点
- 接口的格式如下
接口用关键字interface 来定义
public interface 接口名{
//常量
//抽象方法
}
/**
* 声明一个接口:体现一种规范;规范一定是公开的。
*/
public interface InterfaceDemo {
//目标:接口中的成分特点:JDK8之前接口中只能有抽象方法和常量。
//1、常量
//注意:由于接口体现规范思想;规范都是默认公开的;所以代码层面:public abstract 可以省略不写
String SCHOOL_NAME = "我是程序员";
public static final String SCHOOL_NAME = "我是程序员";
// public static final 可以省略不写
//2、抽象方法
//注意:由于接口体现规范思想;规范都是默认公开的;所以代码层面:public abstract 可以省略不写
void run();
// public abstract void run();
void ext();
// public abstract void ext();
}
- JKD8之前接口中只能是抽象方法和常量,没有其他成分了。
2、什么是接口?
- 接口是一种规范。
3、接口的基本使用:被实现
接口的用法: 接口是用来被类实现(implements) 的,实现接口的类称为实现类。实现类可以理解成所谓的子类。
修饰符 class 实现类 implements 接口1,接口2,接口3,...{
}
实现的关键字:implements
public class Test {
public static void main(String[] args) {
//目标:理解接口的基本使用:被类实现
PingPongMan p= new PingPongMan("张继科");
p.run();
p.competition();
p.rule();
}
}
/**
* 实现类
*/
public class PingPongMan implements SportMan,Law{
private String name;
public PingPongMan(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println(name+"必须跑步训练!!");
}
@Override
public void competition() {
System.out.println(name+"必须参加比赛!!");
}
@Override
public void rule() {
System.out.println(name+"必须守法!!");
}
}
/**
* 规范
*/
public interface SportMan {
void run();
void competition();
}
public interface Law {
void rule();
}
接口实现的注意事项:
- 一个类实现接口,必须重写完全部接口的全部抽象方法,否则这个类需要定义成抽象类。
4、接口与接口的关系:多继承
基本小结:
- 类与类的关系:单继承。
- 类与接口的关系:多实现。
- 接口与接口的关系:多继承,一个接口可以同时继承多个接口。
public class Test {
public static void main(String[] args) {
//目标:理解接口多继承的作用。
BasketBallMan ballMan = new BasketBallMan();
ballMan.rule();
ballMan.competition();
ballMan.eat();
ballMan.run();
ballMan.sleep();
}
}
/**
* 接口可以多继承:一个接口可以同时继承多个接口
*/
public interface SportMan extends Law,People{
void run();
void competition();
}
public interface Law {
void rule();
}
public interface People {
void eat();
void sleep();
}
/**
* 实现类
*/
public class BasketBallMan implements SportMan {
@Override
public void rule() {
System.out.println("必须参加比赛");
}
@Override
public void eat() {
System.out.println("必须吃东西");
}
@Override
public void sleep() {
System.out.println("必须睡觉觉");
}
@Override
public void run() {
System.out.println("必须训练");
}
@Override
public void competition() {
System.out.println("必须竞争");
}
}
接口多继承的作用
- 规范合并, 整合多个接口为同- -个接口,便于子类实现。
5、JDK8开始接口新增方法
JDK8开始之后,Java只对接口的成员方法进行了新增
原因如下:
第一种:默认方法
- 类似之前写的普通实例方法:必须用default修饰
- 默认会public修饰。 需要用接口的实现类的对象来调用
default void run(){
Systen.out.println("开始跑");
}
第二种:静态方法
- 默认会public修饰, 必须static修饰。
- 注意:接口的静态方法必须用本身的接口名来调用。
static void inAddr(){
Systen.out.println("我在快乐的学习java");
}
第三种:私有方法
- 就是私有的实例方法:,必须使用private修饰,从JDK 1.9才开始有的。
- 只能在本类中被其他的默认方法或者私有方法访问。
private void go(){
Systen.out.println("准备开始学习");
}
public interface SportManInter {
/**
* 1、JDK8开始:默认方法(实例方法)
*
* --必须default修饰--,默认用public修饰
* 默认方法属于对象才能调的 接口不能创建对象 所以这个方法只能过继给实现类 由实现类的对象调用
*
*/
default void run (){
go();// 这个是私有方法 只能在内部调
System.out.println("跑得很快~~");
}
/**
* 2、静态方法
* 必须使用static修饰 默认也会用public修饰
*接口的静态方法,必须接口名自己调用。
*
*/
static void inAddr(){
System.out.println("我们都在学习JAVA新增方法的语法~~它是java源码自己会用到的~~");
}
/**
* 3、私有方法(实例方法)
* --- JDK 1.9开始才支持的---
* 必须在接口内部才能被访问
*/
private void go(){
System.out.println("开始跑~~~");
}
}
class PingPongMan implements SportManInter{
}
class Test{
public static void main(String[] args) {
PingPongMan pongMan = new PingPongMan();
pongMan.run();
SportManInter.inAddr(); //接口的静态方法,必须接口名自己调用。
}
}
总结:1、jDK8开始后新增了那些方法?
-
默认方法: default修饰,实现类对象调用。
-
静态方法: static修饰,必须用当前接口名调用
-
私有方法: private修饰, jdk9开始才有的,只能在接口内部被调用。
-
他们都会默认被public修饰。
-
JDK8新增的3种方法我们自己在开发中很少使用,通常是Java源码涉及到。现阶段需要理解、识别语法,明白调用关系即可。
6、使用接口的注意事项
接口的注意事项:
1、接口不能创建对象
2、一个类实现多个接口,多个接口中有同样的静态方法不冲突。
3、一个类继承了父类,同时又实现了接口,父类中和接口中有同名方法,默认用父类的。,
4、一个类实现了多个接口,多个接口中存在同名的默认方法,不冲突,这个类重写该方法即可。
5、一个接口继承多个接口,是没有问题的,如果多个接口中存在规范冲突则不能多继承。