注册两个月了,散分.写了点java中比较容易混淆的东西,欢迎大家排砖.
初学者甚至老手都容易混淆的问题
1.关于继承
继承有几个比较典型的问题:
a.子类可以继承父类的一切属性和方法。父类中声明为private的method或者field,创建子类的对象之后,父类中定义的field都会在子类的对象中占据空间,也就是分配内存。只是有的属性子类可以直接访问,有的必须通过父类提供的public或者protected方法来访问。private只是声明可见性,你看不到不等于不存在。
b.方法可以覆盖,但是field不可以。Fields cannot be overridden; they can only be hidden. 
如果子类中定义了和父类同名的属性,父类中定义的属性可以通过super来访问。
c.private的方法不能被覆盖,但是你可以在子类中重新定义一个和父类中的方法签名相同的方法,这不是覆盖,因为子类是看不到父类中的private方法的。
d.Static members within a class whether fields or methods cannot be overridden, they are always hidden. 
2.关于方法调用时的值传递
   这个问题已经争论了好多次了,简单的引用一下书里的说法。
   Core Java:The term call by value means that the method gets just the value that the caller provides. In contrast, call by reference means that the method gets the location of the variable that the caller provides. Thus, a method can modify the value stored in a variable that is passed by reference but not in one that is passed by value. The Java programming language always uses call by value. That means that the method gets a copy of all parameter values. 
   The Java Programming Language:All parameters to methods are passed "by value." In other words, values of parameter variables in a method are copies of the values the invoker specified as arguments.You should note that when the parameter is an object reference, it is the object reference not the object itselfthat is passed "by value." 
   The Java Tutorials:Primitive arguments, such as an int or a double, are passed into methods by value.Reference data type parameters, such as objects, are also passed into methods by value. 
   sun的很多认证材料上的说法也是pass by value.
   大家可以在google中搜一下java ,pass by reference,看看结果
   很多人坚持pass by reference的说法,一直也不知道这个术语是谁提出来的。希望专家指正来源。
3.关于重载和多态
   多态是面向对象的特性之一,理解也不是特别困难,但是最近发现很多人喜欢把多态和覆盖(Overriding,暂且这么翻译吧)搅在一起。其实自己刚开始学的时候也曾经有过困惑,什么叫做重载(Overloading),什么叫做覆盖(Overriding),后来看书多了也就慢慢理解了,大体的总结一下:    重载是方法之间的一种关系,多个方法使用相同的方法名,但是签名不同,所以我们可以通过签名来区分。早期的java中因为没有采用模板机制,所以大量的方法都是采用重载的方法写成的,比如最经典的System.out.println();在代码里有十种实现方法,接受各种不同类型的参数。这是 Overloading。
    覆盖是类层次结构中的一种关系,比如父类有某个方法,子类中同样实现一个同名并且签名相同的方法,这种情况我们称之为overriding。注意,这里要求签名相同。但是返回值可以有些许不同,这里的不同指的是子类中重写的方法可以返回父类中返回类型的子类型,说起来很绕,简单的举个例子,如果父类中方法的返回类型是Number类型,那么子类中的这个覆盖方法的返回类型可以是Number类型,也可以是其子类型,比如Integer,Double等等。
    这样两个概念的区别已经很明了了,而且也应该知道,覆盖是实现多态的关键技术。
    两个概念还有个重要的区别是,重载是静态绑定的,因为编译的时候编译器就可以根据签名确定具体要调用的方法,而覆盖是运行时绑定的,因为运行的时候才能根据运行时类型信息,确定具体要调用哪个类中定义的覆盖方法。这里面其实有方法表的概念,具体可以参考Core Java.
    最后,引经据典,配合一下自己的说法。
    《The Java Programming Language》中:
   
      Overloading a method is what you have already learned: providing more than one method with the same name but with different signatures to distinguish them.
     Overriding a method means replacing the superclass's implementation of a method with one of your own. The signatures must be identicalbut the return type can vary in a particular way, as discussed below.

解决方案 »

  1.   

    在Thinking in java中看到过pass by reference的说法.
      

  2.   

    呵呵,跟LZ探讨一下:
    1.a子类可以继承父类的一切属性和方法?
        如果private的method可以继承的的话,为什么不可以overriding?
    2.pass by reference
    class Ob {
    private int t = 0;
    public Ob(int i){
    t = i;
    }

    public int getT(){
    return t;
    }

    public void setT(int i){
    t = i;
    }
    }public class Test {
    public static void change(Ob o, int t){
    o.setT(t);
    }

    public static void main(String[] args){

    Ob b = new Ob(8);
    Test.change(b, 4);
    System.out.print(b.getT());
    }
    }
    输出是4,那不是by reference吗?
      

  3.   

    我看过TIJ第四版,不过没看到过这个说法.
      

  4.   

    在Thinking in java第三版的一个中文译本中第二章有这么一段(我只是粘贴出来,不代表我的观点):参数列表方法的参数列表会告诉你应该向方法传哪些信息.或许你也猜到了,按照Java"万物皆对象"的法则,这种信息应该是以对象的形式出现的.所以实际上参数列表就是传给方法的对象类型和名字. 由于,不管在哪种情况下, Java传递对象的时候,实际上是在传reference, 因此reference的类型必须正确.如果参数说要一个String,那你就必须传给它String,否则编译器会报错.
      

  5.   

    关于pass by value or pass by reference的争论已经看过无数次了,现在我也拿不准到底是什么.只是贴出来供参考而已.我也没有找到有说服力的例子.
      

  6.   

    不太喜欢说pass by value也不喜欢pass by reference
    喜欢把它理解成pass by the copy of the object
      

  7.   

    这种理解肯定是错误的,因为对于引用类型是引用的copy 值,而不是对象.
      

  8.   

    The term call by value means that the method gets just the value that the caller provides. In contrast, call by reference means that the method gets the location of the variable that the caller provides. Thus, a method can modify the value stored in a variable that is passed by reference but not in one that is passed by value.
      

  9.   

    Thinking in Java第四版中有一段说明,关于pass by value的,作者表示它的方式只是为了方便理解.注意作者并没有提出pass by reference的说法.
      

  10.   

    Passing Reference Data Type Arguments
    Reference data type parameters, such as objects, are also passed into methods by value. This means that when the method returns, the passed-in reference still references the same object as before. However, the values of the object's fields can be changed in the method, if they have the proper access level.For example, consider a method in an arbitrary class that moves Circle objects:    public void moveCircle(Circle circle, int deltaX, int deltaY) {
            // code to move origin of circle to x+deltaX, y+deltaY
            circle.setX(circle.getX() + deltaX);
            circle.setY(circle.getY() + deltaY);
        
            //code to assign a new reference to circle
            circle = new Circle(0, 0);
        }Let the method be invoked with these arguments:    moveCircle(myCircle, 23, 56)Inside the method, circle initially refers to myCircle. The method changes the x and y coordinates of the object that circle references (i.e., myCircle) by 23 and 56, respectively. These changes will persist when the method returns. Then circle is assigned a reference to a new Circle object with x = y = 0. This reassignment has no permanence, however, because the reference was passed in by value and cannot change. Within the method, the object pointed to by circle has changed, but, when the method returns, myCircle still references the same Circle object as before the method was called.
      

  11.   

    James Gosling等人的说法:
    Some people will say incorrectly that objects are passed "by reference." In programming language design, the term pass by reference properly means that when an argument is passed to a function, the invoked function gets a reference to the original value, not a copy of its value. If the function modifies its parameter, the value in the calling code will be changed because the argument and parameter use the same slot in memory. If the Java programming language actually had pass-by-reference parameters, there would be a way to declare halveIt so that the above code would modify the value of one, or so that commonName could change the variable sirius to null. This is not possible. The Java programming language does not pass objects by reference; it passes object references by value. Because two copies of the same reference refer to the same actual object, changes made through one reference variable are visible through the other. There is exactly one parameter passing modepass by valueand that helps keep things simple.
      

  12.   

    http://www.ibm.com/developerworks/java/library/j-passbyval/
    ibm社区的一个文档,大家可以看看.
      

  13.   

    C++里的引用和java里的引用稍有不同,我觉得应该是两种人对引用的理解不同遭成的
    8种基本类型肯定是value传递,对于对象类型,传进去reference的时候,方法会将这个reference复制一份而并不是
    直接使用它,每一个reference也有值的,就是它所对应的对象在堆中的地址,方法将这个值接收然后赋给了方法中的局部变量,
    这大概才是值传递的本意。
    ------一个菜鸟的见解
      

  14.   


    如果debug跟踪,method内部与外部在堆中的地址也都是一样的
      

  15.   

    知名美资本金融IT公司:英语PM(JAVA 开发方向)
    http://www.racecareer.com/search-nr.asp?id=269日语PL(JAVA 开发方向)http://www.racecareer.com/search-nr.asp?id=294
    如果点击无效 ,请将链接复制到地址栏[email protected]
    Tina:88122571
    MOB:138 8946 0104
      

  16.   

    用eclipse,在method外设个断点,然后debug方式运行,一步一步F5,察看那个参数对象的信息.id等是一样的
      

  17.   

    同意33楼。
    借用一切皆是对象的思想,这里也可以说一切都是值。reference也是可以做为值来传递的。个人认为如果是在C++里就不会有这种争辩,因为指针弄得通,这个就是小问题,说白了所谓的reference传递,也就是传地址。
    反正我是这么理解的,请更正
      

  18.   

    如果按照4楼例子,你的值传递是传递b,而不是你new出来的Ob实例
      

  19.   

    真晕.
    从java语言的设计哲学来说为了简化都设计为值传递了,而且我看到的资料都是这个说法.
    看来该重新设计java语言了,真无聊.
      

  20.   

    对,用google查外语资料都是pass by value
    到中国就不一样了.
      

  21.   

    java的设计都是OO的,所以"值"("value")这个字眼除了基本类型外,对于java来说都是...其实,pass by reference与pass by value的概念区别是传入的参数是否在函数内部被改变.
    对于一个developer来说(至少是我吧),不管是copy,
     还是真reference,都是'reference'(因为都指向了一个Object,而非value)
    这样,我在develop的时候,知道参数在函数内部是可以被改变的。
      

  22.   

    呵呵是啊,等咱们搞个语言,译成english的,同一个意思译成多个english的。气死老外们。(故意将English小写的)
      

  23.   

    Mark!!!LZ总结得挺好,以后再也不参加JAVA的pass by reference的讨论了。
    Core Java中说这么清楚了,连什么是pass by reference都说清楚了,还有什么好讨论的,呵呵曾经在http://www.cjsdn.net/post/view?bid=1&id=195048&sty=1&tpg=1&age=0参加过讨论,没读过知道Core Java,只是自己直观的理解,说服力不强,郁闷!
      

  24.   

    谢谢支持,感觉最权威的还是James Gosling的说法,毕竟人家设计了Java :
    There is exactly one parameter passing modepass by valueand that helps keep things simple.
      

  25.   

    Everything is a reference, it's just passed by value of the reference.
      

  26.   

        Java 编程语言只有值传递参数。
        当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的属性内容可以在被调用的方法中改变,但对象的引用是永远不会改变的。
      

  27.   

    关于传值还是传引用主要是能正确把握就行,我认为基本类型和基本类型变量被当作参数传递给方法时,是值传递。在方法实体中,无法给原变量重新赋值,也无法改变它的值。 
    对象和引用型变量被当作参数传递给方法时,在方法实体中,无法给原变量重新赋值,但是可以改变它所指向对象的属性。至于到底它是值传递还是引用传递,这并不重要,重要的是我们要清楚当一个引用被作为参数传递给一个方法时,在这个方法体内会发生什么。 我来具体谈一谈,方法重载与方法重写的区别:
    方法重载
     在Java中,如果要在同一个类中写多个相同的名字的方法,那么只需要这些方法的参数不同就行.这个过程称为方法重载.方法重载是多态性的一种,也是Java的特征之一.所谓多态性,是指可以向功能传递不同的消息,以便让对象根据相应的消息来产生一定的行为.对象的功能通过类中的方法来实现,那么功能的多态性就是方法的重载.
      方法重载可以概括为一句话:同名不同参.不同参可以是指不同类型的参数,也可以是参数的数量不同.其中方法的返回类型及参数的名字与之无关.例如:Class A{
           void test(){}
           int test(){}       //非法,因为方法重载与返回类型无关
    }方法重写(继承下的重写)
      子类可以通过方法重写来隐藏继承父类的方法.方法重写是指,子类中定义了一个方法,并且这个方法的名字、返回类型、参数类型及参数的个数与从父类继承的方法完全相同。通过方法重写,子类就可以把父类的状态和行为变成自己的状态和行为。只要父类的方法能够被子类继承,子类就能重写这个方法。一旦子类重写了这个方法,就表示隐藏了所继承的这个方法。如果子类对象调用这个方法,那也是调用重写后的方法。
    来看一个方法重写的例题。
    class A{
        void smile()
        {
            System.out.println("我考试得了第一,我很高兴!");
        }
        void cry()
        {
            System.out.println("看完这部电影,我感动的哭了...");
        }
    }class B extends A{
        B(){
            smile();
            cry();
           }
           void smile()
           {
            System.out.println("我找到了一份好工作,我太高兴了!")
            }
    }class RewriteTest{
        public static void main(String args[])
        {
            B b= new B()
        }
    }
    输出结果为:我找到了一份好工作,我太高兴了!
                看完这部电影,我感动的哭了
                Press any key to continue...
        在这个程序中,类B继承类A后,重写了父类的smile()方法。从输出结果我们可以看出父类(类A)的smile()方法中的语句并没有打印出来。
        重写方法既可以操作继承的成员变量,也可以操作子类声明定义的成员变量。如果子类想调用被隐藏的方法,必须使用关键字super.
    以上是我对重载和重写概念的理解,欢迎各位批评指正。
      

  28.   

    意思都理解,说法我不是很赞同.
    我看国人的书上有人提出了方法多态的概念,就是指的这个overloading.但这个概念其实跟面向对象一点关系都没有.
    我们一提到面向对象,就提到三个特性,继承,多态,信息隐藏.多态可以看作是面向对象的本质特征之一.那方法的重载跟它有什么关系呢?
    像C++这样的语言就可以直接定义方法重载而不涉及任何面向对象的东西.
    而且方法的overloading是静态绑定的,跟多态那种运行时的表现也有本质的区别.
    所以还是不要提这个方法多态的好.
      

  29.   

    b.方法可以覆盖,但是field不可以。Fields cannot be overridden; they can only be hidden. 
    如果子类中定义了和父类同名的属性,父类中定义的属性可以通过super来访问。 对这个不是很理解 :)父类中overriding的method也可以通过super 来访问的
      

  30.   

    没有pass by reference只有pass by value~