[Java] Java中override陷阱(参考部分文章)


class Base
{
int a=10;
public void show()
{
  System.out.println(a);
}
}

class Ext extends Base
{
int a=200;
public void show(String s)
{
  System.out.println(s);
}
}

public class MyMain
{
public static void main(String[] argv)
{
  Ext obj=new Ext();
  obj.show();
  obj.show("OK");
}
}


请问,执行上面程序,运行是什么?

10
OK
子类要override父类的方法不但名称要相同同时参数表也要相同,不然就是在子类重新写一个方法并不会override父类的
方法,同时返回值也必须相同,不然会报错。
在JDK5.0中增加了java.lang.Override的Annotation类型解决上述问题,同时实现了返回值不同也不认为是语法错误,也会执行override,示例如下:
java.lang.Override是J2SE 5.0中标准的Annotation型态之一,它对编译器说明某个方法必须是重新定义父类别中的方法,编译器得知这项资讯后,在编译程式时如果发现该方法并非重新定义父类别中的方法,就会回报错误。

举个例子来说,如果您在定义新类别时想要重新定义toString()方法,您可能会写成这样:

CustomObject.java 
public class CustomObject {   

     public String ToString() {       
             return "customObject";  
     }
} 

在撰写toString()方法时,您因为打字错误或其它的疏忽,将之打成了ToString(),但您编译这个类别时并不会出现任何的错误,编译器只当您是定义了一个新的ToString()。

您可以使用java.lang.Override这个Annotation型态,在方法上加上一个@Override的Annotation,告诉编译器您现在定义的这个类别是重新定义父类别中的同名方法,例如:

CustomObject.java 

public class CustomObject {
    @Override
    public String ToString() {
        return "customObject";
    }
}


在编译程式时,编译器看到@Override这个Annotation,了解它必须检查这个方法是不是重新定义父类别的ToString()方法,但父类别中并没有这个方法,所以它会回报错误:

CustomObject.java:2: method does not override a method from its superclas
@Override
^
1 error



重新修改一下程式,编译时就不会有问题了:

CustomObject.java 

public class CustomObject {
    @Override
    public String toString() {
        return "customObject";
    }
}


java.lang.Override是个Marker annotation,简单的说就是用于标示,annotation名称本身即包括了要给工具程式的资讯。

 

========================
关于这道题目,我给出了一个简单的原则,现在有空顺便说
清楚一点这个有趣的现象。

首先要说明,我认为,属性并非不可以override,
成员变量是可以override的,但是成员变量是在编译时解析的
(而方法是在运行时解析的)

这样一来,当子类要引用父类对象的属性时,实际上它会屏蔽
自己的同名属性,只去访问父类对象的属性,所以直接引用
变量名和通过方法来获取变量的效果是不一样的,
这里有个非常好的例子,有时间好好看看,想想

public class Shadow {
  public static void main(String s[]) {
    S1 s1 = new S1();
    S2 s2 = new S2();
    
    System.out.println(s1.s); // prints S1
    System.out.println(s1.getS()); // prints S1
    System.out.println(s2.s); // prints S2
    System.out.println(s2.getS()); // prints S2

    s1 = s2;
    System.out.println(s1.s); // prints S1, not S2 - 
                      // since variable is resolved at compile time
    System.out.println(s1.getS()); // prints S2 - 
                     // since method is resolved at run time    
  }
}

class S1 {
  public String s = "S1";
  public String getS() {
    return s;
  }
}

class S2 extends S1{
  public String s = "S2";
  public String getS() {
    return s;
  }
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值