Java 教程 在线

1396Java 抽象类

java 中抽象类不能被实例化

代码示例:

class abstract A {

}

驱动函数:

public static void  main(String[] args){

   //下面这行会造成编译不通过
    A a=new A();

}

1395Java 虚函数、抽象函数、抽象类、接口

JAVA – 虚函数、抽象函数、抽象类、接口

1. Java 虚函数

虚函数的存在是为了多态。

C++ 中普通成员函数加上 virtual 关键字就成为虚函数。

Java 中其实没有虚函数的概念,它的普通函数就相当于 C++ 的虚函数,动态绑定是 Java 的默认行为。如果 Java 中不希望某个函数具有虚函数特性,可以加上 final 关键字变成非虚函数。

PS: 其实 C++ 和 Java 在虚函数的观点大同小异,异曲同工罢了。

2. Java抽象函数(纯虚函数)

抽象函数或者说是纯虚函数的存在是为了定义接口。

C++ 中纯虚函数形式为:

virtual void print() = 0;

Java 中纯虚函数形式为:

abstract void print();

PS: 在抽象函数方面 C++ 和 Java 还是换汤不换药。

3. Java 抽象类

抽象类的存在是因为父类中既包括子类共性函数的具体定义,也包括需要子类各自实现的函数接口。抽象类中可以有数据成员和非抽象方法。

C++ 中抽象类只需要包括纯虚函数,既是一个抽象类。如果仅仅包括虚函数,不能定义为抽象类,因为类中其实没有抽象的概念。

Java 抽象类是用 abstract 修饰声明的类。

PS: 抽象类其实是一个半虚半实的东西,可以全部为虚,这时候变成接口。

4. Java 接口

接口的存在是为了形成一种规约。接口中不能有普通成员变量,也不能具有非纯虚函数。

C++ 中接口其实就是全虚基类。

Java 中接口是用 interface 修饰的类。

PS: 接口就是虚到极点的抽象类。

5. 小结

C++ 虚函数    ==  Java 普通函数

C++ 纯虚函数  ==  Java 抽象函数

C++ 抽象类    ==  Java 抽象类

C++ 虚基类    ==  Java 接口

1394Java 子类新的实现

如果子类的方法覆盖了父类的方法,我们也说父类的那个方法在子类有了新的版本或者新的实现。覆盖的新版本具有与老版本相同的方法签名:相同的方法名称和参数表。因此,对于外界来说,子类并没有增加新的方法,仍然是在父类中定义过的那个方法。不同的是,这是一个新版本,所以通过子类的对象调用这个方法,执行的是子类自己的方法。

覆盖关系并不说明父类中的方法已经不存在了,而是当通过一个子类的对象调用这个方法时,子类中的方法取代了父类的方法,父类的这个方法被“覆盖”起来而看不见了。而当通过父类的对象调用这个方法时,实际上执行的仍然是父类中的这个方法。注意我们这里说的是对象而不是变量,因为一个类型为父类的变量有可能实际指向的是一个子类的对象。

当调用一个方法时,究竟应该调用哪个方法,这件事情叫做绑定。绑定表明了调用一个方法的时候,我们使用的是哪个方法。绑定有两种:一种是早绑定,又称静态绑定,这种绑定在编译的时候就确定了;另一种是晚绑定,即动态绑定。动态绑定在运行的时候根据变量当时实际所指的对象的类型动态决定调用的方法。Java缺省使用动态绑定。

1393Java 子类的方法覆盖

如果子类的方法覆盖了父类的方法,我们也说父类的那个方法在子类有了新的版本或者新的实现。覆盖的新版本具有与老版本相同的方法签名:相同的方法名称和参数表。因此,对于外界来说,子类并没有增加新的方法,仍然是在父类中定义过的那个方法。不同的是,这是一个新版本,所以通过子类的对象调用这个方法,执行的是子类自己的方法。

覆盖关系并不说明父类中的方法已经不存在了,而是当通过一个子类的对象调用这个方法时,子类中的方法取代了父类的方法,父类的这个方法被“覆盖”起来而看不见了。而当通过父类的对象调用这个方法时,实际上执行的仍然是父类中的这个方法。注意我们这里说的是对象而不是变量,因为一个类型为父类的变量有可能实际指向的是一个子类的对象。

当调用一个方法时,究竟应该调用哪个方法,这件事情叫做绑定。绑定表明了调用一个方法的时候,我们使用的是哪个方法。绑定有两种:一种是早绑定,又称静态绑定,这种绑定在编译的时候就确定了;另一种是晚绑定,即动态绑定。动态绑定在运行的时候根据变量当时实际所指的对象的类型动态决定调用的方法。Java缺省使用动态绑定。

1392Java 父类的属性变量

父类的属性变量(例如变量 int a)可以被继承,同时在子类中也会同时继承该变量(super.int a,继承的变量),子类中也可以再次声明一个同名(可以同类型)的变量(double a,自己声明的同名变量),两者可以同时存在。在输出时候根据对象的引用名输出,例如:

class Animal{
    public int age;      //此处在Animal中定义类型为int,名为age的变量。
    public void move(){
        System.out.println("动物总是不安分");
    }
}
     
class Dog extends Animal{
    public double age;    //此处在Dog中定义新类型double,名为age的变量。当然int尝试也可以。 
    public void move(){
        age =10;
        System.out.println("狗跑的很快");
    }
}
class Cat extends Animal{
    public void move(){
        super.age = 3;   //此处继承age,并赋值为3.且该类中未重新定义变量。
        System.out.println("猫跳的很高");
    }
}     
public class DuiXiang03{
    public static void main(String args[]){
        Animal a = new Animal(); // Animal 对象
        Animal b = new Dog(); // Dog 对象
        Animal c =new Cat(); //Cat 对象
        Dog  d= new Dog();
        Cat  e= new Cat();

        a.move();//执行 Animal 类的方法
        b.move();//执行 Dog 类的方法
        c.move();//执行 Cat 类的方法
        d.move();//执行Dog 类的方法
        e.move();//执行 Cat 类的方法
        Object aValue = a.age;
        Object bValue = b.age;      // b.age有两个age值,一个是自定义的age值,一个是继承的age值
        Object cValue = c.age;     
        Object dValue = d.age;      // d.age有两个age值,一个是自定义的age值,一个是继承的age值
        Object eValue =e.age;
        System.out.println("The type of "+a.age+" is "+(aValue instanceof Double ? "double" : (aValue instanceof Integer ? "int" : "")));     // Animal 类中的 age 未被赋值
        System.out.println("The type of "+b.age+" is "+(bValue instanceof Double ? "double" : (bValue instanceof Integer ? "int" : "")));     // b.age有两个age值,输出取引用名为Animal的int类型值
        System.out.println("The type of "+c.age+" is "+(cValue instanceof Double ? "double" : (cValue instanceof Integer ? "int" : "")));     // c.age只有一个age值,是super所继承的Animal中的age值,再被赋值为3
        System.out.println("The type of "+d.age+" is "+(dValue instanceof Double ? "double" : (dValue instanceof Integer ? "int" : "")));     // d.age有两个age值,输出取引用名为Dog的double类型值
        System.out.println("The type of "+e.age+" is "+(eValue instanceof Double ? "double" : (eValue instanceof Integer ? "int" : "")));     // c.age只有一个age值,是super所继承的Animal中的age值,再被赋值为3
    }
}

输出的结果为:

动物总是不安分
狗跑的很快
猫跳的很高
狗跑的很快
猫跳的很高
The type of 0 is int
The type of 0 is int
The type of 3 is int
The type of 10.0 is double
The type of 3 is int