重写super关键字final关键字多态子类型转换抽象的初步了解

Posted wuzhaoming

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了重写super关键字final关键字多态子类型转换抽象的初步了解相关的知识,希望对你有一定的参考价值。

重写

含义

在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. 抽象类的使用

  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();
}
}

 

 

 

以上是关于重写super关键字final关键字多态子类型转换抽象的初步了解的主要内容,如果未能解决你的问题,请参考以下文章

深度剖析—继承和多态

java的方法重写 ,多态和关键字 instanceof和final

Java语法包 继承 多态 抽象类 接口

继承,多态,抽象,接口

继承,super关键字,方法重写,final关键字

java——super关键字final关键字抽象类接口