【问题标题】:Why cannot I assign a value to the object reference being returned by a method?为什么我不能为方法返回的对象引用赋值?
【发布时间】:2020-02-11 09:11:37
【问题描述】:

我有一个返回对象引用的函数。为什么我不能分配这个返回的引用指向另一个对象?函数返回的引用不是 final 的,因此我应该被允许更改它的值以指向另一个对象。

class TestClass3 {
    public TestClass3 hello() {
        TestClass3 t = new TestClass3();
        return t;
    }
}

class TestClass1 {
    public static void main(String[] args) {
        TestClass3 obj = new TestClass3();

        // The below line of code gives an error
        obj.hello() = null; 
    }
}

我希望调用 hello() 方法返回的引用应该被赋予空值。

【问题讨论】:

  • 您正在尝试将方法设置为一个值。这是不可能的,也没有意义。
  • 您的预期结果对我来说毫无意义。 在执行someVar = null 时实际上并没有操作内存中的对象,该对象保持在原处,垃圾收集器将清理它。为什么“设置对 null 的引用”没有意义,Java 不提供这样的功能。您可以将变量设置为 null 以不再使用某个引用。
  • @Tom 是的,编译器已经抛出错误。测试一下。问题是:您只能为变量赋值。他想给一个值赋值(引用计数一个值,它不是一个变量),这是不可能的
  • @Patrick 我在哪里声称它不会引发编译器错误?而且我不需要测试它,我知道 Java 是如何工作的。还要感谢您向我解释我已经向 OP 解释过的内容。

标签: java oop reference variable-assignment


【解决方案1】:

您正在尝试将方法设置为一个值,如果您考虑一下,这是不可能的并且没有任何意义。如果要保存obj.hello()返回的引用,写

TestClass3 obj2 = obj.hello();

【讨论】:

    【解决方案2】:

    您需要将obj.hello() 分配给一个变量,然后您可以根据需要将其设置为null

    【讨论】:

      【解决方案3】:

      在你写obj.hello()的代码中,它只调用方法hello。它不会将hello 的返回值分配给任何变量。所以实际上没有变量保存方法hello 的返回值。虽然您可以将空值分配给同一个变量。这就是为什么它不是一个有效的语法。

      有效的语法应该是这样的:

      TestClass3 value = obj.hello();
      value = null;
      

      【讨论】:

        【解决方案4】:

        简单地说,这是因为 Java 不允许这样做,而有些语言(例如 Python)允许这样做。在 Java 中,你不能 monkey-patch 现有代码。

        为什么?好吧,Java 并不是作为一种函数式语言诞生的,因此尽管在 Java 8 中添加了相当多的函数引用,但它们仍然不是一等公民。因此,您不能像使用该类的字段那样为该类的方法分配新值。

        但是,由于您可以为字段分配值,因此您可以执行以下操作:

        class TestClass3 {
        
            public Supplier<TestClass3> hello;
        
            public TestClass3() {
                this.hello = this::hello;
            }
        
            public TestClass3 hello() {
                TestClass3 t = new TestClass3();
                return t;
            }
        }
        
        class TestClass1 {
            public static void main(String[] args) {
                TestClass3 obj = new TestClass3();
                obj.hello.get(); // calls hello()
                obj.hello = null; // now works
            }
        }
        

        这里我在TestClass3 中定义了一个名为hello 的成员。它属于Supplier&lt;TestClass3&gt; 类型,而public TestClass3 hello() 恰好属于同一类型。因此,在TestClass3 的构造函数中,我可以这样做:this.hello = this::hello;

        现在我们将hello() 引用为一个字段,这意味着我们可以使用该字段调用函数,甚至可以更改该字段的值:

        obj.hello.get();
        obj.hello = null;
        

        【讨论】:

          【解决方案5】:

          obj.hello()对象的行为,不是引用,只有引用才能设置为null。

          关于空:

          • null 只是一个参考值
          • reference是一个有名字的变量,可以通过引用它所在的内存地址来访问一个对象

          关于对象:

          所有对象都具有三个基本特征:

          • 状态
          • 行为
          • 身份

          【讨论】:

            猜你喜欢
            • 2012-02-22
            • 2018-06-13
            • 2011-06-28
            • 1970-01-01
            • 2015-05-01
            • 2011-06-19
            • 2019-12-25
            • 1970-01-01
            相关资源
            最近更新 更多