2
public class Date
{

static int month; 

public static void setMonth(int x)
{ 
 this.month = x;  //compiler error
}

public static int getMonth()
{
 return month;  //compiles just fine, no error
}

}

编译时,我收到错误:非静态变量 this 不能从静态上下文中引用。但是,如果我删除“this”。没有错误。当我使用关键字 static 明确声明月份时,我不明白为什么它说月份是一个非静态变量。

4

4 回答 4

6

您根本无法this在静态上下文中使用。那是设计使然-this指的是对象而不是类。如果您遇到方法参数和字段之间可能的名称冲突的问题,您可以改用类名:

public static void setMonth(int month)
{ 
 Date.month = month; 
}

另一方面,您可以考虑您的设计并重新考虑将整个类用作一个单例对象的决定。

于 2013-03-23T23:55:22.583 回答
4

this 指的是当前实例。静态方法与实例无关;它们与类相关联。

这个例子是个坏主意。任何了解java.util.Date和的人都会感到困惑java.sql.Date

于 2013-03-23T23:50:16.440 回答
2

考虑这种情况:

class ParaentClass {

  public static final int SOME_VALUE = 7;

  public modValue(int m) {
    // WRONG
    return this.SOME_VALUE % m;
  }

}

class ChildClass extends ParentClass { }

// . . .

(new ChildClass()).modValue(4);

在上面的代码中,当我们调用 时modValuethis实际上是 的实例ChildClass,而不是的实例ParentClass,因此当 JVM 执行该方法时,它甚至不知道在哪个类上查找静态字段。我想 JVM 可以做一些事情,比如爬过继承层次结构来寻找最接近的匹配静态字段——但这会产生糟糕的性能。

无论如何,他们决定定义语义的方式static是它们与一个类相关联,并且它们不能被覆盖。因此,仅通过类名(例如 )来引用它们才有意义ParentClass.SOME_VALUE,而不是通过对像this.

如果静态变量当前在范围内,您可以省略类名:

  public modValue(int m) {
    // CORRECT
    return ParentClass.SOME_VALUE % m;
  }

或者

  public modValue(int m) {
    // ALSO CORRECT
    return SOME_VALUE % m;
  }
于 2013-03-24T00:00:05.753 回答
2

在 Java 中,您可以选择在类中将字段设为静态或非静态。

当字段是静态的时,您不需要“实例化”该类的“实例”来引用它。

在您的示例中,我可以从另一个类的同一包中访问“月”变量(因为您没有“访问修饰符”,Java 使该变量为“包私有” - 隐藏到每个类中,除了相同的目录(Java 术语中的包))通过执行以下操作:

public class Example {
    void outputMonth() {
         System.out.println("This is the month: " + Date.month);
    }
}

但是,如果删除了 static 修饰符,那么“月”就不会简单地附加到类上。它属于类的每个“实例”。使用您当前版本的程序,我可以将“月”移动到示例类,并让 Date 使用 Example.month 而不是月来引用它,它的工作方式完全相同。

要“实例化”一个类的“实例”,请使用“new”关键字:

public class Example {
    void instantiateAndDisplay() {
         Date newInstance = new Date();
         System.out.println("This won't be pretty, but it's a new Date: " + newInstance);
    }
 }

现在,如果从“月”中删除静态关键字,则每个日期“实例”都有自己的月变量副本,可以独立更改。对 new 的两次调用产生两个实例,三个调用,三个实例,等等。

如果这更清楚一点,那么编译器警告您有关“this”的原因是“this”是当前实例的抓取包术语。由于您将该方法设为静态,因此没有实例 - 该代码附加到该类,但它可以移动到 Example 类,并且 Date 可以通过调用 Example.setMonth(month); 来使用它;

定义“this”的原因是范围有时不明确。在您的 setMonth 示例中,如果您从所有方法中删除了 static 修饰符,则可以将局部变量从“x”重命名为“month”,但如果没有这个,您所做的就是将从自身传入的局部变量月分配给本身,它什么都不做。“this”将“month”的范围定义为“Date 类的当前实例”,然后允许您对其进行分配,如下例所示:

public class Date {
    private int month;
    public void setMonth(int month) {
        this.month = month;
    }
    public void getMonth() {
        return month; // Note - no competing scope, so month comes from the current instance.
    }
 }

然后,您可以创建两个新的 Date 实例,将它们的月份分配给不同的值,并独立使用它们。但是,如果修饰符是静态的,则该类的所有实例以及“访问修饰符”允许的任何类都可以访问该值,其范围超出了本讨论的范围。

于 2013-03-24T00:26:40.050 回答