栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java学习笔记(2)(方法重写与向上转型)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java学习笔记(2)(方法重写与向上转型)

方法重写

在子类中如果创建了一个与父类中相同名称、相同返回值类型、相同参数列表的方法,只是方法体中的实现不同,以实现不同于父类的功能,这种方式被称为方法重写(override),又称为方法覆盖。当父类中的方法无法满足子类需求或子类具有特有功能的时候,需要方法重写。
重写方法时,需要遵循以下规则:

    参数列表必须完全与被重写的方法参数列表相同。

    返回的类型必须与被重写的方法的返回类型相同。

    访问权限不能比父类中被重写方法的访问权限更低(public>protected>default>private)

    父类的成员方法只能被它的子类重写。

    声明为 final 的方法不能被重写。

    声明为 static 的方法不能被重写,但是能够被再次声明。

    子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。

    子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。

    构造方法不能被重写。

    如果不能继承一个方法,则不能重写这个方法。

代码如下:
class Father{
   public void move(){
      System.out.println("Father");
   }
}

class Son extends Father{
    public void move(){
      System.out.println("Son");
   }
}

public class Test1{
   public static void main(String args[]){
      Father a = new Father(); // Father 对象
	   // 父类的引用指向了子类
      Father b = new Son(); // Son子类重写了Father父类的方法
	  Son c = (Son)new Father();

      a.move();// 执行 Father 类的方法

      b.move();//执行 Son 类的方法
	  
	  c.move();
   }
}

以上实例编译运行结果如下:

Father
son
son

在上面的例子中可以看到,尽管 b 属于 Father 类型,但是它运行的是 Son类的 move方法。

这是由于在编译阶段,只是检查参数的引用类型。

然而在运行时,Java 虚拟机(JVM)指定对象的类型并且运行该对象的方法。

因此在上面的例子中,之所以能编译成功,是因为 Father 类中存在 move 方法,然而运行时,运行的是特定对象的方法。

父类引用指向子类对象

父类引用指向子类对象指的是:

例如父类Animal,子类Cat,Dog。其中Animal可以是类也可以是接口,Cat和Dog是继承或实现Animal的子类。

Animal animal = new Cat();

即声明的是父类,实际指向的是子类的一个对象。

可以用这几个关键词来概括:多态、动态链接,向上转型

向上转型

子类引用的对象转换为父类类型称为向上转型。通俗地说就是是将子类对象转为父类对象。此处父类对象可以是接口

我定义了一个子类Son,它继承了Father类,那么后者就是前者是父类。我可以通过

Son c = new Son();
实例化一个Son的对象,这个不难理解。但当我这样定义时:

Father a = new Son();
这代表什么意思呢?

很简单,它表示我定义了一个Father类型的引用,指向新建的Son类型的对象。由于是继承自它的父类Father,所以Father类型的引用是可以指向Son类型的对象的。这就是“向上转型”。

代码如下:
class Gun{
   public void fixity(){
      System.out.println("0");
   }
   public void power()
   {
	   System.out.println("0");
   }
}

class M416 extends Gun{
    public void fixity(){
      System.out.println("Fixity : 70");
   }
   public void power()
   {
	   System.out.println("power : 40");
   }
   public void recoil()
   {
	   System.out.println("recoil : 50");
   }
}

class Akm extends Gun{
   public void fixity(){
      System.out.println("Fixity : 55");
   }
   public void power()
   {
	   System.out.println("power : 47");
   }
   public void recoil()
   {
	   System.out.println("recoil : 100");
   }
}
public class Test2{
   public static void main(String args[])
   {
	   show(new M416());//向上转型实现
	   show(new Akm());
   }
   public static void show(Gun gun)//父类实例作为参数
    {
        gun.fixity();
        gun.power();
        //gun.recoil();会报错
    }

}

需要注意的是向上转型时gun会遗失除与父类对象共有的其他方法。如本例中的recoil方法不再为gun所有。

public class Test2{
   public static void main(String args[])
   {
	   show(new M416());//向上转型实现
	   show(new Akm());
   }
   public static void show(Gun gun)//父类实例作为参数
    {
        gun.fixity();
        gun.power();
        //gun.recoil();会报错
    }

}

上述代码体现了向上转型的优点,这也体现了Java抽象编程的思想。如果此处没有向上转型,要实现show每个子类的功能,那么有几个子类就要写多少函数。代码如下:

public class Test2{
   public static void main(String args[])
   {
	   show(new M416());
	   show(new Akm());
   }
   public static void show(M416 gun) {
        gun.fixity();
        gun.power();
    }
	public static void show(Akm gun)
	{
		gun.fixity();
		gun.power();
	}

}

如果有很多的子类,不用向上转型则工作量会大很多,所以向上转型提高了代码的简洁性。

动态链接

当父类中的一个方法只有在父类中定义而在子类中没有重写的情况下,才可以被父类类型的引用调用; 对于父类中定义的方法,如果子类中重写了该方法,那么父类类型的引用将会调用子类中的这个方法
下面是一个多态例子:

class Father{
public void method1(){
method2();
}
//这是父类中的method2()方法,因为下面的子类中重写了该方法
//所以在父类类型的引用中调用时,这个方法将不再有效
//取而代之的是将调用子类中重写的method2()方法
public void method2(){
System.out.println("Son1");
}
}
class Son extends Father{
//method1(int i)是对method1()方法的一个重载,主要不是重写!
//由于在父类中没有定义这个方法,所以它不能被父类类型的引用调用
public void method1(int i){
//method2()重写了父类Father中的method2()方法
//如果父类类型的引用中调用了method2()方法,那么必然是子类中重写的这个方法
public void method2(){
System.out.println("Son3");
}
}
public class Test3 {
public static void main(String[] args) {
Father son = new Son();
son.method1();//打印结果将会是什么?
//son.method1(68);//报错,因为父类中无此方法
}
}

在上面的例子中,子类重载了父类的 method1( ) 方法,重写了父类的 method2( ) 方法,由于父类中没有method1(int i) 方法,只能调用父类中的 method1( ) 方法,而子类重写了method2 ( ) 方法,所以父类类型的引用son调用的是子类重写的method2方法,故结果输出为Son3。
当父类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在父类中定义过的,也就是说被子类覆盖的方法。

    如果a是类A的一个引用,那么,a可以指向类A的一个实例,或者说指向类A的一个子类。如果a是接口A的一个引用,那么,a必须指向实现了接口A的一个类的实例。
向下转型

与向下转型相反,向下转型是是把父类对象转为子类对象,它弥补了向上转型不能调用父类中未定义的方法。
代码:

class Father{
public void method1(){
method2();
}
//这是父类中的method2()方法,因为下面的子类中重写了该方法
//所以在父类类型的引用中调用时,这个方法将不再有效
//取而代之的是将调用子类中重写的method2()方法
public void method2(){
System.out.println("Son1");
}
}
class Son extends Father{
//method1(int i)是对method1()方法的一个重载,主要不是重写!
//由于在父类中没有定义这个方法,所以它不能被父类类型的引用调用
public void method1(int i){
System.out.println("Son2");
}
//method2()重写了父类Father中的method2()方法
//如果父类类型的引用中调用了method2()方法,那么必然是子类中重写的这个方法
public void method2(){
System.out.println("Son3");
}
public void method3(){
	System.out.println("向下转型");
}
}

public class Test3 {
public static void main(String[] args) {
Father son = new Father();//向上转型
son.method1();
Son child =(Son)son;//向下转型
child.method3();//调用了父类中没有的方法
child.method1(68);

}
}

运行结果:

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/785138.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号