java中的继承使用extends关键字,在子类继承了父类之后将会获得父类的全部属性与方法(父类的构造器除外)。如果在定义java类时没有显示定义她的父类,那么这个类默认将扩展java.lang.Object类。因此java.lang.Object是所有类的父类,要么是直接父类,要么就是间接父类。

   方法的覆盖(Overridden Methods)

   在类继承中,子类可以修改从父类继承来的行为,也就是说子类能创建一个与父类方法有不同功能的方法,但具有相同的:名称、返回类型、参数列表。如果在新类中定义一个方法,其名称、返回类型及参数表正好与父类中方法的名称、返回类型及参数相匹配,那么,新方法被称做覆盖旧方法。

示例:如下在 Employee 和 Manager 类中的这些方法:

public class Employee {
     String name;
     int salary;
     public String getDetails() {
         return " Name: " + name + " \n " + "Salary: " + salary;
     }
 }
 public class Manager extends Employee {
     String department;
     public String getDetails() {
         return " Name: " + name + " \n " + " Manager of " +
         department;
     }
 }


Manager 类有一个定义的 getDetails()方法,因为它是从 Employee 类中继承的。基本的方法被子类的版本所代替或覆盖了。

到底运行哪一个方法?
这里会给我们带来一个麻烦,父子类中有相同的方法,那么在运行时到底调用哪一个方法呢?假设下述方案:

Employee e = new Employee();
     Manager m = new Manager();


如果请求 e.getDetails()和 m.getDetails(),就会调用不同的行为。Employee 对象将执行与 Employee 有关的 getDetails 版本, Manager 对象将执行与 Manager 有关的getDetails()版本。

不明显的是如下所示:
    Employee e = new Manager();
    e.getDetails();
或某些相似效果,比如一个通用方法参数或一个来自异类集合的项。事实上,你得到与变量的运行时类型(即,变量所引用的对象的类型)相关的行为,而不是与变量的编译时类型相关的行为。这是面向对象语言的一个重要特征。它也是多态性的 一个特征,并通常被称作虚拟方法调用。

在前例中,被执行的e.getDetails()方法来自对象的真实类型Manager。因此规则是:编译时看数据类型,运行时看实际的对象类型(new 操作符后跟的构造方法是哪个类的)。一句话:new 谁就调用谁的方法。

覆盖方法的规则
子类的方法的名称以及子类方法参数的顺序必须与父类中的方法的名称以及参数的顺序相同以便该方法覆盖父类版本。下述规则适用于覆盖方法:

  • 覆盖方法的返回类型、方法名称、参数列表必须与它所覆盖的方法的相同。
  • 覆盖方法不能比它所覆盖的方法访问性差(即访问权限不允许缩小)。
  • 覆盖方法不能比它所覆盖的方法抛出更多的异常。


这些规则源自多态性的属性和Java编程语言必须保证“类型安全”的需要。考虑一下这个无效方案:

public class Parent {
     public void method() {}
 }
 public class Child extends Parent {
     private void method() {// 编译就会出错
     }
 }
 public class Test {
     public void otherMethod() {
         Parent p1 = new Parent();
         Parent p2 = new Child();
         p1.method();
         p2.method();
     }
 }


Java编程语言语义规定,p2.method()导致方法的Child版本被执行,但因为方法被声明为 private,p2(声明为 Parent)不能访问它。于是,语言语义冲突。

方法重载

如果有两个方法的方法名相同,但参数不一致,哪么可以说一个方法是另一个方法的重载。

  * 方法名相同

  * 方法的参数类型,个数顺序至少有一项不同

  * 方法的返回类型可以不相同

  * 方法的修饰符可以不相同

  * main方法也可以被重载

例如:

public class Test
{
    public static void main(String[] args)
    {
        Human person = new Human();
        person.breath(10);
    }

}

class Human
{
    /**
       * breath() 1
       */
    void breath()
    {
        System.out.println("hu...hu...");
    }


   /**
    * breath() 2
    */
    void breath(int rep)
    {
        int i;
        for(i = 0; i < rep; i++) {
            System.out.println("lu...lu...");
        }
    }

    int height;
}