java 继承 学习笔记

继承

一、面向对象继承性

public class ObjectDemo {
    public static void main(String[] args) {
        Student stu = new Student();
        stu.setAge(14);
        stu.setName("孙笑川");
        stu.tell();
    }
}
class Person{
    private String name;
    private int age;

    public void setName(String name){
        this.name = name;
    }

    public void setAge(int age){
        this.age = age;
    }

    public void tell(){
        System.out.println("姓名: "+this.name+"、 年龄: "+this.age);
    }
}

class Student extends Person{
}

1. 在子类中扩展方法

public class ObjectDemo {
    public static void main(String[] args) {
        Student stu = new Student();
        stu.setSchool("平津军官学校");
        stu.setAge(14);
        stu.setName("孙笑川");
        
        stu.tell();
        stu.getSchool();
    }
}
class Person{
    private String name;
    private int age;

    public void setName(String name){
        this.name = name;
    }

    public void setAge(int age){
        this.age = age;
    }

    public void tell(){
        System.out.println("姓名: "+this.name+"、 年龄: "+this.age);
    }
}

class Student extends Person{
    private String school;// 扩充方法
    public void setSchool(String s){
        this.school = s;
    }
    public void getSchool(){
        System.out.println("school is "+ this.school);
    }
}

2. 子类对象实例化对象

public class ObjectDemo {
    public static void main(String[] args) {
        Student stu = new Student("孙笑川", 14, "平津大学");
        stu.tell();
        stu.getSchool();
    }
}
class Person{
    private String name;
    private int age;

    public Person(String name, int age){
        this.name = name;
        this.age = age;
    }

    public void setName(String name){
        this.name = name;
    }

    public void setAge(int age){
        this.age = age;
    }

    public void tell(){
        System.out.println("姓名: "+this.name+"、 年龄: "+this.age);
    }
}

class Student extends Person{
    private String school;
    public Student(String name, int age, String school){
        super(name, age); // 调用父类构造方法
        this.school = school;
    }

    public void getSchool(){
        System.out.println("school is "+ this.school);
    }
}

3. 继承限制

1. 单继承

多层继承:继承层次不要过多

2. 非私有操作

不允许直接访问非私有操作

public class ObjectDemo {
    public static void main(String[] args) {
        Student stu = new Student("孙笑川");
        System.out.println(stu.getInfo());
    }
}
class Person{
    private String name;

    public void setName(String name){
        this.name = name;
    }

    public String getName(){
        return this.name;
    }
}

class Student extends Person{
    private String school;
    public Student(String name){
        setName(name);
    }

    public String getInfo(){
        return "姓名: "+ getName();
    }
}

本程序中Person父类定义的name属性虽然可以被子类继承使用,但是由于private定义,所以在子类中无法直接访问私有属性访问,只能通过getter方法访问,所以该属性属于隐式继承

二、覆写

子类可能会和父类定义名称相同的方法和属性,此时情况被称为覆写

1. 覆写定义

public class ObjectDemo {
    public static void main(String[] args) {
        Student stu = new Student("孙笑川");
        System.out.println(stu.getInfo());
        Person per = new Person();
        per.printInfo();
        stu.printInfo();
    }
}
class Person{
    private String name;

    public void setName(String name){
        this.name = name;
    }
    public void printInfo(){//父类方法
        System.out.println("笑川桑,你还在吗?");
    }
    public String getName(){
        return this.name;
    }
}

class Student extends Person{
    private String school;
    public Student(String name){
        setName(name);
    }
    public void printInfo(){// 覆写方法
        System.out.println("平津原来是没有雪的");
    }

    public String getInfo(){
        return "姓名: "+ getName();
    }
}

使用super调用父类未覆写方法,使用this调用子类覆写方法

public class ObjectDemo {
    public static void main(String[] args) {
        Student stu = new Student("孙笑川");
        stu.getInfo();
    }
}
class Person{
    private String name;

    public void setName(String name){
        this.name = name;
    }
    public String printInfo(){
        return "笑川桑,你还在吗?";
    }
    public String getName(){
        return this.name;
    }
}

class Student extends Person{
    private String school;
    public Student(String name){
        setName(name);
    }
    public String printInfo(){
        return "平津原来是没有雪的";
    }

    public void getInfo(){
        System.out.println("姓名: "+ getName());
        System.out.println("父类方法: "+ super.printInfo());// 为覆写的父类方法
        System.out.println("子类方法: " + this.printInfo());// 为子类已经覆写的方法
    }
}

2. 方法覆写限制

核心问题:被子类所覆写的方法不能拥有比父类更严格的访问控制权限,也就是父类方法是public,子类覆写方法不能是default

No.区别重载覆写
1英文OverloadingOverriding
2定义方法名称相同,参数的类型和个数不同,返回值按标准要一致,也可以不一致,会强制进行转换方法名称、参数的类型及个数、返回值类型完全相同
3权限没有权限要求被子类覆写的方法的访问控制权限不能比父类方法更严格
4范围发生在一个类中发生在继承关系类中

3. 属性覆盖

子类除了可以对父类进行覆写外,也可以对非private定义的父类属性进行覆盖,至于要定义相同的名称就行

public class ObjectDemo {
    public static void main(String[] args) {
        Student stu = new Student();
        stu.getInfo();
    }
}
class Person {
    String info = "23124"; // 父类属性
}
class Student extends Person{
    int info = 123;// 子类覆写属性
    public void getInfo(){
        System.out.println("child info is "+this.info+ "、parent info is "+ super.info);
    }
}

三、final 关键字

实现以下功能:

  1. 定义不能够被继承的类

final class Channel{}该类不能被继承

  1. 定义不能够覆写的方法
public class ObjectDemo {
    public static void main(String[] args) {
        Student stu = new Student();
        stu.getInfo();
    }
}
class Person {
    public final void getInfo(){// 无法被覆写
        System.out.println("父类方法");
    }
}
class Student extends Person{
    public void getInfo(){// IDE 中会报错
        System.out.println("child info is "+this.info+ "、parent info is "+ super.info);
    }
}
  1. 定义常量(全局常量)

final int ON = 1

定义全局常量,无法被更改

四、Annotation 注解

1. 准确覆写 Override

用在子类覆写父类方法使用了Override注解,就可以直接分别出哪些是覆写方法,哪些是子类扩充方法。同时利用@Override 注解也可以在编译时检测出因为子类拼写错误所造的方法覆写错误

public class ObjectDemo {
    public static void main(String[] args) {
        Student stu = new Student();
        stu.getInfo();
    }
}
class Person {
    String info = "23124";
    public void getInfo(){
        System.out.println("父类方法");
    }
}
class Student extends Person{
    int info = 123;
    // 注释
    @Override
    public void getInfo(){
        System.out.println("child info is "+this.info+ "、parent info is "+ super.info);
    }
}
2. 过期声明

程序开发是迭代进行的,因此有些不推荐使用的结构,所以就有针对此的注释 @Deprecated

public class ObjectDemo {
    public static void main(String[] args) {
        Student stu = new Student();
        stu.getInfo();
        stu.getInfo1();// 函数名称上会出现删除线
    }
}
class Person {
    String info = "23124";
    public void getInfo(){
        System.out.println("父类方法");
    }
    @Deprecated
    public void getInfo1(){
        System.out.println("aenfasef");
    }
}
class Student extends Person{
    int info = 123;
    @Override
    public void getInfo(){
        System.out.println("child info is "+this.info+ "、parent info is "+ super.info);
    }
}
3. 压制警告

@SuppressWarning(value = {“deprecation”}):可以去除使用@Deprecated注释的函数体发生的Warning

五、面向对象多态性

展现形式1:

  1. 方法重载
  2. 方法覆写

展现形式2:

1. 对象向上转型

父类 父类实例 = 子类实例,自动完成转换

public class ObjectDemo {
    public static void main(String[] args) {
        Person person = new Person();
        person.tell();
        Person person1 = new Student();// 向上转型
        person1.tell();
        Person person2 = new Worker();
        person2.tell();
    }
}
class Person {
    public void tell(){
        System.out.println("人来了!");
    }
}
class Student extends Person{
    public void tell(){
        System.out.println("学生来了!");
    }
}
class Worker extends Person{
    public void tell(){
        System.out.println("工人来了!");
    }
}

统一方法参数

public class ObjectDemo {
    public static void main(String[] args) {
        Home.tell(new Student()); //不同的实例化对象,但都是一个Person类型
        Home.tell(new Worker());
    }
}
class Person {
    public void tell(){
        System.out.println("人来了!");
    }
}
class Student extends Person{
    public void tell(){
        System.out.println("学生来了!");
    }
}
class Worker extends Person{
    public void tell(){
        System.out.println("工人来了!");
    }
}
class Home{
    public static void tell(Person per){
        per.tell();
    }
}
2. 对象向下转型

子类 子类实例 = (子类)父类实例,强制完成转换

public class ObjectDemo {
    public static void main(String[] args) {
        Person per = new Superman(); //先向上转型
        per.run();
        Superman sup = (Superman) per;// 再向下强制转型
        sup.fly();
    }
}
class Person {
    public void run(){
        System.out.println("跑步!");
    }
}
class Superman extends Person{
    public void fly(){
        System.out.println("我会飞翔!");
    }
}
4. instanceof 关键字

对象的向下转型有安全隐含,为了保证安全性,可以在转换前通过instanceof队对象所属类型进行判断,语法如下

对象 instanceof 类

返回一个boolean类型的数据

public class ObjectDemo {
    public static void main(String[] args) {
        Person per1 = new Person();
        Person per2 = new Superman();

        System.out.println(per1 instanceof Person);
        System.out.println(per1 instanceof Superman); //判断对象所属类型false,未建立联系
        System.out.println(per2 instanceof Person);
        System.out.println(per2 instanceof Superman);
        per2.run();
        Superman spm1 = (Superman) per1;// 发生ClassCastException
        spm1.fly();
        Superman spm2 = (Superman) per2; //向下转型
        spm2.fly();
    }
}
class Person {
    public void run(){
        System.out.println("跑步!");
    }
}
class Superman extends Person{
    public void fly(){
        System.out.println("我会飞翔!");
    }
}

进行安全的向下转型

public class ObjectDemo {
    public static void main(String[] args) {
        Person per = new Superman();
        if (per instanceof Superman){ // 先判断对象所属类型,再向下转型
            Superman spm = (Superman) per;
            spm.fly();
        } else {
            System.out.println("错误");
        }
    }
}
class Person {
    public void run(){
        System.out.println("跑步!");
    }
}
class Superman extends Person{
    public void fly(){
        System.out.println("我会飞翔!");
    }
}

六、Object类

Object是所有类的父类,所有利用class关键字定义的类全部默认继承自Object类

class Person{}class Person extends Object{}是相同的

public class ObjectDemo {
    public static void main(String[] args) {
        Object per = new Superman();// 可以直接向上转型到爷爷类
        if (per instanceof Superman){
            Superman spm = (Superman) per;// 向下转型到孙子类
            spm.fly();
        } else {
            System.out.println("错误");
        }
    }
}
class Person {
    public void run(){
        System.out.println("跑步!");
    }
}
class Superman extends Person{
    public void fly(){
        System.out.println("我会飞翔!");
    }
}

Object可以接受所有的引用数据类型

1. 获取对象信息

Object提供了toString方法,打印对象信息

public class ObjectDemo {
    public static void main(String[] args) {
        Person per = new Person("孙笑川", 18);
        System.out.println(per.toString());
    }
}
class Person {
    private String name;
    private int age;

    public Person(String name, int age){
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString(){
        return "姓名:" + this.name + "、年龄:" + this.age;
    }
}

Object.toString方法的默认实现

public String toString(){
        return getClass().getName()+"@"+Integer.toHexString(hashCode());
}
2. 对象比较

Object类中的equals方法是基于对象是否相同来建立的,主要是判断两个对象的地址是否相同,”对象.equals(对象)“ 效果等同“对象 == 对象“

String类中覆写了equals方法public boolean equals(Object obj)

覆写equals方法

public class ObjectDemo{
    public static void main(String[] args) {
        Person per1 = new Person("孙笑川",18);
        Person per2 = new Person("孙笑川",18);
        System.out.println(per1.equals(per2));
    }
}
class Person extends Object{
    private String name;
    private int age;

    public Person(String name, int age){
        this.name = name;
        this.age = age;
    }
    // 覆写的目的是为了判断new的两个对象是否创建的是同一人
    public boolean equals(Object obj){
        if (!(obj instanceof Person)){//判断是否为Person类
            return false;
        }
        if (obj == null){// 判断目标是否为空
            return false;
        }
        if (this == obj){// 判断地址是否相同,地址相同则认为是同一个对象
            return true;
        }
        Person per = (Person) obj;
        return this.name.equals(per.name) && this.age == per.age;// 然后判断对象的属性是否相同
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值