【问题标题】:How does a class referenced to itself work?引用自身的类如何工作?
【发布时间】:2011-05-26 15:18:38
【问题描述】:

假设我们有这样一个类:

class XCopy {
    public static void main(String[] args) {
        int orig = 42;
        XCopy x = new XCopy();
        int y = x.go(orig);
        System.out.println(orig + " " + " y);
    }
}

我知道go 方法不见了,但没关系。这应该工作吗?看起来是这样,但我无法在脑海中想象课堂内的自我参考是如何工作的;它有副作用吗?为什么这行得通?这不是某种无限递归循环吗?

无论如何,我只是无法弄清楚这是如何工作的;提前致谢。

【问题讨论】:

    标签: java oop class object


    【解决方案1】:

    通过调用

    XCopy x = new XCopy();
    

    您实际上是在调用 XCopy 的空构造函数,而不是再次调用 main 方法。

    所以,调用看起来像:

    JVM calls XCopy.main();
    main method creates new instance of XCopy by calling XCopy's empty constructor
    XCopy constructor ends
    main method ends -> program ends
    

    【讨论】:

    • 这是一个很好的解释方式,只是为了确定。 Main() 只在程序启动时被调用,并且可以在没有任何类的实例的情况下使用,因为它是一个静态方法,对吗?
    • 是的,main 是静态的,所以 JVM 可以在没有类实例的情况下调用它。
    【解决方案2】:

    我猜你正在看这个并且认为这是一个鸡和蛋类型的问题,但它根本不是。

    如果这是您的第一个 OO 语言,您可能对 Java 的术语感到困惑。 Java有一种叫做“静态方法”的东西。你的 main(String[]) 方法是一个静态方法。这些 static 方法实际上只是普通的旧函数。另一方面,面向对象的方法称为“实例方法”或简称为“方法”。人们经常对术语草率。

    在 Java 中,函数(即静态方法)必须定义在与类相同的位置,并使用该类的名称来标识它。但是,它仍然只是一个普通的旧功能。有时一个类只有一堆松散相关的函数/静态方法。就像 Math 类有一堆关于数学的函数。有时,像字符串这样的更多 OO 类会在 OO 方法中包含一些静态方法/函数。

    在您的程序中,您的主要功能与您的课程无关。但是放在那里作为一个小例子仍然很好。

    当 Java 启动时,总​​是在某处的主函数中启动(你可以告诉它主函数在哪个类中)。

    因此,当您的程序运行时,JVM 会选择您的主函数作为有效的主函数。它运行该功能。它只是一个不需要任何对象的函数。调用 main 不会创建任何对象。

    现在,当您在 main(String[]) 中时,您碰巧在这里创建了一个对象:

    XCopy x = new XCopy();
    

    现在你有了一个 XCopy 类型的新对象,它在主函数的本地范围内由引用(对象指针)x 指向。如果 XCopy 有一个构造函数,它就会被调用。

    所以,如果你想在脑海中想象它,让我用一种虚构的语言为你编写它,它具有更清晰的可视化语法!

    这里是:

    Namespace XCopy 
    {
      function void main(String[]) 
      { 
        int orig = 42;
        XCopy x = new XCopy();
        int y = x.go(orig);
        System.out.println(orig + " " + " y);
      }
    }
    
    Class XCopy
    {
       method int go(int i) 
       {
          ....
          return whatever;
       }
    }
    

    在使用其他语言语法的同一程序中,您可以看到您有一个函数、一个类和一个方法,并且您有该类的一个实例。

    希望有帮助!!

    【讨论】:

    • 这很有帮助。谢谢!
    【解决方案3】:

    为什么会递归? main() 在它自身的任何地方都没有被调用,所以它不会递归。一个类在它自己的成员范围内,所以你可以创建它的实例。

    makeCopy() 方法为例;它需要创建自己类型的另一个对象的实例。

    不要把方法看成是在一个类/对象的“内部”,而从它自身内部调用一个方法的行为是很尴尬的;方法只是一个带有隐式this 参数的函数。

    【讨论】:

      【解决方案4】:

      main 方法是静态的,这意味着它的代码可以独立于存在 Xcopy 实例的事实进行访问。因此,不存在冲突或递归循环。它有自己的内存空间,不同于为每个类实例分配的内存空间。

      【讨论】:

        【解决方案5】:

        main() 是静态的,因此您可以将其视为类的一部分,而不是实例的一部分。它被 OS+JVM 调用并创建一个类的实例。该类恰好是定义 main() 的类,但这并不重要。

        【讨论】:

          【解决方案6】:

          想象一个不同的类:

          public class Person {
            private String name;
            private Person favorite;
            public Person(String name) { setName(name); }
            public void setFavorite(Person favorite) {this.favorite = favorite;}
            public Person getFavorite() { return favorite; }
            public void setName(String name) {this.name = name;}
            public String getName() { return name; }
            public static void main(String args[]) {
              Person a = new Person("Alex");
              Person b = new Person("Becky");
              Person c = new Person("Chris");
              Person d = new Person("David");
              a.setFavorite(b);
              b.setFavorite(c);
              c.setFavorite(c);
            }
          }
          

          所以,亚历克斯最喜欢的人是贝基。贝基最喜欢的人是克里斯。但克里斯是个自恋者。他最喜欢的人是他自己。大卫没有最喜欢的人。可悲的是,没有人认为大卫是他们最喜欢的人。

          当您将自引用的概念应用于具有真实世界语义的事物时,这样的结构是可能的难道不是有意义吗?请注意,设置自引用不会创建副本。这个程序中仍然只有一个 Chris。

          只要你不主动说:“我会问每个人他们最喜欢的人是谁。然后我会问那个人他们最喜欢的人是谁。我不是直到我找到大卫才停下来。因为那样的话,你就有机会永远循环下去。

          【讨论】:

            猜你喜欢
            • 2023-01-12
            • 2013-03-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-09-27
            • 2013-05-02
            相关资源
            最近更新 更多