27

当我尝试以下操作时,Eclipse 将给出错误“赋值的左侧必须是变量”:

public class Thing{

  String a1;
  int a2;

  public void meth(){
    Thing A = new Thing();
    this = A;
  }
}

我必须分配每个变量 ( this.a1 = A.a1; this.a2 = A.a2;) 作为解决方法。

有没有其他方法可以在不遍历每个变量字段的情况下做到这一点?
如果this不是变量,它叫什么?

4

12 回答 12

72

this是一个指向对象当前实例的伪变量,它不能被重新赋值。根据Java Language Specification的第3.9节,它也被视为语言中的关键字。

于 2012-12-12T20:40:15.627 回答
24

不,没有简单的捷径。

如果“this”不是变量,它叫什么?

this不是变量,而是关键字

尽管this很特别,但在许多方面它就像一个参考。因此,为了一致性,this = A必须是一个参考分配,这不太有意义。

您似乎期望从tothis = A执行逐个字段的复制,并且在这种情况下,Java 的设计者确实可以选择这样做。但是,这将与其他参考分配不一致,并且将其作为例外的整体好处并不明确。Athis

于 2012-12-12T20:40:04.910 回答
10

thisthis类的实例。

您不能分配给this

于 2012-12-12T20:40:08.717 回答
9

是一个java保留关键字,它指的是当前对象。它不是一个变量,它是一个 java 保留关键字。所以this = A;无效。使用this关键字我们可以引用当前对象的任何实例变量或方法。您必须引用实例变量,例如:

this.a1 = A.a1;

来自文档

使用 this 关键字的最常见原因是字段被方法或构造函数参数遮蔽。

于 2012-12-12T20:40:14.457 回答
6

您不能this在 Java 中分配给。这不是一个变量;这是一个关键字。

如果您不需要特定实例,您可能会考虑的一件事就是returning 您的新实例。

public class Thing{

  String a1;
  int a2;

  public Thing meth(){
    Thing A = new Thing();
    return A;
  }
}

你会像这样使用它

whatever = whatever.meth();
于 2012-12-12T20:41:41.530 回答
5

根据java lang spec §15.8.3 this是一个关键字,它可以是表达式语句

  1. 当用作主要表达式 this时,表示一个值,该值是对其调用实例方法的对象的引用。
    • 表达式:求值的东西。示例:x++
  2. 关键字 this 也用于特殊的显式构造函数调用语句
    • 语句:控制程序执行的句法元素,其执行是为了它们的效果并且没有值示例:if (true)

无论哪种情况,它都不是变量

  • 变量:具有关联类型的存储位置

在你的情况下this是一个表达式而不是一个变量。但是出于所有目的,只需将其称为关键字

  • 关键字:由 ASCII 字母组成的字符序列,保留使用......不能用作变量名
于 2012-12-13T04:07:39.873 回答
1

this指方法的所有者。在这种情况下,所有者就是对象本身。

有时,this可能不会引用您正在编写代码的类。比如在匿名类中。一个常见的例子是匿名监听器。

 button.addActionListener(
        new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                this; // refers to the ActionListener
            }
        }
    );

此外,您可以返回this可以做method chaining的。假设您有一个名为 Homework 的类,它有一个方法 addTask。

public Homework addTask(String task){
return this;
}

你可以像这样调用addTask方法

homework.addTask("a").addTask("b").addTask("c");
于 2012-12-12T20:50:28.717 回答
1

我认为 OP 要求能够将一个对象的内容分配给另一个对象,而不是为“this”指针分配一个新值。C++ 具有这种能力——您可以覆盖赋值运算符——但 Java 没有这种能力。

在某些偶尔的情况下,这将是一个不错的功能,但目前根本不可能,而且它并不真正适合 Java“模具”以在未来提供该功能。

如果 Java 允许将对象嵌入到其他对象中(而不是简单地嵌入引用),则该功能将更有用(并且会有更多提供它的动机),但这也不在卡片中。

于 2012-12-13T01:40:41.333 回答
0

在基本的 Java 语言中,没有一种方法可以将所有字段的值从一个实例复制到另一个实例。而且您通常不需要它。您通常可以只替换对新实例的引用或直接在目标实例上工作。

在您的情况下,当您想要将对象的所有字段重置为初始值(并且很少需要它)时,您通常使用重置方法,该方法适用于自己的实例,或者是适用于任何给定对象的静态方法.

所以

class A {
  String a1; int a2;
  void reset() { a1 = ""; a2 = 0; }
}

将被用作

A a = new A();
// modify a
a.reset();

class A {
  String a1; int a2;
  static void reset(A anotherA) { anotherA.a1 = ""; anotherA.a2 = 0; }
}

并像这样使用它:

A.reset(a);

在这两种情况下,使用 reset 方法也可以在构造函数中设置初始值:A() { A.reset(this); }A() { this.reset(); }

1实际上有一些库可以做到这一点,你可以在反射的帮助下对其进行编码,我看到它被使用的唯一原因是实现一个 clone() 方法或某种包装/存根。

于 2012-12-13T01:31:57.043 回答
0

在我看来,你想要做的是有一个方法来重新初始化你的对象,即将它设置回它的初始值。这就是为什么您要创建一个新对象并将其分配给当前对象的原因,对吗?

如果是这种情况,让我们尝试一种不同的方法,因为正如前面所说,你不能 reassign this

如果您不这样做,而是尝试这样的事情怎么办:

public class Thing {

    String a1;
    int a2;

    public Thing() {
        this.meth();
    }

    public void meth() {
        this.a1 = "a1";
        this.a2 = 2;
    }

}

这样, Thing.meth() 实际初始化您的对象,并且构造函数在创建对象时调用它。然后,您可以随时再次调用它。

于 2012-12-13T02:55:50.630 回答
0

==免责声明,我不知道java ==

你会想要手动分配。

我不确定您为什么要尝试在 Thing 中创建 Thing 的新实例,但是由于您没有设置 a1 和 a2 的值,因此您需要按照您的方式分配它们。

这是一个保留关键字,指向它所在的类对象。

例如,如果您想要另一个名为 fish() 的函数,您的代码可能看起来像这样。

public class Thing{

  String a1;
  int a2;

  public Thing meth(){
    Thing A = new Thing();
    return A;
  }

  public Thing fish(){
    this.a1 = "foo";
    this.meth();
    return A;
  }
}
于 2012-12-13T03:59:24.290 回答
0

当你这样做时,this = stuff;你试图用另一件事替换当前的对象实例引用(在这种情况下,是你在构造函数中初始化的那个),并且(在 java 的特定情况下)这是非法的,并且语言禁止你这样做它。

想一想,如果您可以像这样替换对当前实例的引用,那么您可能会遇到一些严重的内存和安全问题(对构造对象的引用将丢失并被某些未知对象覆盖)。

完全有效的是使用运算符引用当前对象的成员.,因为它们属于this,所以不会出现问题(至少不是明显的问题)。

JVM 有一些内部安全措施(例如,方法最大堆栈大小验证、类文件格式验证等),这些措施可以防止简单的二进制操作,并由语言语法强制执行。这可以看作是其中之一。

于 2012-12-13T04:31:44.187 回答