1、多态性
1.1 概念
概念:父类引用指向子类对象,从而产生多种形态。
- 父类对象指向子类对象
父类类型 父类对象 = new 子类类型();- 接口对象指向实现类对象
接口类型 接口对象 = new 实现类类型();- 约束父类对象只能调用子类从父类中继承的方法或者重写的方法
- 在方法的参数中,可以接受参数类型对应的对象,还可以接受其对应的子类对象
开闭原则
- open:对新增的代码持开放状态
- close:对内部修改的代码持关闭状态
创建Animal.java
public class Animal {
public void test01(){
System.out.println("父类的方法1");
}
public void test02(){
System.out.println("父类的方法2");
}
}
创建Cat.java
public class Cat extends Animal {
@Override
public void test01() {
System.out.println("子类重写父类的方法");
}
public void test03(){
System.out.println("子类独有的方法");
}
}
创建Demo01.java
public class Demo01 {
public static void main(String[] args) {
//-----------普通创建对象---------------
//new Cat()创建对象 Cat cat = 是指Cat类的对象接收
//cat 引用new Cat(),cat类型为Cat
Cat cat = new Cat();
//调用子类重写父类的方法
cat.test01();
//子类调用父类的方法
cat.test02();
//子类调用独有的方法
cat.test03();
System.out.println("--------------------");
//-------------使用多态创建对象------------
//animal引用new Cat(),animal类型为Animal
//父类对象指向子类对象
Animal aniaml = new Cat();
aniaml.test01();
aniaml.test02();
//子类调用独有的方法,父类引用无法调用
//aniaml.test03();
}
}
课堂示例:
创建Animal.java
public abstract class Animal {
public abstract void eat();
}
创建Cat.java
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
创建Demo.java
public class Demo {
/* public void test01(Cat cat){
cat.eat();
}
public void test02(Dog dog){
dog.eat();
}
public void test03(Pig pig){
pig.eat();
}*/
// 可以接收Animal类型的对象和Animal子类的对象
public void test(Animal animal){
animal.eat();
}
}
创建Demo01.java
public class Demo01 {
public static void main(String[] args) {
Cat cat = new Cat();
Dog dog = new Dog();
Pig pig = new Pig();
Demo demo = new Demo();
demo.test(cat);
demo.test(dog);
demo.test(pig);
}
}
创建Dog.java
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃肉");
}
}
创建Pig.java
public class Pig extends Animal {
@Override
public void eat() {
System.out.println("猪吃菜叶");
}
}
使用
2、修饰符
2.1 abstract
abstract:抽象的
- 1.abstract修饰的方法为抽象方法,必须存在抽象类中,没有方法体,子类必须重写
- 2.abstract修饰的类为抽象类
- 3.abstract不能修饰属性,构造方法,构造代码块
- 4.抽象类有构造方法(抽象类会被继承),但是不能被实例化(存在抽象方法)
- 5.抽象类中存在抽象方法,也能存在普通方法
- 6.抽象类中可以只有普通方法,这样做的用作只是让类无法被实例化
- 7.普通类继承抽象类,必须重写所有的抽象方法
- 8.抽象类可以继承抽象类,可以有选择地进行重写其中的抽象方法
抽象类的使用场景:
- 当父类存在一个或者多个子类必须重写的方法时,可以把父类写成抽象类
- 减少了需要重写的父类方法的方法体,约束了子类必须重写对应的方法
创建Animal.java
public abstract class Animal {
int age;
public Animal(){
}
public void sleep(){
System.out.println("趴着睡");
}
public abstract void eat();
public abstract void test();
}
创建Cat.java
public class Cat extends NewAnimal{
@Override
public void eat() {
System.out.println("猫吃猫粮");
}
}
创建Demo01.java
public class Demo01 {
public static void main(String[] args) {
//抽象类不能被实例化
/*Animal animal = new Animal();
animal.eat();*/
}
}
创建NewAnimal.java
public abstract class NewAnimal extends Animal{
@Override
public void test() {
}
}
创建Person.java
// 抽象类中可以只存在普通方法
public abstract class Person {
public void test(){
}
}
2.2 final
2.2.1 什么是final(最终)
概念:最后的,不可更改的。
- final可修饰的内容:
- 类(最终类)
- 方法(最终方法)
- 变量(最终变量)
2.2.2 final类
- final修饰类:此类不能被继承。
- String、Math、System均为final修饰的类,不能被继承。
- final修饰方法:此方法不能被覆盖(重写)。
- 意为最终方法,不支持子类以覆盖的形式修改。
2.2.3 final变量
final修饰变量:此变量值不能被改变(常量)。
2.2.4 final常量
- 静态常量不再提供默认值,必须手动赋予初始值。
- 赋值时机:显示初始化、静态代码块。
2.2.5 final方法
- 可以正常调用,可以被重载,不能被重写
创建Demo01.java
public class Demo01 {
public static void main(String[] args) {
User user = new User();
user.test2();
user.test2(1);
Father father = new Father();
String str = "";
}
}
创建Father.java
public final class Father {
}
创建Person.java
public class Person extends User {
/*public void test2(int num){
System.out.println("final重写的方法");
}*/
}
创建User.java
public class User /* extends Father*/{
//final与static一起使用,名字一般为大写,多个单词用下划线进行区分,SYSTEM_NAME
static final int ID = 1;
public void test1(){
//无法被重新赋值
//id = 2;
}
public void test2(){
System.out.println("final修饰的方法");
}
public final void test2(int num){
System.out.println("final重载的方法");
}
/* final 不能修饰构造方法
public final User(){
}*/
/* final 不能修饰构造代码块
final{
}*/
}
3、接口
3.1 概念
接口:
- 定义关键词interface,实现关键词implements
- 接口相当于特殊的抽象类,定义方式、组成部分与抽象类类似。
特点:
- 没有构造方法,不能创建对象。
- 只能定义:公开静态常量、公开抽象方法。
其他:
- 1.接口是一个特殊的抽象类,但不是类
- 2.一个类可以多实现接口
- 3.接口中的方法默认是抽象方法,访问修饰符默认是public
- 4.接口中不能有普通方法,都是必须要被实现的抽象方法
- 5.接口中的属性默认为静态常量,访问修饰符默认是public,不能私有化
- 6.接口不存在构造方法,更不能被实例化
- 7.接口不存在构造代码块
- 8.接口不能实现接口
- 9.接口可以多继承接口
10.JDK1.8新特性
- 接口中允许存在default和static修饰的方法
- default修饰的方法可以被重写,static修饰的方法不能被重写
isp:
- 接口分离原则:一个接口只做一件事
面向对象设计原则:(开口合里最单依)
- 开闭原则,
- 接口分离原则,
- 合成复用原则,
- 里氏替换原则,
- 最少原则(迪米特原则),
- 单一原则,
- 依赖原则
3.2 与抽象类的区别
相同点:
- 可编译成字节码文件。
- 不能创建对象。
- 可以作为引用类型。
- 具备Object类中所定义的方法。
不同点:
- 所有属性都是公开静态常量,隐式使用public static final修饰。
- 所有方法都是公开抽象方法,隐式使用public abstract修饰。
- 没有构造方法、动态代码块、静态代码块。
创建Demo01.java
public class Demo01 {
}
创建Door.java
public abstract class Door {
public abstract void open();
public abstract void close();
}
创建FingerDoor.java
public class FingerDoor extends Door implements IFinger{
@Override
public void open() {
System.out.println("开指纹门");
}
@Override
public void close() {
System.out.println("关指纹门");
}
@Override
public void finger() {
System.out.println("指纹解锁");
}
}
创建IFace.java
//人脸识别的接口
public interface IFace {
void face();
}
创建IFinger.java
//指纹解锁的接口
public interface IFinger {
//接口中的方法默认是公开抽象的方法
void finger();
}
创建IronDoor.java
//铁门
public class IronDoor extends Door{
@Override
public void open() {
System.out.println("开铁门");
}
@Override
public void close() {
System.out.println("关铁门");
}
}
创建StainlessDoor.java
//不锈钢门 -- 能够进行指纹解锁和人脸识别
public class StainlessDoor extends Door implements IFinger,IFace{
@Override
public void open() {
System.out.println("开不锈钢门");
}
@Override
public void close() {
System.out.println("关不锈钢门");
}
@Override
public void finger() {
System.out.println("指纹解锁不锈钢门");
}
@Override
public void face() {
System.out.println("人脸识别不锈钢门");
}
}
创建TreeDoor.java
public class TreeDoor extends Door{
@Override
public void open() {
System.out.println("开木门");
}
@Override
public void close() {
System.out.println("关木门");
}
}
4、转型
instance of关键字
- 判断关键词左边的对象是否为右边的类型,如果是则返回true
- 向下转型前,应判断引用中的对象真实类型,保证类型转换的正确性。
- 语法:父类引用 instance of 类型
4.1 向上转型
父类引用中保存真实子类对象,称为向上转型(即多态核心概念)。
注意: 仅可调用Animal中所声明的属性和方法。
4.2 向下转型
将父类引用中的真实子类对象,强转回子类本身类型,称为向下转型。
注意:只有转换回子类真实类型,才可调用子类独有的属性和方法。
4.3 代码示例
创建Animal.java
public class Animal {
}
创建Cat.java
public class Cat extends Animal {
public void test01(){
System.out.println("cat独有的方法");
}
}
创建Dog.java
public class Dog extends Animal {
public void test01(){
System.out.println("dog独有的方法");
}
}
创建Demo01.java
public class Demo01 {
public static void main(String[] args) {
/*
//小类型转大类型 -- 默认转换 -- 向上转型
int num1 = 1;
long num2 = num1;
//大类型转小类型 -- 强制转换 -- 向下转型
int num3 = 128;
byte num4 = (byte)num3;//-128
//引用数据类型转换
//子类转父类 -- 默认转换 -- 向上转型
Cat cat1 = new Cat();
Animal animal1 = cat1;
//父类转子类 -- 强制转换 -- 向下转型
Animal animal2 = new Animal();
Cat cat = (Cat)animal2;
*/
/*
会报类型转换异常
Animal animal = new Cat();
Dog dog = (Dog)animal;*/
}
Cat cat = new Cat();
test(cat);
Dog dog = new Dog();
test(dog);
}
public static void test(Animal animal){
//无法通过animal直接调用,因为test01是子类独有的方法
//animal.test01()
//判断animal是哪个子类对象,强转成对应的子类对象再调用独有的方法
if(animal instanceof Cat){
Cat cat = (Cat)animal;
cat.test01();
}else if(animal instanceof Dog){
Dog dog = (Dog)animal;
dog.test01();
}
}