2022-07-20 第五小组 顾祥全 学习笔记 day13-JavaSE-面向对象-继承

本文深入探讨了面向对象编程中的继承概念,包括其作用、特点以及何时使用。讲解了Java中单继承的特性,并通过实例展示了方法重写和方法重载的区别。同时,讨论了equals()和toString()方法的重写实践,以及this与super关键字的使用场景。最后,分析了构造方法中的隐含操作,强调了对象初始化过程中的细节。
摘要由CSDN通过智能技术生成

面向对象-继承

1. 继承有什么作用

基本作用:子类继承父类,代码得到复用
主要作用:继承是方法覆盖的重写和多态机制的前提(有了继承关系才有后来的方法覆盖重写和多态机制)

2. 继承的特点

  1. 若A继承B,我们称B为父类(基类、超类),称A为子类(派生类)。
  2. 在Java中只支持单继承,这也是体现java简单性的一点。
  3. 虽然Java不支持多继承,但可以实现间接继承(A–>B–>C)。
  4. 子类可以拥有父类“特征”,子类也可以拥有自己的“特征”。
  5. 如果一个类没有编写继承关系,那么这个类默认继承Object(是祖宗类,也就是说所有的类的实例都有Objec类t的特征)。
  6. 继承也有缺点:在两个类实现继承关系后,会导致代码耦合度提高(若父类修改内容,会导致子类收到影响)

3. 什么条件下可以使用继承?

凡是能用“is a“(类与类之间的关系)能描述的类,都可以使用继承
  Cat is Animal -----> class Cat extends Animal
  Dog is Animal -----> class Dog extends Animal
  Monkey is Animal -----> class Monkey extends Animal

is a
is a
is a
Animal
Cat
Dog
Monkey

4. 方法的覆盖(重写)

方法重写与方法重载区别

方法重载
  • 什么时候会考虑使用方法重载?

    在一个类中,如果方法的功能相似,建议将取相同的名字,这样代码美观、便于编程

  • 什么条件满足后会构成方法重载?

    1. 前提:在同一个类中
    2. 方法名相同
    3. 参数列表不同(参数的个数,参数的类型,参数类型的顺序)
    4. 方法重载于修饰符列表和返回值无关
方法重写
  • 什么时候会考虑使用方法重写?
    当子类从父类继承过来的方法无法满足当前子类的业务需求时,子类有权利对这个方法进行重新编写

  • 什么条件满足后会构成方法重写?

    1. 前提:在继承关系中
    2. 方法名和参数列表都相同
    3. 访问权限不能更低,可以更高
    4. 子类返回值类型必须小于等于父类返回值类型
    5. 子类不能比父类抛出更宽泛的异常

方法重写经典案例

	public class Test2 {
	public static void main(String[] args){
		EnglishPerson enPer = new EnglishPerson();
		ChinaPerson cPer = new ChinaPerson();
		
		enPer.speak();
		cPer.speak();
	}
}

class Person {
	String name;		//姓名
	String skinColor;	//肤色

	public void speak() {
		System.out.println("人在讲话");
	}
}

class EnglishPerson extends Person{
	public void speak() {
		System.out.println("英国人讲话说英语");
	}
}

class ChinaPerson extends Person {
	public void speak() {
		System.out.print("中国人讲话说汉语");
	}
}

上面的代码子类重写了父类的方法
在这里插入图片描述

引子——println()输出对象为什么得到的是内存地址的哈希值

package com.jsoft.test;

public class UserTest {
    public static void main(String[] args){
        User user = new User("admin","123");
        System.out.println(user);
    }
}

class User {
    String name;        //用户名
    String password;    //密码

    public User(){}
    public User(String name, String password) {
        this.name = name;
        this.password = password;
    }
}

对于上面的程序运行结果是这样的:完整类名@地址哈希值
在这里插入图片描述
我们去println()方法中看看这个方法具体是怎么实现的(我们以Java8为例)
在这里插入图片描述
可以看到println()调用了String.valueOf()这个静态方法,继续进入到String.valueOf()看一下
在这里插入图片描述
我们可以看到当String.valueOf()方法中的参数是一个Object时,会调用这个Object的toString()方法,也就是说当println()中的参数是Object时底层会调用这个Object的toString()方法,那么我们会在下一个内容中,尝试重写一下这个User类的toString()看看

重写从Object类中继承过来的方法

重写toString()
package com.jsoft.test;

public class UserTest {
    public static void main(String[] args){
        User user = new User("admin","123");
        System.out.println(user);
    }
}

class User {
    String name;        //用户名
    String password;    //密码

    public User(){}
    public User(String name, String password) {
        this.name = name;
        this.password = password;
    }
    public String toString() {
        return "用户名: " + name + "\t密码:" + password;
    }
}

运行结果如下,可以看出通过重写toString()后使用println(),可以完成对对象打印的操作(toString()即返回对象的字符串表示形式)
在这里插入图片描述

重写equals()

为什么要重写equals(),首先我们来看一个案例

public class Test2 {
	public static void main(String[] args){
		User user1 = new User("user1","123");
		User user2 = new User("user1","123");
		//判断user1、user2是否相等
		System.out.print("是否相等:" + (user1 == user2));
	}
}

class User {
	String name;
	String password;

	public User(){}
	public User(String name, String password) {
		this.name = name;
		this.password = password;
	}
}

对于这段代码的两个User对象用"=="进行比较是否相等?
在这里插入图片描述

从结果来看是不相等的,因为对于引用数据类型来说"=="比较的是两个对象的内存地址但是我们认为这两个User对象的所有属性的值都相等,可以认定这两个对象是相同的,那么该怎么做呢?

Object类中有一个用于比较两个对象是否相同的方法equals,可以通过重写这个equals方法来比较两个对象。如果不重写,默认使用Object类的equls方法,该方法对于非String类型的对象只会使用"=="运算符比较两个对象的内存地址,下图是Object类equals方法的源码(Java8)
在这里插入图片描述

对于String类中也重写了equals方法
在这里插入图片描述

所以我们需要重写equals方法,设置对象比较条件

public class Test2 {
	public static void main(String[] args){
		User user1 = new User("user1","123");
		User user2 = new User("user1","123");
		//判断user1、user2是否相等
		System.out.print("是否相等:" + (user1.equals(user2)));
	}
}

class User {
	String name;
	String password;

	public User(){}
	public User(String name, String password) {
		this.name = name;
		this.password = password;
	}
	//重写equals
	public boolean equals(Object obj) {
		if(this == obj) return true;	
		if(obj == null) return false;
		User user = null;
		if(obj instanceof User) {
			user = (User)obj;
		}
		return this.name.equals(user.name) && this.password.equals(user.password);
	}
}

代码运行结果如下
在这里插入图片描述
通过上述代码得出结论:我们可以通过重写equals()来界定User对象的比较内容

5. this与super

this

  1. this是关键字,是一个引用保存了对象自身的地址,存储在对象内部,代表对象本身。
  2. this可以用在实例方法和构造方法中。
  3. this不能用在静态方法中
  4. this在大多数情况下是可以省略的——当局部变量和实例变量同名时不能省略
  5. 语法格式:this.属性名/方法名 | this()

super

  1. super是关键字,代表的是当前对象(this)的“父类型特征1
  2. super可以用在实例方法和构造方法中(子类构造方法第的第一行有一个隐含的“super()”)
  3. super不能用在静态方法中
  4. super在大多数情况下是可以省略的——当子类对象的属性或实例方法和“父类型特征”相同时,需要使用super区分两者。
  5. 语法格式:super.属性名/方法名 | super() —> 初始化对象父类型特征

this和super内存分析

public class Test1 {
	public static void main(String[] args){
		Student stu1 = new Student();
		Student stu2 = new Student("张三",18,1);
	}
}

class Person {
	String name;		//姓名
	int age;			//年龄
	public Person() {
		//隐含的 super()
		//隐含的 this.name = null;
		//隐含的 this.age = 0;
	}
	public Person(String name, int age) {
		//隐含的 super() ----> 调用Object的无参构造,创建对象时初始化Person对象的"父类特征(Object)"
		this.name = name;
		this.age = age;
	}
}

class Student extends Person {
	int no;				//学号
	public Student() {
		//隐含的 super() ----> 调用Person的无参构造,创建对象时初始化Student对象的"父类特征(Person)"
		//隐含的 this.no = 0;
	}
	public Student(String name, int age, int no) {
		//此处调用父类有参构造,则此处将不再有super()
		super(name,age);
		this.no = no;
		
	}
}

对于上面的代码的内存图
在这里插入图片描述

6. 构造方法中存在的隐含的操作

1.所有子类的构造方法的第一行都会有隐含的super(),用于调用父类缺省构造器,如果在子类中编写super()或this(),那么第一行隐含的super()将不复存在。
2.对于任何构造方法都会有隐含的赋值操作(给实例变量赋默认值),如果给实例变量赋值此处隐含的赋默认值操作将取消。

知识点:了解

掌握情况:了解

思维导图

在这里插入图片描述


  1. 子类对象的父类型特征是属于对象本身的 ↩︎

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值