JavaSE(10) - 面向对象进阶

发布时间 2023-11-04 18:29:48作者: 大宝贝94106

JavaSE(10) - 面向对象进阶

P129 认识多态 (polymorphism)

  1. 多态就是对象的多种形态
  2. 多态的前提是: 1,有继承/实现关系 2,有父类引用指向子类对象 3,有方法重写
  3. 多态的好处: 使用父类型作为参数, 可以接收所有子类对象,体现多态的扩展性与便利

P130 多态调用成员的特点

  • 调用成员变量 : 编译看左边, 运行也看左边
  • 调用成员方法 : 编译看左边, 运行看右边

P131 多态的优势和弊端

1, 多态的优势

方法中, 使用父类型作为参数, 可以接收所有子类对象

2, 多态的弊端

不能使用子类的特有功能,如果要用要转换回子类对象

3, 引用数据类型的类型转换有两种, 自动类型转换, 强制类型转换

Person p = new Student();//自动类型转换,小变大
Student s = (Student)p;//强制类型转换,大变小

4, 强制类型转换可以转换成真正的子类类型, 从而调用子类独有功能

​ 转换类型与真实类型不一致会报错,这时可以用instanceof关键字进行判断

//判断变量a是不是Dog类型,如果是就返回true,否则返回false,
if(a instanceof Dog){
    Dog d = (Dog)a;
    d.lookHome();
}else if(a instanceof Cat){
    Cat c = (Cat)a;
    c.catchMouse();
}else{
    System.out.println("没有这个类型,无法转换.");
}

P132 多态的综合练习

根据需求完成代码:

  1. 定义狗类

属性:

年龄,颜色

行为:

eat(String something)(someth丨ng表示吃的东西)

看家lookHome方法(无参数)

  1. 定义猫类

属性:

年龄,颜色

行为:

eat(String something)方法(something表示吃的东西)

逮老鼠ScatchMouse方法(无参数)

  1. 定义Person类//饲荞员

属性:

姓名,年龄

行为:

keepPet(Dog dog,String something)方法

功能:隈养宠物狗,something表示喂荞的东西

行为:

keepPet(Cat cat,String something)方法

功能:喂荞茏物猫,something表示喂养的东西 生成空参有参构造,set和get方法

  1. 定义测试类(芫成以下打印效果):

keepPet(Dog dog,String somethind)方法打印内容如下:

年龄为30岁的老王养了一只黑颜色的2岁的狗 2岁的黑颜色的狗两只前腿死死的抱住骨头猛吃

keepPet(Cat cat,String someth丨nd)方法打印内容如下:

年龄为25岁的老李养了一只灰颜色的3岁的猫 3岁的灰顔色的猫,眯着眼睛侧着头吃鱼

  1. 思考:

1 .Dog和Cat都是Animal的子类,以上案例中针对不同的动物,定义了不同的keepPet方法,过于繁琐, 能否简化,并体会简化后的好处?

2.Dog和Cat虽然都是Animal的子类,但是都有其特有方法,能否想办法在keepPet中调用特有方法?

P133 包和final

包就是文件夹. 用来管理各种不同功能的Java类, 方便后期代码的维护.

包名的规则: 公司域名反写 + 包的作用, 需要全部英文小写, 见名知意. com.itheima.domain.Student

导包, 使用其它类的规则

  • 使用同一个包中的类时, 不需要导包

  • 使用java.lang包中的类时, 不需要导包

  • 其它情况都需要导包

  • 如果同时使用两个包中的同名类, 需要用全类名.

  • 全类名 = 包名 + 类名

final 关键字

可以修饰 方法, 类, 变量.

  • final修饰方法 : 表明该方法时最终方法, 不能被重写.
  • final修饰类 : 表明该类是最终类, 不能被继承.
  • final修饰变量 : 叫做常量, 只能被赋值一次.

常量

实际开发中, 常量一般作为系统的配置信息, 方便维护, 提高可读性.

常量的命名规范:

  • 单个单词 : 全部大写
  • 多个单词 : 全部大写, 单词之间用下划线隔开.

细节 :

  • final修饰的变量是基本类型 : 那么变量存储的数据值不能改变
  • final修饰的变量是引用类型 : 那么变量存储的地址值不能发生改变, 对象内部的可以改变.
  • 核心 : 常量记录的数据是不能改变的.

大小写转换 快捷键 CTRL + shift +U

P134 权限修饰符和代码块

  • private 只能本类用
  • 默认 只能本包用
  • protected 受保护的 , 不同包下的子类可以用
  • public 公共的 , 不同包下的子类/无关类都可以用

在实际开发中, 一般只用private和public

  • 成员变量私有
  • 方法公开

特例 : 如果方法中的代码是抽取其它方法中共性代码, 这个方法一般也私有.

代码块

一,局部代码块

二,构造代码块(已经不用了)

  1. 写在成员位置的代码块
  2. 作用 : 可以把多个构造方法中重复的代码抽取出来
  3. 执行时机 : 我们在创建本类对象的时候会先执行构造代码块在执行构造方法

三,静态代码块

格式 : static{}

执行时机 : 随着类的加载而加载 , 并且只执行一次.

应用场景 : 可以在程序开始时, 做一些数据初始化工作. 比如,在学生管理系统中事先添加一些用户信息, 以便用户登录.

P135 抽象类和抽象方法

  1. 抽象类的作用

    抽取共性时, 无法确定方法体, 就把方法定义为抽象的.

    强制让子类按照某种格式重写.

    抽象方法所在的类, 必须是抽象类

  2. 抽象类和抽象方法的格式

    public abstract 返回值类型 方法名 (参数列表)

    public abstract class 类名{}

  3. 继承抽象类要注意的

    要么重写抽象类中的所有抽象方法

    要么是抽象类

练习:

青蛙 frog 属性: name ,age 吃虫子,喝水

狗 dog ... 吃骨头,喝水

山羊 sheep ... 吃草 ,喝水

P 136 接口

接口的定义和使用

  • 接口用关键字interface来定义 public interface 接口名{}

  • 接口不能实例化

  • 接口和类之间是实现关系,通过implements关键字表示

    public class 类名 implements 接口名{}

  • 接口的子类(实现类)

​ 要么重写接口中的所有抽象方法

​ 要么是抽象类

注意1 : 接口和类的实现关系,可以单实现,也可以多实现。

​ public class 类名 implements 接口名 1 ,接口名2 {}

注意2 : 实现类还可以在继承一个类的同时实现多个接口。

​ public class 类名 extends 父类 implements 接口名 1 ,接口名2 {}

练习:

编写带有接口和抽象类的标准Javabean类

青蛙 名字,年龄 行为:吃虫子, 游泳

狗 ... 吃骨头, 狗刨

兔子 ... 吃胡萝卜

P137 接口的特点: 成员特点和各种关系

  • 成员变量

    只能是常量

    默认修饰符 : public static final

  • 构造方法

    没有

  • 成员方法

    只能是抽象方法

    默认修饰符 : public abstract

  • JDK7以前 : 接口中只能定义抽象方法.

接口和类之间的关系

  • 类和类的关系

继承关系,只能单继承,不能多继承,但是可以多层继承

  • 类和接口的关系

实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口

  • 接口和接口的关系

继承关系,可以单继承,也可以多继承

P138 接口和抽象类综合案例

乒乓球运动员:姓名,年龄,学打乒乓球,说英语

篮球运动员:姓名,年龄,学打篮球

乒乓球教练:姓名,年龄,教打乒乓球,说英语

篮球教练: 姓名,年龄,教打篮球

sporter(运动员) coach(教练员)

P139 多学3招

JDK8以后接口中新增的方法, 有方法体的方法

  • 允许在接口中定义默认方法,需要使用关键字default修饰

作用:解决接口升级的问题

接口中默认方法的定义格式:

  • 格式:public default 返回值类型方法名(参数列表)

  • 范例:public default void show()

接口中默认方法的注意事项:

  • 默认方法不是抽象方法,所以不强制被重写。但是如果被重写,重写的时候去掉default关键字

  • public可以省略,default不能省略

  • 如果实现了多个接口,多个接口中存在相同名字的默认方法,子类就必须对该方法进行重写

JDK8以后接口中新增的方法,静态方法

  • 允许在接口中定义定义静态方法,需要用static修饰

    接口中静态方法的定义格式:

  • 格式:public static返回值类型方法名(参数列表)

  • 范例:public static void show()

接口中静态方法的注意事项:

  • 静态方法只能通过接口名调用,不能通过实现类名或者对象名调用-
  • public可以省略,static不能省略

接口的应用

  1. 接口代表规则,是行为的抽象。想要让哪个类拥有一 个行为,就让这个类实现对应的接口就可以了。

  2. 当一个方法的参数是接口时,可以传递接口所有实现 类的对象,这种方式称之为接口多态。

适配器设计模式(Design pattern)

简单理解 : 设计模式就是解决问题的套路.

适配器设计模式 : 解决接口与接口实现类之间的矛盾问题.

  1. 当一个接口中抽象方法过多,但是我只要使用其中一部分的 时候,就可以适配器设计模式

  2. 书写步骤:编写中间类XXXAdapter,实现对应的接口

    对接口中的抽象方法进行空实现

    让真正的实现类继承中间类,并重写需要用的方法

    为了免其他类创建适配器类的对象,中间的适配器类

    用abstract进行修饰

P140 初识内部类

  1. 什么是内部类?

​ 写在一个类里面的类就叫做内部类

  1. 什么时候用到内部类?

​ B类表示的事物是A类的一部分,且B单独存在没有意义。 比如:汽车的发动 机,ArrayUst的迭代器,人的心脏等等

P141 成员内部类

成员内部类如何书写

  • 写在成员位置的, 属于外部类的成员.
  • 可以被一些修饰符所修饰, 比如 : private , 默认, protected , public ,static等

如何创建成员内部类的对象

方式1 : 在外部类中编写方法, 对外提供内部类的对象.

//在外部类中编写getInstance方法获取内部类对象
Inner getInstance(){
    return new Inner();
}
//创建外部类对象,调用方法
Outer o = new Outer();
//如果内部类是私有的,就用父类去接收(多态)
Object inner = o.getInstance();
//或者直接输出
o.getInstance().sout
//如果不想CTRL+alt+v用变量接收而直接打印,就在后边 " .sout"就可以.

方式2 : 直接创建, 格式: 外部类名 . 内部类名 对象名 = 外部类对象 . 内部类对象;

//格式: 外部类名 . 内部类名  对象名 = 外部类对象 . 内部类对象;
Outer.Inner oi = new Outer().new Inner();

小建议 : 给变量起名字时不要去用$和_, $是给内部类使用的, _是给常量使用的.

​ 在File菜单中的Project Structure中选Project可以选择编译的JDK版本.

思考题: 分别输出不同位置的a

public class Outer {
    //外部类成员
    private int a = 10;
    class Inner{
        //内部类成员
        private int a = 20;
        void method(){
            //内部类方法中,局部变量
            int a = 30;
            System.out.println(a);//30
            System.out.println(this.a);//20
            //Outer.this就是获取了外部类的地址值
            System.out.println(Outer.this.a);//10
        }
    }
}
///////////////////////////////
public class test {
    public static void main(String[] args) {
        //创建内部类对象
        Outer.Inner oi = new Outer().new Inner();
        //调用方法
        oi.method();
    }
}

在程序运行加载到内存时, 内部类和外部类分别加载为两个字节码文件: Outer.class和Outer$Inner.class.

获取外部类的地址值 : 外部类名. this. 例如:Outer.this.a就能调用外部类的成员变量a了.

P142 静态内部类和局部内部类

  1. 什么是静态内部类?

​ 静态内部类是一种特殊的成员内部类。(用static修饰的内部类)

  1. 直接创建静态内部类对象的方式?

​ Outer.lnner oi = new Outer.lnner();

  1. 如何调用静态内部类中的方法?

​ 非静态方法:先创建对象,用对象调用

​ 静态方法:外部类名.内部类名.方法名();

局部内部类

  1. 将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量。

  2. 外界是无法直接使用,需要在方法内部创建对象并使用。

  3. 该类可以直接问外部类的成员,也可以访问方法内的局部变量。

P143 匿名内部类

  1. 什么是匿名内部类?

​ 隐藏了名字的内部类,可以写在成员位置,也可以写在局部位置。

  1. 匿名内部类的格式?
  2. 格式的细节

​ 包含了继承或实现,方法重写,创建对象。

整体就是一个类的子类对象或者接口的实现类对象

  1. 使用场景

当方法的参数是接口或者类时,

以接口为例,可以传递这个接口的实现类对象,

如果实现类只要使用一次,就可以用匿名内部类简化代码。