Java语言学习day 07 - 面向对象02(继承和关键字)

1.面向对象

1.1 this关键字

  • this定义: 当代码中局部变量和成员变量同名时, 此时调用方法中的变量根据就近原则.
  • 解决: 为了避免局部变量和成员变量同名时, 产生的歧义性, 我们使用this关键字去直接访问成员变量.
  • 使用构造器和使用setter方法区别

​ 构造器: 在创建对象的时候设置初始数据, 只能初始化一次.

​ setter方法: 创建对象后再设置初始数据可以设置多次.

1.2 继承

1.2.1 继承的概念
  • 继承定义: 如果一个类需要继承另一个类, 此时使用extends关键字
  • 继承语法
public class 子类名 extends 父类名{
}
  • 继承概念: 被继承的类, 叫父类或者基类.

​ 继承父类的类, 叫子类或者拓展类.

​ 父类: 存放多个子类公共的字段和方法.

​ 子类: 存放自己特有的字段和方法.

  • 注意: Java中的类只支持单继承, 但是支持多重继承(不是多继承).

​ 一个父类可以有多个子类.

  • Object 类是Java语言的根类, 任何类都是Object的子类, 要么是直接子类, 要么是间接子类.
1.2.2 判断子类可以继承什么

子类继承父类之后, 可以拥有到父类的某一些成员( 字段和方法 ), 根据访问修饰符来判断:

  • 如果父类中的成员使用public和protected修饰, 子类都能继承.

  • 如果父类和子类在同一个包中, 使用缺省访问修饰的成员, 此时子类可以继承到.

  • 如果父类中的成员使用private修饰, 子类继承不到. private只能在本类中访问.

  • 父类的构造器, 子类也不能继承, 因为构造器必须和当前的类名相同.

1.3 方法覆盖

当子类存在一个和父类一摸一样的方法的时候, 我们就说子类覆盖了父类的方法, 也叫重写.

//父类鸟
public class Bird {
    //鸟会飞的方法
    public void fly() {
        System.out.println("飞");
    }
}
//子类鸵鸟
public class Ostrich extends Bird {
    public void fly(){
        System.out.println("不会飞");
    }
}
//需求:演示方法覆盖
public class OverrideDemo {
    /*
    父类鸟类(Bird),鸟类中含有飞翔(fly)行为
    鸟的子类鸵鸟类(Ostrich),子类中覆盖父类飞翔(fly)方法
     */
    public static void main(String[] args){
        Ostrich o = new Ostrich();
        o.fly();
    }
}
  • 方法调用的顺序: 在子类先找有没有对应的方法, 没有就执行父类的, 子类有就执行子类的, 都没有就报错.
  • 方法覆盖的细节:

private修饰的方法不能被子类继承, 也就没有覆盖.

  1. 实例方法签名必须相同 (方法签名= 方法名 + 方法的参数列表).

  2. 子类方法的返回值类型是和父类方法的返回类型相同或者是其子类.

  3. 子类方法中声明抛出的异常小于或等于父类方法声明抛出异常类型.

  4. 子类方法的访问权限比父类方法访问权限更大或相等.

总结:以上4点不明白就直接拷贝父类中方法的定义粘贴到子类中,再重新编写子类方法体.

1.4 super关键字

super作用: 当子类的方法覆盖了父类的方法, 我们再想子类去调用父类方法时, 就要使用super.方法名().

//子类鸵鸟
public class Ostrich extends Bird {
    public void fly(){
        System.out.println("不会飞");
    }
    public void say(){
        fly();
        super.fly();
    }
}

1.5 抽象方法和抽象类

用抽象修饰的方法具备两个特征:

  • 该方法没有方法体.

  • 要求子类必须覆盖该方法.

使用abstract修饰的方法,称为抽象方法.

public abstract 返回类型 方法名(参数);

特点:

  • 使用abstract修饰,没有方法体,留给子类去覆盖.

  • 抽象方法必须定义在抽象类或接口中.

使用abstract修饰的类,成为抽象类.

public abstract class 类名{
}

一般的,抽象类以Abstract作为类名前缀, 一看就能看出是抽象类.

特点:

  • 抽象类不能创建对象, 调用没有方法体的抽象方法没有任何意义.

  • 抽象类中可以同时拥有抽象方法和普通方法.

  • 抽象类要有子类才有意义, 子类必须覆盖父类的抽象方法, 否则子类也得作为抽象类.

//表示求形状面积的抽象类,里面包含求面积的抽象方法,其他子类必须覆盖此方法
public abstract class AbstractGraph {
    public abstract double getArea();
}

1.6 Object类和常用方法

Object本身是表示对象的意思, 是Java中的根类, 要么是一个类的直接父类, 要么就是间接父类.

class  A{}   其实等价于  class  A extends Object{}

因为所有类都是Object类的子类, 所以类的所有对象都可以调用Object类中的方法.

1.6.1 equals方法

在Object类中的equals方法和"==" 符号是相同的都是比较对象是否在同一个存储地址.

实际开发中: 我们通常是比较两个对象中的成员变量的值是否相等, 来判断两个对象是否相同

官方建议:每个类都应该覆盖equals方法去比较我们关心的数据,而不是内存地址。

1.6.2 toString方法

表示把对象中的字段信息转换为字符串格式

默认情况下打印的是对象的hashCode值, 但是我们更关心对象中字段存储的数据.

官方建议: 应该每个类都应该覆盖toString返回我们关心的数据.

public class Person {
    protected String name;
    protected int age;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public Person() {
    }

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

    public boolean equals(Object o) {
        return true;
    }

    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
//需求:演示Object类中的toString和equals方法
public class ObjectDemo {
    //- 创建一个Person类,通过覆盖toString方法,打印Person对象的内容
    //
    //- 使用==和equals比较两个Person对象,通过结果得到==和equals的区别
    public static void main(String[] args){
        Person p = new Person();
        p.setName("周");
        p.setAge(17);

        Person p1 = new Person();
        p1.setName("周");
        p1.setAge(17);

        boolean result1 = p == p1;
        boolean result2 = p.equals(p1);
        System.out.println(result1);//地址不同false
        System.out.println(result2);//值相同true

        //官方toString输出:com.day02.demo.objectdemo.Person@2133c8f8
        //在Person覆盖官方的toString方法
        //Person{name='周', age=17}
        System.out.println(p1.toString());
        //实际开发中使用,因为println方法会去调用传递参数的toString方法
        System.out.println(p1);
    }
}

拓展:

== 符号到底比较的是什么:

  • 比较基本数据类型: 比较两个值是否相等

  • 比较对象数据类型: 比较两个对象是否是同一块内存空间(地址是否相同).

每一次使用new关键字, 都表示在堆中创建一块新的内存空间.

2.总结

2.1 this关键字的作用

当类中的成员变量和形式参数的名字一样时, 为了避免歧义性(就近原则), 我们使用this可以直接指向成员变量.

2.2 为成员变量设置值, 构造器和setter方法的选择

构造器: 构造器可以一边创建对象一边赋值, 但是只能赋值一次.

setter方法: 创建对象后再赋值, 可以设置多次.

2.3 为什么需要继承?

当多个类中的成员变量, 成员方法(存在相同代码),都是一样的时候, 为了简化代码我们可以使用继承.

2.4 Java中的继承语法

语法: public class 子类名 extends 父类名{}

2.5 子类能从父类中继承到哪些成员?

使用public和protected修饰子类都可以继承, 当父类子类在同一个包中, 没有使用修饰符的也可以继承.

2.6 子类什么时候需要覆盖父类中的方法?

当父类的方法不符合子类的信息的时候我们应该使用覆盖.

2.7 super关键字的作用

super: 当子类覆盖了父类的方法时, 我们还想去调用父类的方法就要使用super.方法名.

2.8 什么时候需要把父类中的方法定义成抽象方法?

当父类的方法没有什么实际意义(不需要方法体), 而子类都必须覆盖该方法的时候.

2.9 抽象类应该怎么使用?可以直接使用抽象类创建对象吗?

抽象类: 抽象类的命名应该带有abstract, 让人知名见意, 抽象类必须有抽象方法, 子类必须覆盖父类的抽象方法.

不可以直接使用抽象类创建对象.

2.10 Object中的toString()的作用?实际开发中如何使用?

toString: Object类的toString()方法默认返回该对象实现类的“类名+@+hashcode”值.

实际开发: 在实际开发中我们需要自定义toString(), 让对象中的字段信息转换为我们想要的字符串格式

2.11 Object中的equals()和==的区别?实际开发中如何使用?

相同: 在比较对象时Object中的equals( )和==都是比较地址是否相同

不同: ==可以用来比较基本数据类型的值是否相等, equals( )不行.

实际开发: 我们需要自定义equals( ) 方法, 用equals来比较对象中的值是否相等

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值