`
bluewind1433
  • 浏览: 153009 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

java继承时的覆盖和隐藏

    博客分类:
  • java
阅读更多

JAVA类继承过程中其成员的一些问题

 构造函数不能继承。子类的构造函数可以通过super关键字显式调用父类中的构造函数。如

果子类中的构造函数没有显式调用父类中的构 造函数,编译器就会自动在子类的构造函数中调用父类中参数为空的构造函数。于是,当父类中没有参数为空的构造函数,而子类中又没有显示调用父类的其他构造 函数,编译时就会报错。这一点需要特别注意。当父类中没有定义任何构造函数时,编译器就会为它指定一个参数为空的默认的构造函数;如果父类中定义了构造函 数,那么编译器就不会为它指定一个参数为空的默认构造函数了。因此,如果某个类有可能成为其他类的父类,为了避免发生不必要的编译错误,最好为它编写一个 参数为空的构造函数。

eg1.父类Sup中没有定义构造函数,编译程序将为它指定一个参数为空的默认构造函数。子类Sub中也没有定义构造函数,编译程序也会为它指定一个参数为空的默认的构造函数,并且会在这个默认的构造函数中调用父类的参数为空的构造函数。
public class Sub  extends Sup{
    //子类中没有定义构造函数
    public static void main(String args[]){
        Sub sub=new Sub();
    }
}

class Sup{
    //父类中没有定义构造函数
}


eg2.父类Sup中没有定义构造函数,编译程序将为它指定一个参数为空的默认构造函数。子类定义了一个带整型参数的构造函数,在这个构造函数中子类没有显式调用父类的构造函数,所以编译器为在它里面调用父类中参数为空的构造函数。

public class Sub  extends Sup{
    //子类中定义类一个带整型变量参数的构造函数
    public Sub(int i){
        //
    }
    public static void main(String args[]){
        Sub sub=new Sub(1);
    }
}
class Sup{
    //父类中没有定义构造函数
}
eg3.父类中定义了一个带整型参数的构造函数,因此编译器不再为它指定参数为空的默认的构造函数。子类中也定义了一个带整型参数的构造函数。编译时,编 译器将试图在子类的构造函数中调用父类的参数为空的构造函数,但是父类中没有定义参数为空的构造函数,所以编译程序将会报错。排错的方法时在子类的构造函 数中显示调用父类的构造函数,或者在父类中添加一个带空参数的构造函数。

public class Sub  extends Sup{
    //子类中定义类一个带整型变量参数的构造函数
    public Sub(int i){
        //
    }
    public static void main(String args[]){
        Sub sub=new Sub(1);
    }
}

class Sup{
    //父类中定义了一个带整型参数的构造函数
    public Sup(int i){
        //
    }
}
   排错方法1:

public class Sub  extends Sup{
    //子类中定义类一个带整型变量参数的构造函数
    public Sub(int i){
        super(i);//调用父类中的构造函数
    }
    public static void main(String args[]){
        Sub sub=new Sub(1);
    }
}

class Sup{
    //父类中定义了一个带整型参数的构造函数
    public Sup(int i){
        //
    }
}
   排错方法2:

public class Sub  extends Sup{
    //子类中定义类一个带整型变量参数的构造函数
    public Sub(int i){
        //
    }
    public static void main(String args[]){
        Sub sub=new Sub(1);
    }
}

class Sup{
    //父类中定义了一个带整型参数的构造函数
    public Sup(int i){
        //
    }
    //定义一个带空参数的构造函数
    public Sup(){
        //
    }
}

二、类方法和实例方法在继承过程中的问题:
  
   首相要明确一个概念,JAVA中通过什么来区别不同的成员——答案是标记。所谓标记,对于方法而言是指方法的名字、参数的数量和参数的类型;对于变量而言是指变量的名称。注意,标记不包括方法的返回值和变量的类型。

   如果子类的实例方法和父类的实例方法具有相同的标记,子类的方法将覆盖父类的方法。但是如果子类的方法和父类的方法具有相同的标记,但是具有不同的返回值类型,编译程序将会报错。排错的方法是修改子类中这个方法的返回值类型,使它父类中相同标记的方法的返回值一样。

public class Sub  extends Sup{
    //子类中的这个方法父类中的方法有相同的标记,
    //但返回值不同,编译程序就会报错
    int test(){
        return  1;
    }
}

class Sup{
    void test(){
        //
    }
}
   排错:

public class Sub  extends Sup{
    //子类中的方法正确覆盖了父类中的方法
    void test(){
        //
    }
}

class Sup{
    void test(){
        //
    }
}
   同样如果子类的类方法和父类的类方法具有相同的标记,那么子类的类方法将隐藏父类的类方法。注意这里不叫覆盖,而叫隐藏,两者的区别将在后面讨论。同样, 如果子类的类方法和父类的类方法具有相同的标记和不同的返回值,编译程序也会报错。解决的问题的方法同实例方法一样。

   但是实例方法不能覆盖类方法,类方法也不能隐藏实例方法,否则编译程序就会报错。
  
   实例方法不能覆盖类方法(编译时报错):
public class Sub  extends Sup{
    //实例方法不能覆盖类方法,编译时报错
    void test(){
        //
    }
}

class Sup{
    static void test(){
        //
    }
}
   类方法不能隐藏实例方法(编译时报错): public class Sub  extends Sup{
    //类方法不能隐藏实例方法,编译时报错
    static void test(){
        //
    }
}

class Sup{
     void test(){
        //
    }
}
   覆盖和隐藏的区别。对于隐藏的方法,运行时系统调用当前对象引用的编译时类型中定义的方法;对于覆盖的方法,运行时系统调用当前对象引用运行时类型中定义 的方法。一个是调用编译时类型中定义的方法,一个是调用运行时类型中定义的方法。通过下面这个例子可以直观的看出两者之间的差别。

class Planet {
    public static void hide() {
        System.out.println("The hide method in Planet.");
    }

    public void override() {
        System.out.println("The override method in Planet.");
    }
}

class Earth extends Planet {
    public static void hide() {
        System.out.println("The hide method in Earth.");
    }

    public void override() {
        System.out.println("The override method in Earth.");
    }

    public static void main(String args[]) {
        Earth earth = new Earth();
        Planet planet = (Planet) earth;
        planet.hide(); // result:"The hide method in Planet."
        planet.override(); // result:"The override method in Earth."
    }
}
   Earth类覆盖了Planet类的override方法,并隐藏了它的hide方法。在main方法中创建了一个Earth的实例,并将此实例转换为一 个Planet的引用。然后通过Planet引用调用override方法和hide方法。hide方法是类方法,因此根据引用的类来决定调用哪个方法, 所以planet.hide()调用的是Planet的类方法hide。override方法是实例方法,因此调用的是运行时的实例中的方法,因为 planet引用的是Earth的实例,因此planet.override()调用的是Earth类中实例方法override。

   JAVA正是通过实例方法的这种覆盖关系来实现多态的目的。

三、类的变量在继承过程中的问题:
  
   如果子类中的变量如果和父类中的变量具有相同的标记——即相同的名字——那么子类中的变量一就会隐藏父类中的变量。不过他们的类型是什么,也不管他们是类变量还是实例变量。只要他们具有相同的名字。

public class Sub extends Sup {
    float i; //子类中的实例变量隐藏父类中的类变量,并且具有不同的类型
    float j; //子类中的类变量隐藏父类中的实例变量,并且具有不同的类型
    int k; //子类中的实例变量隐藏父类中的实例变量
    static int l; //子类中的类变量隐藏父类中的类变量
}

class Sup {
    static int i ;
    int j;
    int k;
    static int l;
}
   同子类中的类方法隐藏父类中的类方法一样,当子类中的变量覆盖父类中的变量的时候,到底使用哪个变量,要根据引用的类型来确定。

   下面是一个类成员继承关系的综合例子:
package basic;

public class Subclass extends Superclass {
    static String staticString = "static String in Subclass";

    String instanceString = "instance String in Subclass";

    static void staticPrintf(float a) {
        System.out.println("static printf method in Subclass");
    }

    void instancePrintf(float a) {
        System.out.println("instance printf method in Subclass");
    }

    public static void main(String args[]) {
        Subclass sub = new Subclass();
        Superclass sup = (Superclass) sub;
        System.out.println(sub.staticString); // static String in Subclass
        System.out.println(sub.instanceString); // instance String in Subclass
        System.out.println(sup.staticString); // static String in Superclass
        System.out.println(sup.instanceString); // instance String in Superclass

        sub.staticPrintf(1); // static printf method in Subclass
        sub.instancePrintf(1); // instance printf method in Subclass
        sup.staticPrintf(1); // static printf method in Superclass
        sup.instancePrintf(1); // instance printf method in Subclass
    }
}

class Superclass {
    static String staticString = "static String in Superclass";

    String instanceString = "instance String in Superclass";

    static void staticPrintf(float a) {
        System.out.println("static printf method in Superclass");
    }

    void instancePrintf(float a) {
        System.out.println("instance printf method in Subclass");
    }
   
}

分享到:
评论

相关推荐

    Java中的方法和变量在继承时的覆盖问题

    变量和方法覆盖和隐藏的不同:一个类的实例无法通过使用全局名或者强制自己转换为父类型,以访问父类中被隐藏的方法,然而强制转换子类为父类型之后,可以访问父类中被隐藏的变量。另外静态方法不能覆盖父类的实例...

    方法和变量在继承时的覆盖和隐藏问题

    最近有个同学问了我一个小问题,觉得很有意思,之前一直没有想到过。他说“java中存在方法覆盖,是否存在变量的覆盖呢?”。

    java继承与多态教学及练习

    1继承的概念 2继承的实现 3变量隐藏与方法覆盖 4super关键字 5 子类的构造顺序 6Object类 7 final关键字

    Java源码小合集:继承和多态相关的例子.rar

    继承和多态的相关Java源码下载,比较散,像覆盖和重载、对象类Object和它的toString()方法、多态性、动态绑定和一般程序设计、数组线性表ArrayList类、final类、方法和变量、数据域和静态方法的隐藏、调用父类的方法...

    Java开发技术大全(500个源代码).

    showDiff.java 演示隐藏与覆盖之间的区别 showSomething.java 测试运行时多态 stupid.java 试图覆盖最终方法的类,它有错误 Sub.java 一个简单的子类 Super.java 一个基类 testOverload.java 测试方法的重载...

    java简答题

    方法的覆盖:在子类中对父类定义方法的重新定义,在子类中将隐藏来自父类的同形态方法。 4-3 Java类的继承有何特点?如何理解接口的作用? 继承是存在于面向对象程序中两个类之间的一种关系。使用继承的主要优点是使...

    10个java主题

    10个JAVA主题,Item 1: 什么时候被覆盖的方法并非真的被覆盖了 Item 2: String.equals()方法与== 运算符的用法比较 Item 3: Java 是强类型语言本 Item 4: 那是构造函数吗 Item 5: ...

    java jdk实列宝典 光盘源代码

    方法和变量在继承时的覆盖和隐藏;排序类; 3数字 数字类;格式化数字;转换数字进制;生成随机数; 4数组和集合 使用Arrays类;动态调整数组长度;java为数据结构中的列表定义了一个接口类java.util.list同时提供了...

    java 编程入门思考

    1.11 Java和因特网 1.11.1 什么是Web? 1.11.2 客户端编程 1.11.3 服务器端编程 1.11.4 一个独立的领域:应用程序 1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 ...

    Java初学者入门教学

    1.11 Java和因特网 1.11.1 什么是Web? 1.11.2 客户端编程 1.11.3 服务器端编程 1.11.4 一个独立的领域:应用程序 1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 ...

    java联想(中文)

    1.11 Java和因特网 1.11.1 什么是Web? 1.11.2 客户端编程 1.11.3 服务器端编程 1.11.4 一个独立的领域:应用程序 1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 ...

    java初学者必看

    尤其是那些和我一样初学Java的朋友们,看看哪一节对你有用,不妨过来讨论一下哦! 第1章 Java概述 1.1 Java的发展史 1.1.1 Java起源 1.1.2 Java发展 1.2 Java是什么 1.2.1 Java语言 1.2.2 Java平台 1.2.3 ...

    java基础教学ppt

    java基础教学ppt,共15章....* 隐藏和覆盖 * 重载、覆盖和重载的区别 * Object类 * 终结类、终结方法 * 抽象类、抽象方法 * 接口 其它不在这里一一说明.如果有感趣的可以自己下载看.

    疯狂JAVA讲义

    5.4 隐藏和封装 132 5.4.1 理解封装 132 5.4.2 使用访问控制符 132 5.4.3 package和import 135 5.4.4 Java的常用包 140 5.5 深入构造器 140 5.5.1 使用构造器执行初始化 141 学生提问:构造器是创建Java对象...

    java学习重点

    多态性 (重载overload,方法名相同、参数的个数不同、参数的类型不同、返回的类型不同和覆盖override) ;多态性就是“一种接口,多种方法”,可以为一组相关的动作设计一个通用的接口,其实类的函数的重载就是一种...

    JAVA_Thinking in Java

    1.11 Java和因特网 1.11.1 什么是Web? 1.11.2 客户端编程 1.11.3 服务器端编程 1.11.4 一个独立的领域:应用程序 1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 ...

    Thinking in Java简体中文(全)

    1.11 Java和因特网 1.11.1 什么是Web? 1.11.2 客户端编程 1.11.3 服务器端编程 1.11.4 一个独立的领域:应用程序 1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 ...

    Thinking in Java 中文第四版+习题答案

    1.11 Java和因特网 1.11.1 什么是Web? 1.11.2 客户端编程 1.11.3 服务器端编程 1.11.4 一个独立的领域:应用程序 1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 ...

    Thinking in java(中文)

    多形性 7.1 上溯造型 7.1.1 为什么要上溯造型 7.2 深入理解 7.2.1 方法调用的绑定 7.2.2 产生正确的行为 7.2.3 扩展性 7.3 覆盖与过载 7.4 抽象类和方法 7.5 接口 7.5.1 Java的“多重...

    Java入门教程(微学苑)-part1

    4 Java继承和多态 61 4.1 继承的概念与实现 61 4.2 Java super关键字 63 4.3 调用隐藏变量和被覆盖的方法 63 4.4 调用父类的构造方法 64 4.5 继承中的方法的覆盖和重载 65 4.6 多态和动态绑定 66 4.7 动态绑定 69 ...

Global site tag (gtag.js) - Google Analytics