• 深入理解JAVA面向对象的继承原理
  • 发布于 2个月前
  • 203 热度
    0 评论
  • 雾月
  • 0 粉丝 23 篇博客
  •   
前言

. Java中的继承机制一个类只可以继承另一个类(不能同时继承多个,可以多实现),继承的类称为子类,被继承的类称为父类。

. 在一个子类被创建的时候,首先会在内存中创建一个父类对象,然后在父类对象外部放上子类独有的属性,两者合起来形成一个子类的对象,所以子类可以继承父类中所有的属性和方法,包括private修饰的属性和方法,但是子类只是拥有父类private修饰的属性和方法,无法直接访问到它。

. 子类可以通过调用父类的public声明的get方法来获取父类的private属性,但无法访问父类的private方法

. 子类可以对继承的方法进行重写,也可以新建自己独有的方法。


案例
向上转型
假设有一个Animal类,Animal类中有一个say()方法,代码如下:
public class Animal {
    // 堆代码 duidaima.com
    public void say(){
        System.out.println("This is the zoo");
    }
}
有一个Tiger类继承自Animal类,该类有自己的方法speak(),并且重写了父类的say()方法,代码如下:
public class Tiger extends Animal {
    @Override
    public void say() {
        System.out.println("This is the zoo,I'm a tiger !!!");
    }

    public void speak(){
        System.out.println("I like meat !!!");
    }
}
调用父类say()
  public static void main(String[] args) {
       // 堆代码 duidaima.com
      //向上转型
      Animal animal = new Tiger();
      animal.say();
  }
  
  //输出结果:This is the zoo,I'm a tiger !!!
调用子类speak()方法,你会发现根本.不出来:

向上转型,就是用父类的引用变量去引用子类的实例,这是允许的。当向上转型之后,父类引用变量可以访问子类中属于父类的属性和方法,但是不能访问子类独有的属性和方法。

例子中由于子类重写了父类的say()方法,所以调用的say()方法是子类的say()方法,输出结果为:This is the zoo,I'm a tiger !!!,而调用子类的speak()方法则提示没有该方法。

向下转型
注意:并不是所有的对象都可以向下转型,只有当这个对象原本就是子类对象通过向上转型得到的时候才能够成功转型

接着上面测试代码:
    public static void main(String[] args) {
        //向上转型
        Animal animal = new Tiger();
        animal.say();

        //向下转型
        Tiger tiger = (Tiger) animal;
        tiger.say();
        tiger.speak();
如果这时新建一个Rabbit类
public class Rabbit extends Animal{

    @Override
    public void say() {
        System.out.println("This is the zoo,I'm a rabbit !!!");
    }

    public void speak(){
        System.out.println("I like carrots !!!");
    }
}
接着上面测试代码:
    public static void main(String[] args) {
        //向上转型
        Animal animal = new Tiger();
        animal.say();

        //向下转型
        Tiger tiger = (Tiger) animal;
        tiger.say();
        tiger.speak();
        
        /**
         * 这里编译正常,但运行时会报以下异常:
            Exception in thread "main" java.lang.ClassCastException: org.example.test.Tiger cannot be cast to org.example.test.Rabbit
            at org.example.test.Tiger.main(Tiger.java:30)
         */
        Rabbit rabbit = (Rabbit) animal;
        rabbit.say();
        rabbit.speak();
    }
因为Animal对象是由Tiger对象向上转型得到的,只能够向下转型成Tiger对象,不能够向下转型成Rabbit对象。优化测试代码,增加instanceof关键字:
    public static void main(String[] args) {
        //向上转型
        Animal animal = new Tiger();
        animal.say();
        //堆代码 duidaima.com
        //向下转型
        if(animal instanceof Tiger){
            Tiger tiger = (Tiger) animal;
            tiger.say();
            tiger.speak();
        }

        if(animal instanceof Rabbit){
            Rabbit rabbit = (Rabbit) animal;
            rabbit.say();
            rabbit.speak();
        }
    }
Java中,instanceof运算符用于判断前面的对象是否是后面的类,或其子类、实现类的实例。如果是返回true,否则返回false。也就是说:用instanceof关键字做判断时, 操作符的左右操作必须有继承或实现关系。

总结
向上转型
好处:隐藏了子类型,提高了代码的扩展性。
坏处:只能使用父类的功能,不能使用子类特有功能,功能被限定。
向下转型
好处:可以使用子类型的特有功能
坏处:面对具体的子类型,向下转型具有风险,容易发生ClassCastException,只要转换类型和对象不匹配就会发生。
解决方法:使用关键字instanceof。
样例
通过向上向下转型肯定是有好处的,比如可以减少编程代码,比如有这样一个方法:
  public static void run(Animal animal){
      animal.say();
  }
这时你可以传Tiger或Rabbit都可以。
用户评论