目录
多态
格式
父类/接口 变量名 = new 子类();
特点
对象的多态:等号右边是可以切换子类的对象。 行为的多态【重点】:方法重写之后,执行的是子类的方法。 【个人经验】 其实多态就是为了使用子类的方法,实现解耦【在不改变方法调用的时候,直接使用子类的方法,多好】
好处
1、可以切换等号右边的对象,实现切换一种方案 2、可以用父类/接口作为方法的参数,接收一切子类对象。增加方法的通用性
应用场景
如果一个问题有多个实现方案,我们就可以使用多态来解决问题
补充
强制类型转换:子类类型 新变量名 = (子类类型) 变量名
将类型转换为子类类型后才能调用子类特有的方法
可以使用 instanceof 判断变量的类型
格式:变量名 instanceof 类型名
案例代码
//主类
public class Animal {
private String name;
private String color;
public Animal() {
}
public Animal(String name, String color) {
this.name = name;
this.color = color;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return color
*/
public String getColor() {
return color;
}
/**
* 设置
* @param color
*/
public void setColor(String color) {
this.color = color;
}
public void eat(){
System.out.println(name + "在吃饭");
}
}
//子类Cat
public class Cat extends Animal{
public Cat() {
}
public Cat(String name, String color) {
super(name, color);
}
public void catchMouse(){//子类特有方法
System.out.println(getName() + "在抓老鼠");
}
@Override//重写父类方法
public void eat(){
System.out.println(getName() + "在吃猫粮");
}
}
//子类Dog
public class Dog extends Animal{
public Dog() {
}
public Dog(String name, String color) {
super(name, color);
}
public void lookHome(){//子类特有方法
System.out.println(getName() + "在看家");
}
@Override//重写父类方法
public void eat(){
System.out.println(getName() + "在吃骨头");
}
}
//测试类
public class Test {
public static void main(String[] args) {
Animal c = new Cat("橘猫","橘黄色");//多态结构 父类/接口 变量名 = new 子类();
Animal d = new Dog("大黄","黄色");
c.eat();
d.eat();
if(c instanceof Cat){//判断变量类型
Cat c1 = (Cat) c;//强制类型转换
c1.catchMouse();
}
if(d instanceof Dog){//判断变量类型
Dog d1 = (Dog) d;//强制类型转换
d1.lookHome();
}
}
}
代码运行结果如下:
Final修饰符
作用
1、可以修饰类 代表最终的类,不能被继承 一般都是底层或者源码的某一些类才会用到,实际开发用的比较少。 源码的类:String
2、可以修饰方法 代表最终的方法,不能被重写 一般都是比较少用到。目前用到的是在模板方法设计模式
3、可以修饰变量 代表常量,只能被赋值一次 基本数据类型,值不可以改变 引用数据类型,地址值不可以改变,但是地址上的值可以发生改变
4、注意事项 如果是修饰局部变量,可以先定义,后赋值 如果是修饰成员变量 可以直接赋值 也可以通过构造器赋值【如果是用构造器赋值一定要确保每一个构造器里面都要赋值】
使用场景
模板方法
1、作用 用于抽取多个方法中相同的代码 2、步骤 1.定义一个抽象类 2.把多个方法中相同的代码抽取到一个实例方法中 , 这个实例方法要用final修饰 3.定义一个抽象方法,不同的内容交给子类去实现
常量
1、概念 static final 修饰的变量 2、作用 记录一些系统的信息,或者一些特殊的数据 例如:公司的名称,整数的最大值、最小值 3、好处 可阅性好 4、命名规范 每个单词的每个字母都需要大写,多个单词之间通过下划线隔开
抽象类
格式
public abstract class 类名{ //抽象方法 public abstract 返回值类型 方法名(参数); // 没有方法体 }
好处
在抽象类中定义抽象方法,可以强制子类要去重写抽象方法。让我们更好使用多态【多态的前提就是要有方法重写】
注意事项
1、抽象类不一定要有抽象方法,有抽象方法的类就一定要定义为抽象类 2、抽象类比普通类就是多了抽象方法,普通类有的,抽象都可以有【成员变量、成员方法、构造器、代码块,内部类】 3、抽象类是不能创建对象的,要通过子类去继承抽象类 4、一个类继承了抽象类,一般都是要重写里面所有的抽象方法,否则就把这个类定义为抽象类
@Override
在子类中在重写的方法前添加注释@Override可以判断重写是否正确
应用场景
如果想让子类有着和父类同样的方法签名,我们就可以使用抽象类【相同的签名是为了多态】
案例代码
//父类,抽象类
public abstract class Employee {
private String name;
private int age;
private double salary;
public Employee() {
}
public Employee(String name, int age, double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
/**
* 获取
* @return salary
*/
public double getSalary() {
return salary;
}
/**
* 设置
* @param salary
*/
public void setSalary(double salary) {
this.salary = salary;
}
public abstract void work();//抽象方法
}
//子类Manager
public class Manager extends Employee{
public Manager() {
}
public Manager(String name, int age, double salary) {
super(name, age, salary);
}
@Override//重写work()抽象方法
public void work() {
System.out.println(getName() + "分配任务");
}
}
//子类Cook
public class Cooker extends Employee{
public Cooker() {
}
public Cooker(String name, int age, double salary) {
super(name, age, salary);
}
@Override//重写work()抽象方法
public void work() {
System.out.println(getName() + "炒菜");
}
}
//子类Worker
public class Worker extends Employee{
public Worker() {
}
public Worker(String name, int age, double salary) {
super(name, age, salary);
}
@Override//重写work()抽象方法
public void work() {
System.out.println(getName() + "拧螺丝");
}
}
//测试类
public class Test {
public static void main(String[] args) {
Employee m = new Manager("张三",50,5000);//多态
m.work();//调用抽象方法
Employee w = new Worker("李四",40,4000);
w.work();
Employee c = new Cooker("王五",45,4500);
c.work();
}
}
代码运行结果如下:
接口
概念
一种特殊的结构,其实,接口可以理解为一种更加彻底的抽象类【因为在实际开发中,我们一般都是在接口中定义抽象方法】
作用
起到一种约束的作用,让子类一定要重写里面的方法【就相当于制定了一套规则、规范,为了以后的拓展】
格式
public interface 接口名{ //常量【少用】 // 抽象方法【多用】 }
定义常量时 如果变量前面没有 public static final ,系统会默认加上
定义方法时 不管方法前面是否有public abstract ,系统默认都会加上
使用方法
接口是没有办法创建对象的,要通过子类去实现 public class 子类 implements 接口A, 接口B {
}
JDK8新增方法
目的
在不改变子类的前提下,增加子类的功能【子类不需要重写!】
方法
默认方法:要通过子类对象调用 public default 返回值类型 方法名(参数){
} 静态方法:要通过类名.方法名调用 public static 返回值类型 方法名(参数){
} 私有方法:只能在接口的默认方法中调用,把多个默认方法的相同内容抽取到私有方法中 private 返回值类型 方法名(参数){
}
案例代码
//接口Dance
public interface Dance {
void dance();//抽象方法
}
//接口Rapper
public interface Rapper {
void rapper();//抽象方法
}
//接口Sing
public interface Sing {
void sing();//抽象方法
}
//接口实现类Trainee
public class Trainee implements Sing,Dance,Rapper{
@Override
public void sing() {//重写接口方法
System.out.println("坤在唱歌");
}
@Override
public void dance() {//重写接口方法
System.out.println("坤在跳舞");
}
@Override
public void rapper() {//重写接口方法
System.out.println("坤在Rapper");
}
}
//测试类
public class Test {
public static void main(String[] args) {
Dance t = new Trainee();
t.dance();
Rapper r = new Trainee();
r.rapper();
Sing s = new Trainee();
s.sing();
}
}
代码运行结果如下