java的继承&instanceOf的使用&方法重写&继承树追溯问题

本文详细介绍了Java中的继承特性,包括子类继承父类的属性和方法,instanceOf运算符的使用,以及方法的重写规则。还讨论了Object类的toString、equals方法及其重写,并解释了super关键字在子类中的应用。最后探讨了Java中的继承树追溯问题,揭示了构造器在创建子类对象时如何调用父类构造器的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、继承、封装、多态三大特征。

继承:extends意思是扩展,子类拥有父类的一切,子类是父类的扩展。
我们先来写一个类:

class Person
{
     String name;
     int height;
     
     public void rest()
     {
           System.out.println("learning java");
     }
}

再写另外一个类:

class Student
{
     String name;
     int height;
     String major;
     
     public void study()
     {
           System.out.println("learning");
     }
     public void rest()
     {
           System.out.println("learning java");
     }
}//发现student里面重复了person的属性和方法

这种时候student就没必要这样写,而选择用继承:

class Student extends Person
{
     String major;
     public void study()
     {
           System.out.println("learning java");
     }
}

采用下面的继承,在实例化一个student对象的时候,可以发现已经拥有了person的属性:
在这里插入图片描述
继承使用要点:
* 父类也称作超类、基类、派生类;
* java里面只有一个直接父类,没有像C++那样的多继承,多继承会引起混乱,使得继承过于复杂,系统难以维护;
* java中类没有多继承,接口有多继承;
* 子类继承父类,可以得到父类的全部属性和方法(除了父类的构造方法),但不见得可以直接访问(比如父类私有的属性和方法);
* 如果定义一个类时没有调用extends,则它的父类是:java.lang.Object;

(可以用ctrl + T 查看类的继承层次结构)
instanceof运算符:
instanceof用来判断某个对象是不是某个类型

           System.out.println(stu instanceof Student);
           System.out.println(stu instanceof Person);

在这里插入图片描述

二、方法的重写(override):

父类的某个方法的实现不完全符合子类的要求,因此可以进行改变,变成独特的实现,也就是override;

class Vehicle
{
     public void run()
     {
           System.out.println("running……");
     }
     public void stop()
     {
           System.out.println("stop");
     }
     public Person whoIsPassenger()
     {
           return new Person();//返回的类型是一个person类
     }//父类里面的返回乘客方法
}
class horse extends Vehicle
{
     public void run()
     {
           System.out.println("didadidadida");
     }//重写了run方法
     public Student whoIsPassenger()
     {
           return new Student("john",178,"java");
     }//重写父类的返回乘客方法,返回值类型小于父类的返回值,因为返回的student类时person类的子类
}

总结方法的重写需要符合下面的三个要点:
* “==”:方法名,形参列表相同;
* “<=”:返回值和声明异常类型,子类的必须要小于等于父类的;
* “>=”:访问权限,子类大于等于父类。

Object类是所有java类的根基类,也就是所有的java对象都拥有object类的属性和方法。如果在类的声明里没有extends关键字声明其父类,那么默认是继承的object类。Object类属于java的lang包里。
object类里的toString()方法

public class testObject {
     public static void main(String[] args)
     {
           //Object obj;
           testObject to=new testObject();
           System.out.println(to.toString());
     }
}

返回了类的路径和十六进制的数字组成的字符串:
在这里插入图片描述
可以重写tostring方法

public class testObject {
     public static void main(String[] args)
     {
           //Object obj;
           testObject to=new testObject();
           System.out.println(to.toString());//toString方法返回一个十六进制的字符串
     }
     
    public String toString() {
        return "override toString";
    }
}

运行结果就变成了:
在这里插入图片描述
==和equals方法的重写
“==”是比较双方是否相同,如果是基本类型则是表示值相等,如果是引用类型,就是比较指向地址是否相等,也就是是否指向同一个对象;
Object类中定义有一个方法:public boolean equals(Object obj)方法,提供定义“对象的内容是否相等”的逻辑。
equals是经常被重写的方法(比如公安系统,那么只要两个人的身份证号相等那么就认为是同一个人,对象的其他内容就不需要再比较)
可以查看equals的源码:
在这里插入图片描述
例如定义一个user类:

class User{
     int id;
     String name;
     String pwd;
     //按住alt shift + s,可以选择自动生成constructor
     public User(int id, String name, String pwd) {
           super();
           this.id = id;
           this.name = name;
           this.pwd = pwd;
     }
}

用“==”和“equals方法”

           User u1=new User(1000,"john","123456");
           User u2=new User(1000,"archie","123456");
           
           System.out.println(u1==u2);
           System.out.println(u1.equals(u2));

在这里插入图片描述

由于这是两个对象,所以返回了false;
我们可以对equals方法重写,可以使用eclipse自动生成的hashcode和equals方法,也可以自己写:
这里改为只判断id一个属性的值是否相等

   @Override
     public boolean equals(Object obj) {
           if (this == obj)
                return true;//先大范围判断整个类,地址一样肯定一样
           if (obj == null)
                return false;//如果有一个为空那肯定不一样
           if (getClass() != obj.getClass())
                return false;//如果类的类型不一样
           User other = (User) obj;//这里需要一个强制类型的转换
           if (id != other.id)
                return false;//只判断id一个属性的值
           return true;
     }

这次的运行结果变成了:
在这里插入图片描述
也就是判断了id属性是一样的值。

我们阅读String类的源代码,可以发现它也重写了equals方法:
在这里插入图片描述
进行简单的测试:

   String str=new String("yanhaoqi");
   String str2=new String("yanhaoqi");
   System.out.println(str==str2);//false因为这是两个对象
   System.out.println(str.equals(str2));//true因为内容一样

super关键字
super是直接父类对象的引用,可以通过super来访问父类中被子类覆盖的方法或属性。
来看一个例子,先写父类:

class fatherClass{
public int value;

 public void f() {
       value=100;
       System.out.println("fatherClass value is :"+value);
 } }

然后在子类里重写父类的方法,但是依然用super来访问父类中的方法和属性:

 class childClass extends fatherClass{
         public int value;
         @Override
         //重写父类的方法f
         public void f() {
               // TODO Auto-generated method stub
               value=200;
               super.f();//访问父类对象的普通方法
               System.out.println("childClass value is :"+value);
               System.out.println(value);
               System.out.println("fatherClass value is  :"+super.value);//调用父类对象的成员变量
         }
         
    }

在main函数中调用看看:

public static void main(String[] args) {
fatherClass f=new fatherClass();
childClass c=new childClass();

   f.f();
   c.f();

}

结果是这样的:
在这里插入图片描述
一般来说构造器里的第一行没有显示调用super()的话或者this(),那么java都会默认调用super(),含义是调用父类的无参数构造方法,这里的super()可以省略(可以看到我上面的自动生成构造器的代码里就有一行super())

三、继承树追溯问题:

我们还是先来写一个父类和子类:

class father{
     public father() {
           System.out.println("building father class");
     }
}
class child extends father{
     public child() {
           System.out.println("building child class");
     }
}

在main方法里new一个子类看看:

public static void main(String[] args) {
System.out.println(“building a child class”);
child c=new child();
}

发现输出结果意外的是这样:
在这里插入图片描述
也就是说,在创建子类的时候已经调用了父类的方法,这丫就是上面所说的:
“构造器里的第一行没有显示调用super()的话或者this(),那么java都会默认调用super()”
因此这里面的过程在构造child类的时候首先第一句默认的super()会去调用father类的构造器,然后father类里面也有默认的super(),回去调用父类object的构造器,然后再一步一步返回回来到child;
这个追溯的过程有点类似前面的static静态初始化块的过程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值