Java之重写、关键字(super、final)Object类以及多态、引用数据类型转换以及抽象的初步了解

重写

含义

​ 在Java中,子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。方法重写又称方法覆盖。

重写与重载的异同点

相同点

都是作用在方法上

不同点

​ 重载时作用在同一个类中,多个方法名相同,参数列表不同(方法签名不同)而采用的方式

​ 重写是作用在不同类,该类继承于需要修改方法的父类.

区别:

​ 重载是在同一个类中,方法名相同,参数列表不同

​ 重写是作用在两个有继承关系的子类中,方法签名相同

需要重写的原因

​ 在一些业务实现过程中,子类存在从父类中继承的功能,但子类要实现的功能与父类不同所以我们需要重写该功能,以满足我们的业务需求

重写(在子类中才能重写)

​ 重写的方法:与普通方法相同,但是方法名和参数列表要与父类中相同

重写的方法的调用顺序

​ 子类对象在调用这个功能的使用,如果有重写方法,就调用重写方法如果没有则调用父类的方法

public class OverrideDemo {
	public static void main(String[] args) {
			//创建一个子类的实例(对象)
			Son son=new Son();
			//使用子类的重载方法
			son.word();
	}
}
//父类  
class Dad{
	private int money=1250;
	//父类的方法 如果加上static则无法被子类继承
	public  void words(){
		System.out.println("我是父类的方法");
	}
}
//子类  父类继承子类
class Son extends Dad{
    //在父类被static修饰后,该方法不是重写父类的方法,而是创建了一个新方法
	public void word(){
		System.out.println("我是子类的方法");
	}
}

**注意:**父类中,方法被static被修饰,则子类无法继承.如果子类中有相同的方法签名,则该方法是子类新建方法,并非对父类方法的重写.

super关键字

super与this的区别

this:代指当前创建的对象

  1. 调用本类中其他构造器
    1. 必须放在构造器首行
    2. this([参数列表])//参数是列表匹配本类中的其他构造器
  2. 区分同名变量(局部变量与成员变量)的问题
    1. this.变量名 代指当前创建对象的变量即成员变量

super:指代父类对象

  1. 调用父类构造器
    1. 默认调用父类的空构造器//所以在写javaBean的时候要求必须有一个空构造器
    2. 调用父类的其他构造器需要显式调用super([参数列表]),参数列表匹配父类构造器的参数列表
    3. 与this相同,必须放在构造器的首行
    4. this与super在同个构造器中,不能同时来调用其他构造器
  2. 区分同名变量问题(子类和父类)
    1. 局部 子类成员 父类成员同名的时候调用局部变量直接写该变量名|方法名(),调用子类变量的时候写this.变量名|this.方法名(),调用父类成员的时候super.变量名|super.方法名()
    2. 注意:调用构造方法与调用普通的方法不一样,采用super.变量名|super(参数列表)

如何设置父类中属性值的两种方式:

  1. 用设置器和获取器来设置和访问父类中的属性
  2. 采用通过构造器给父类的属性赋值,其具体经过如下:子类在创建对象时,调用子类构造器,子类构造器,我们可以子类构造器首行调用父类构造器传入参数,将参数传入到父类构造器中,进而实现对父类属性的赋值
public class Supper01 {
	public static void main(String[] args) {
		//先执行子类的无参构造,在执行父类的无参构造
		Son son1=new Son();
		//先执行子类的有参构造,在把值传给父类的有参构造
		Son son2=new Son("小吴");
	}	
}
//父类
class Dad{
	//父类成员变量
	String name;
	//父类成员方法
	public void study(){
		System.out.println("父亲在学习");
	}
	//父类构造器
	public Dad() {
		System.out.println("父类空构造");
	}
	public Dad(String name) {
		this.name = name;
		System.out.println("父类带参构造"+this.name);//这里的name是指代当前父类的成员
	}

}
//子类 继承父类
class Son extends Dad{
	//子类成员变量
	String name;
	//子类成员方法
	@Override
	public void study() {
		System.out.println("儿子在学习.覆盖了父亲在学习");
	}
	//子类构造器1
	public Son() {
		System.out.println("子类无参构造器");
	}
	//子类构造器2
	public Son(String name) {
		super(name);//把变量传给父类的构造
		System.out.println("子类有参构造器");
	}
	
}

final关键字 最终

记住以下三点:

  1. 被final修饰的变量为常量

    1. 变量的数据类型如果是基本数据类型:存储的数据值不能改变
    2. 变量的数据类型如果是引用数据类型:存储的地址值不会改变,但是对象内存中的属性可以改变
  2. 被final修饰的方法不能被重写

    public class Final01 {
    	public static void main(String[] args) {
    		DadOne dad=new DadOne();
    		SonOne son=new SonOne();
    		son.eat();
    	}
    }
    class DadOne{
    	int a=5;
    	public static void  eat(){
    		System.out.println("父类的吃");
    	}
    }
    class SonOne extends DadOne{
    	public static void eat(){//方法签名与父类一致,但是不是重写,因为该方法中在父类中final修饰过,此为新方法
    		System.out.println("子类的吃");
    	}
    }
    

    以上的代码不会报错,

  3. 被final修饰的类不能被继承(俗称太监类)

public class Final01 {
	public static void main(String[] args) {
		DadOne dad=new DadOne();
		SonOne son=new SonOne();
	}
}
final class DadOne{
	int a=5;
}
class SonOne extends DadOne{//此行会报错
	
}

Object类(所有的类的最基础的类,相当于源头)

所以类的父亲,java中的所有类都会直接或间接继承来自Object类

如果没有显式继承其他类,默认继承自Object类

toString方法

  1. toString()把对象的内容以字符串的形式展示

    源码:

    public String toString() {
     	return getClass().getName() + "@" + Integer.toHexString(hashCode());
        	}
    

    ​ 在打印一个对象的引用的时候,打印对象的地址,默认打印的是这个对象调用了toString 方法的返回值,根据需要可对toString方法进行重写.

  2. equal方法:

equals两种情况

  1. 如使用是Object类中的equal()方法中比较是对象的地址
  2. 如有对equal()方法重写,则比较就是方法重写的内容.如String.euqals("");
/*
判断两个用户是否是同一个用户,判断条件为 用户名和密码 相同,并输出用户的信息
思路:重写equals方法,判断其中 用户名和密码,重写toString输出用户的信息

*/public class UserNamePassword {
	public static void main(String[] args) {
		UserPassword u1=new UserPassword("小翁","123456");
		UserPassword u2=new UserPassword("xaiaong","56152");
		UserPassword u3=new UserPassword("小翁","123456");
		String a="525";
		System.out.println(u1);
		System.out.println(u2);
		System.out.println(u3);
		System.out.println(u1.equals(u2));
		System.out.println(u1.equals(u3));	
		System.out.println(u1.equals(525));
		System.out.println(u1.user.equals("小翁"));
	}
	
}
class UserPassword{
	public String user;
	public String password;
	
	public UserPassword() {
		super();
	}
	public UserPassword(String user, String password) {
		super();
		this.user = user;
		this.password = password;
	}
	//重写toString方法
	@Override
	public String toString() {
		return user+password;
	}
	//重写euqual方法
	@Override
	public boolean equals(Object obj) {
		if(this==obj){
			return true;
		}else{
			if(obj instanceof UserPassword){
				UserPassword u=(UserPassword)obj;
				if(this.user==u.user){
					return true;
				}else{
					return false;
				}
			}
			return false;
		}
		
	}
		
}

多态

面向对象的三大特征

封装:隐藏内部的实现细节,对外提供公共的方法方式.私有是封装的一种具体的表现形式

继承:子类一旦继承父类,有权实现父类的内容

多态:一种事物的多种形态|多种表现方式

多态的前提

​ 必须是类的继承或是接口的实现

多态的最终体现

​ 父类的引用指向子类的对象

假设Person是父类,Study是子类

Person p=new Study();

多态重写方法的调用顺序

​ 如果子类和父类中同时有重写方法,多态调用是子类中的重写方法,如没有则直接调用父类的方法.

注意:父类引用对子类的新增内容不可见

多态的编译与运行

  1. 成员变量
    1. 编译看父类|看左边|看类型
  2. 成员方法
    1. 编译看父类,运行看子类
    2. 编译看左边,运行看右边
    3. 编译看类型,运行找对象
public class Shy {
	public static void main(String[] args) {
		Pig pigOne=new Pig();
		Aniaml pigTwo=new Pig();
		//测试
		//子类引用指向子类对象  成员变量与成员方法都可以使用
		System.out.println(pigOne.name);
		pigTwo.eat();
		/*父类引用指向子类对象  
		成员变量:不可以直接使用子类对象的属性
		成员方法:如果有子类重写方法,则直接使用子类重写的方法
				如果子类中没有该方法,而父类中有此方法,则直接使用父类的方法
		注意:如果该变量不可以无法使用子类中的新增内容
		*/
		System.out.println(pigTwo.name+"===");
//		System.out.println(pigTwo.name);
		pigTwo.eat();	
	}
}

class  Aniaml{
	//成员变量
	public String name="动物";
	private int age;
	//成员方法
	public void eat(){
		System.out.println("我喜欢吃");
	}
	//构造函数
	public Aniaml() {
		super();
	}
	public Aniaml(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
}

//子类
class Pig extends Aniaml{
	String name="小猪";
	int age;
	public Pig(){
		super();
	}
	
	public Pig(String name,int age){
		super(name,age);
	}
	@Override
	public void eat() {
		System.out.println("猪吃猪");
	}	
}

注意事项

子类引用指向子类对象 ,成员变量与成员方法都可以使用如下种形式:

//Person是父类,Study是子类
Person p=new Study();

成员变量:不可以直接使用子类对象的属性
成员方法:如果有子类重写方法,则直接使用子类重写的方法
如果子类中没有该方法,而父类中有此方法,则直接使用父类的方法
**注意:**如果该变量不可以无法使用子类中的新增内容

子类型转换

向上类型转换

就是多态的使用

向下类型转换

子类类型 引用 = (子类类型)父类类型的数据;

判断是否为该父类的子类,用instanceof判断

注意:向下转型后,就可以使用子类新增内容

public class Shy02 {
	public static void main(String[] args) {
		//孔子以孔子爹的面孔展现
		//父类(孔子爹) 的引用 指向 子类对象(孔子)
		//向上转型,从子类到父类
		ConfuciusDad kzd=new Confucius();
		kzd.teache();
		//向下转型,父类转到子类,才能使用子类的新增内容
		Confucius kz=(Confucius)kzd;
		kz.play();
		//向下转型,父类引用可以转到任意子类的类型,但是也可能不是我们想要的
	/*	Brother kzb=(Brother)kzd;
		kzb.play();	*/
		//向下类型转换前,可以采用instanceof进行判断是否为我们想要的子类
		if(kzd instanceof Confucius){//判断kzd是否是Confucius的一个实例(对象)返回boolean值
			Confucius kzz=(Confucius)kzd;
			kzz.play();
		}		
	}
	
}
class ConfuciusDad{
	public void teache(){
		System.out.println("孔子爹---授课");
	}
}
class Confucius extends ConfuciusDad{
	public void teache(){
		System.out.println("孔子---授课");
	}
	public void play(){
		System.out.println("大话西游");
	}
}
class Brother extends ConfuciusDad{
	public void teache(){
		System.out.println("孔子兄弟---授课");
	}
	public void play(){
		System.out.println("LOL");
	}
	
}

抽象

抽象类:被abstract修饰的类

抽象方法:别abstract修饰的方法

抽象方法:必须在抽象类中且必须在抽象类中

注意:

  1. 抽象类不能被实例化|不能创建对象
  2. 抽象方法要存在于抽象类中,抽象方法必须被重写
  3. 抽象类的使用
    1. 具体子类:重写所用的抽象方法+按需新增
    2. 抽象子类:按需重写抽象方法+按需新增
  4. 一个抽象方法一旦被重写过,就不需要再次被重写
  5. 抽象列中可以存在普通方法,可以存在抽象方法
  6. abstract不能和private,final,static,native一起使用

父类:

  1. 具体父类
    1. 可以创建父类对象,同时知道父类中的内容如何定义可以定义具体的父类
  2. 抽象父类
    1. 不想要能够直接创造父类对象
    2. 父类中的方法体不知道如何实现

示例:

定义抽象类

//定义一个抽象类
public abstract class Develop {
	//定义两个抽象类 work sleep
	public abstract void work();
	public abstract void slepp();
}

定义具体子类

//具体的子类必须全部实现 继承的抽象类中的方法
public class Java extends Develop{

	@Override
	public void work() {
		System.out.println("java攻城狮在工作");
	}

	@Override
	public void slepp() {
		System.out.println("java攻城狮在睡觉");
	}
	
	public void huo(){
		System.out.println("java攻城狮在接私活");
	}
}

定义抽象父类,并定义具体子类

//具体的子类必须全部实现 继承的抽象类中的方法
//如果有一个没有实现,则应该把此类也定义成抽象类
public abstract class Web extends Develop{

	@Override
	public void work() {
		System.out.println("Web工程师在工作");
	}

}

class Demo extends Web{
	//实现了上面未实现的方法
	@Override
	public void slepp() {
		System.out.println("web工程师也在休息");
	}
}

测试代码

public class Test {
	public static void main(String[] args) {
		Java java=new Java();
		java.work();
		java.slepp();
		java.huo();
		
		Demo d=new Demo();
		d.slepp();
		d.work();
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值