今天看了头版那几个版主推荐的贴子其中JAVA面试题解惑系列(三)——变量(属性)的覆盖这个贴子  我看了后有很多不解首先覆盖一说,贴子所讲的覆盖跟我所理解的继承关系的覆盖就有偏差,我是新手,可能是我的问题。我见众多五角星的高手多回复道“学习了”  外加那贴子有斑竹推荐   那肯定是我理解的覆盖有问题吧
我理解的覆盖就是:子类继承父类   子类中的变量名字可以跟父类的名字一样     叫他覆盖的原因就是子类可以包含父类的变量 且子类变量和父类变量名字一样   这就产生了覆盖(子类变量覆盖父类变量)讨论覆盖应该是举例new子类对象 然后看引用他的是父类还是子类的引用变量。这样才能说明些问题贴子中所有new父类对象的语句我认为是毫无意义。莫非子类变量能把父类的覆盖掉?以后父类的那个变量将永远被子类同名变量压在下面永不翻身?推荐的那个贴子:讲了一大堆不知所云的东西。
拿在一个java文件下的代码给大伙讲访问修饰符,不解,要讨论访问修饰符的话,最起码也来个package吧。
为了访问private变量,还来了个getPrivateFieldValue()方法,调用的话那是方法的动态绑定,跟覆不覆盖也没啥关系看了那贴我没发现得到了解惑,反而以前没觉得是问题的东西,现在变得迷惑了。
不知什么叫做覆盖。class T1

final String s="super";
}class T2 extends T1
{
final String s="sub"; public static void main(String[] args)
{
T1 t = new T2();
System.out.println(t.s);
}
}//输出是super,那贴子说不能覆盖,没覆盖的话为什么new的是子类对象,却可以输出super? 我认为是覆盖了。
//另外那贴子的很多结论都让人很迷惑。

解决方案 »

  1.   

    此回复为自动发出,仅用于显示而已,并无任何其他特殊作用
    楼主【jingulang】截止到2008-07-17 11:17:11的历史汇总数据(不包括此帖):
    发帖的总数量:26                       发帖的总分数:720                      每贴平均分数:27                       
    回帖的总数量:368                      得分贴总数量:143                      回帖的得分率:38%                      
    结贴的总数量:24                       结贴的总分数:650                      
    无满意结贴数:2                        无满意结贴分:40                       
    未结的帖子数:2                        未结的总分数:70                       
    结贴的百分比:92.31 %               结分的百分比:90.28 %                  
    无满意结贴率:8.33  %               无满意结分率:6.15  %                  
    值得尊敬
      

  2.   

    可以这么理解:
    两个s是单独, 一个父亲的。一个是孩子,他们没有任何关系。你new 出孩子向上转型成父亲以后,t当然不能访问子类有而父类没有的属性,
    它只能访问父类有,子类覆盖的,或者父类有,子类没有的。
      

  3.   

    楼上位手真快,刚看完就到五楼了覆盖是对方法而言的,而不是对变量而言的,LZ贴的代码输出当然是super
      

  4.   


    public class Test{
        public static void main(String[] args) {
          Super s=new Sub();
          s.print();//Sub覆盖了超类中的print()方法,因为s是Sub()类的对象,所以这里调用的是Sub()的print()方法,
          //当然sub访问到的只能是sub类中的name了。
          s.printSuper();//子类没有覆盖此方法,调用的是父类的,所以输出的是父类中的name
          System.out.println(s.getName());//s.getName(),子类没有覆盖也是调用父类的,所以输出的是父类的name
        }
    }class Super{
        public  String name="super";
        public void print(){
            System.out.println(name);
        }    public void printSuper(){
            System.out.println(name);
        }
        
        public String getName() {
            return name;
        }    public void setName(String name) {
            this.name = name;
        }    
    }class Sub extends Super{
        public String name="Sub";    @Override
        public void print() {
            System.out.println(name);
        }
        
    }
      

  5.   

    子类从超类继承下来了一个 s 自己又添加了一个实例域 s,这样当创建了一个子类实例时它内部就保存有两个都叫 s 的实例域的值,当我们从这个子类对象外部去访问 s 只能看到和访问到子类自己定义的 s 的值,而打父类继承下来的 s 被子类的 s 给遮盖住了(这个就是你说的所谓覆盖,当你站在别人前面时我只能看到你,但不等于被你挡住的人就不存在了),所有访问不到被遮住的父类继承下来的那个 s。而当我们从子类对象内部去访问 s 时,基于同样道理我们只能看到子类自己的 s,当想访问超类定义的 s 时要用 super 来限定,即 super.s(前提是有访问权限,即如果子类和超类在同一个包内那超类的 s 的访问级别应该是“默认的”、protected 或 public,分处不同包时超类的 s 的访问级别应该是 protected 或 public)。
      

  6.   

    若没看错 楼主说的这种情况应该是隐藏(hidden) 翻译区别于覆盖,因为容易与override混淆子类对父类的继承可能导致各种陷阱,比如隐藏(hidden),遮蔽(shadow),遮掩(obscure),覆写(override),重载(overload)等行为。 
      

  7.   

    来看看2个隐藏的例子:1.
    class Base {
        public String className = "Base";
    }class Derived extends Base {
        private String className = "Derived";
    }public class PrivateMatter {
        public static void main(String[] args) {
            System.out.println(new Derived().className);
        }
    }
    我们可能指望它打印Base,可很抱歉,此程序是无法编译通过,刚一看错误信息你可能愣住:无权访问private的className对于实例方法,子类可以对父类的实例方法进行覆写,可对于实例变量(而且包括类变量,静态方法,final静态变量),子类只能隐藏父类中的相同名称的变量,而不是覆写。根据new Derived()的编译期类型为子类Derived,调用子类的className属性,可此属性是声明为private的,所以无法编译通过。如果我们想调用父类中被隐藏的className,可以通过向上转型来实现:System.out.println(((Base)new Derived()).className);此例告诉我们,JAVA语言中子类定义与父类相同类型和名称的变量、嵌套类型和静态方法,都将隐藏掉父类中相应的方法,而不是覆写,所以,请避免隐藏!此过程中当然也不存在所谓多态。另外,我们不应该违反这样一条规则:对基类所做的任何行为,都应当可以同样作用于子类。此例中子类className为private,违反了基类中className是public的定义,这样的写法应该避免。 2.也许哪一天你突然想自己写一个String来代替java.lang中的String,让我们来看看会发生什么?public class StrungOut {
        public static void main(String[] args) {
            String s = new String("Hello world");
            System.out.println(s);
        }
    }class String {
        private final java.lang.String s;    public String(java.lang.String s) {
            this.s = s;
        }    public java.lang.String toString() {
            return s;
        }
    }试运行此程序,JVM会给你一个非常奇怪的消息:StrungOut does not have a main method!怪了,明明有个main方法啊??请注意,main方法中的参数String []args,其中的String类型要求是java.lang.String,可JVM会自动地把把这些参数认为是我们自定义的下面那个String类型,这就是错误的原因所在。教训:避免重用类名,特别是java平台的类型,特别是java.lang包下的类名!在此例中,当前类所在包中的所有类的main方法都将因此失效。
      

  8.   

    刚浏览了原贴,不知楼主从何判断原贴说不能“覆盖”
    这种情况就是“覆盖”
    感觉确实hidden要好些
      

  9.   

    赞楼上,以前研究String代码的时候,也自己写过一个String,不过跟java.lang.String冲突很多,因为String本身内部使用了大量的java.lang.String
      

  10.   


    学习了,搞半天,我还以为子类把父类的变量给吞了呢
    晕~~~~~~~~~~~~~
    可以用super去访问就说明没被吞哦
    那方法又怎么说呢,同样也可以用super去访问,莫非也只是重定向了而已(override重写)?
    被重写了的父类方法是怎么存储在子类中的?啊!!!!!头疼!
      

  11.   

    我在那个帖子的发言:我认为:java不存在属性覆盖,无论这个属性被什么修饰符修饰(public,static,final,protected... ...)。得到最终结果只与该对象的引用的类型有关。
    SubClass subClass = new SubClass();此时使用 subClass.属性 ,得到的都是子类的属性。
    ParentClass subClass = new SubClass();此时使用 subClass.属性 ,得到的都是父类的属性。 不知道有不同意见没?
      

  12.   

    赞同25楼!!感觉好像只是变量作用域的问题
    在子类中,如果有与父类同名的变量,在子类中直接使用该变量,将不能得到父类中定义的值,而需要用super去使用(前提可访问)
    如果在外部引用,那将取决于引用的方式,以父类引用得到父类的值,以子类引用得到子类的值所以用hidden,只不过是scope的问题对照方法,又有点晕了,方法的话可以实现override,也就是多态的基础
    在外部引用时,声明为父类,定义为子类,实现了override的方法就会调用子类的,但同样在子类中可以用super去调用父类被ovrride的方法,为什么呢?怎么会不一样呢?
      

  13.   

    学习一下。个人认为,搞清语法固然好。但在实际code时最好还是"写"明白,尽可能避免这些让人误解的写法。
      

  14.   

    呵呵,
    1,首先方法中叫覆盖(override)可以,同事用final、private、static修饰的方法不能被重写,但是可以被重载,
    2,至于属性应该称之为隐藏(hidden),