一、封装 1. 概述

定义:将类的某些信息隐藏在类的内部,不允许外部程序直接访问。只能通过该类提供的 特定的方法 来实现对隐藏信息的操作和访问,也就是: 要隐藏对象的信息 同时也要留出访问的接口 2. 封装的特点

隐藏类的实现细节,实现了信息的隐藏及安全性,方便修改和实现 提高了程序的模块化,提高系统独立性和软件的可重用性,且易于维护 具体实现是编写该类的人控制的,让使用者只能通过事先定制好的 方法 来访问数据,实现者可以方便地加入控制逻辑,限制对属性的不合理操作 3. 封装的实现

变量:使用 private 修饰,这就是变量的封装 方法:也是一种封装,封装了多条代码 类: 也是一种封装,封装了多个方法 封装的实现步骤:

封装的实现

public class Cat {
    //成员属性:
    //修改属性可见性---private 限定只能在当前类内访问,只能修饰成员变量
    private String name;
    public Cat() {
    }
    //创建get/set方法
    //在get/set方法当中添加属性的限定
    public void setName(String name) {  //set方法一般没有返回值
        this.name = name;
    }
    public String getName() { 
        return "我是一只名叫"+this.name+"的猫咪";
    }
    public int getMonth() {
        return month;
    }
    public void setMonth(int month) {   //对年龄进行限定
        if(month<=0)//对属性的限定信息
            System.out.println("输入信息错误,宠物猫的年龄必须大于0");
        else
            this.month = month;
    }
}

二、 继承 1. 概述

一种类于类之间的关系,使用已存在的类作为基础建立新类。 使用已存在的类的定义作为基础创建新类 新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但 不能选择性地继承父类必须继承父类 所有开放的特征 使用 extends 关键字实现 2. 继承的逻辑关系

不能为了继承某个功能而随意进行继承操作,必须要符合 “A is a B” 关系 3. 继承的特点:

子类会自动拥有父类所有 非 private 修饰的属性和方法 通过 子类对象 既可以调用自身的 非 private 修饰的成员,也可以调用父类的 非 private 修饰的成员 **父类 不可以 访问子类 特有成员,**即使是共有的 继承的出现提高了代码的复用性,提高软件开发效率。 继承的出现让类与类之间产生了关系,提供了多态的前提 4. 继承的注意事项:

在Java中,类只支持单继承,不允许多继承,一个类只能有一个直接父类 多个类可以继承一个父类: class B extends A{} class C extends A{} // 类B和类C都可以继承类A 在Java中,多层继承 是可以的,即一个类的父类可以再去继承另外的父类 class A{} class B extends A{} // 类B继承类A,类B是类A的子类 class C extends B{} // 类C继承类B,类C是类B的子类,同时也是类A的子类 (类的继承具有传递性) 在Java中,子类和父类是一种相对概念,一个类是某个类父类的同时,也可以是另一个类的子类 5. 继承后子类父类成员变量的特点

子类的对象调用成员变量的时候,子类自己有,使用子类子类自己没有则调用父类 子父类中出现了 同名 的成员变量时,在子类中需要访问父类中非私有成员变量时,需要使用** super 关键字** 6. 继承后子类父类成员方法的特性

子类的对象调用方法的时候,子类自己有,使用子类,子类自己没有调用的父类 子类中出现与父类一模一样的方法时,会出现覆盖操作,也称为 override 重写、复写或者覆盖 7. 继承的初始化顺序

父类中有:静态代码块,构造代码块,无参构造方法,静态属性。 子类中有:静态属性,静态代码块,构造代码块,无参构造方法 执行顺序:

  1. 父类的静态代码块

  2. 子类的静态代码块

  3. 父类的构造代码块

  4. 父类的无参构造方法

  5. 子类的构造代码块

  6. 子类的无参构造方法

  7. 方法重载和方法覆盖

方法重载:

  1. 同一个类中
  2. 方法名:重载的两个方法的方法名必须相同
  3. 参数列表: 不同,三者至少满足一个(参数顺序、个数、类型),三者至少满足一个
  4. 重载与返回值类型、权限修饰符 无关
  5. 与方法的参数名 无关 方法覆盖
  6. 有继承关系的 子类 中, 子类覆盖父类的方法
  7. 方法名:子类方法和父类方法 必须相同,
  8. 参数列表:子类方法和父类方法的形参列表 必须相同
  9. 访问修饰符:子类方法的权限 >= 父类的方法的权限(不能比父类更严格)
  10. 返回值类型:(父类的返回值类型的子类)
  • 基本数据类型: 必须相同
  • 引用数据类型:相同 或者 子类方法的返回值类型是父类方法的返回值类型的 子类 注意: 当子类重写父类方法后,子类对象调用的是 覆盖后 的方法。 属性名也是一样的道理,没有重名之前,调用的是父类的,重名之后用的是子类的 被 final 修饰的方法不允许在子类中覆盖 父类被覆盖的方法的参数列表中被声明为 final 的参数,在子类的覆盖方法的中可以不必指定为 final 子类覆盖方法声明的 异常列表中的异常类 必须与父类被覆盖方法声明的异常列表中的异常类 兼容 只有在 子类类体中可以访问 的父类或祖先类的方法才能被覆盖 静态方法 不能被覆盖,只能被隐藏 如果通过子类对象访问父类方法,在 父类类体 中,访问到的任然是子类中的覆盖方法

三、 多态

  1. 概述 定义:多种形态,是面向对象语言最核心特征,封装和继承都是为多态准备的,非常重要 Java中多态的 代码体现 在一个子类对象(实现类对象)既可以给这个子类(实现类对象)引用变量赋值,又可以给这个子类(实现类对象)的父类(接口)变量赋值。 最终多态体现为 父类引用变量可以指向子类对象 如 Student 类可以为 Person 类的子类。那么一个S tudent 对象既可以赋值给一个 Student 类型的引用,也可以赋值给一个 Person 类型的引用。 多态的分类: Java中的多态一般是运行时多态 编译时多态:设计时多态,方法重载来实现 运行时多态:程序运行时动态决定调用哪个方法 多态的前提:必须有 子父类关系 或者类 实现接口关系,否则无法完成多态。 多态的优点: 提高代码的可维护行 提高代码的扩展性 多态的弊端:不能使用子类的特有功能 如何解决? 法1:创建子类对象调用子类方法 法2:把父类的引用强转为子类引用

  2. 多态调用的三种格式

父类的引用变量指向子类对象:父类类型 变量名 = new 子类类型(); 普通类多态定义的格式:父类 变量名 = new 子类(); 抽象类多态定义格式:抽象类 变量名 = new 抽象类子类(); 接口多态定义的格式:接口 变量名 = new 接口实现类();

  1. 注意事项:

同一个父类的方法会被不同的子类重写。在调用方法时,调用的为各个 子类覆盖后的方法 Person p1 = new Student(); Person p2 = new Teacher(); p1.work(); //p1会调用Student类中重写的work方法 p2.work(); //p2会调用Teacher类中重写的work方法 当变量名指向不同的子类对象时,由于每个子类覆盖父类方法的内容不同,所以会调用不同的方法。 4. 多态中成员访问的特点

成员变量 编译看左边(引用变量的声明类型),运行看左边(实际访问到的成员变量的值,也是由引用变量的声明类型来决定) 方法 编译看左边(引用变量的声明类型),运行看右边(实际访问到的方法,是由引用变量所指向的对象的实际类型来决定) 5. 编译时多态(方法重载 overload)

因为对于方法重载而言,虽然多个方法的方法名相同,但是我们的编译器,可以根据方法调用代码推断出,所要调用的那个方法的方法签名,从而根据方法签名(jvm唯一的),确定要调用的方法 注:方法签名: 方法名+方法参数列表**

  1. 运行时多态

因为在编译器编译的时候,无法知道,具体调用的是哪个方法的代码,只有当 jvm 具体真正执行到调用代码的地方,jvm才能知道调用的究竟是哪个方法 实现运行时多态:继承、方法覆盖/重写(override)、父类引用指向子类对象 7. 多态的转型

向上转型:当有 子类对象赋值给一个父类引用 时,便是向上转型**,多态本身就是向上转型的过程。(也叫:隐式转型、自动转型) 格式:父类类型 变量名 = new 子类类型(); 向下转型:一个 已经向上转型 的子类对象可以使用 强制类型转换 的格式,将父类引用转为子类引用,这个过程是向下转型。如果是直接创建父类对象,是无法向下转型的! 格式:子类类型 变量名 = (子类类型) 父类类型的变量; 什么时候使用向上转型? 当不需要面对子类类型时,通过提高扩展性,或者使用父类的功能就能完成相应的操作,**这时就可以使用向上转型。 什么时候使用向下转型? 当要使用子类特有功能时,就需要使用向下转型。 向下转型的好处:可以使用子类特有功能。 但是弊端是需要面对具体的子类对象;在向下转型时容易发生 ClassCastException 类型转换异常。在转换之前必须做 类型判断 如: if( !a instanceof Dog){…}

  1. instanceof 关键字

作用: 可以通过 instanceof 关键字来判断是否能够对象转化。也就是,一个引用型的变量,是不是这个类型的对象,提高向下转型的安全性 格式: boolean b = **对象 instanceof 数据类型; **,返回 true / false 注意:null instanceof <类名> 结果永远是 false Person p1 = new Student(); // 前提条件,学生类已经继承了人类 boolean flag = p1 instanceof Student; //flag结果为true boolean flag2 = p2 instanceof Teacher; //flag结果为false