无法静态引用非静态方法


102

用Java构建多语言应用程序。从R.string资源XML文件插入String值时出现错误:

public static final String TTT =  (String) getText(R.string.TTT);

这是错误消息:

错误:无法从上下文类型静态引用非静态方法getText(int)

这是怎么引起的,我该如何解决?


1
对于“多语言应用程序”,为什么需要它是静态的?不太懂
xil3 2011年

3
切勿将字符串资源存储在静态数据成员中。始终getString()在需要时通过他们提出要求。这样,您的应用程序就可以适应用户更改他们选择的语言的情况。
CommonsWare,

Answers:


143

由于getText()它是非静态的,因此无法从静态方法中调用它。

要了解原因,您必须了解两者之间的区别。

实例(非静态)方法适用于特定类型(类)的对象。这些是使用新的创建的,如下所示:

SomeClass myObject = new SomeClass();

要调用实例方法,请在实例(myObject)上调用它:

myObject.getText(...)

但是,只能直接在类型上调用静态方法/字段,如下所示: 一条语句不正确。也可以使用诸如此类的对象引用来引用静态字段, myObject.staticMethod()但是不建议这样做,因为它并不清楚它们是类变量。

... = SomeClass.final

两者不能一起工作,因为它们在不同的数据空间(实例数据和类数据)上运行

让我尝试解释一下。考虑此类(伪代码):

class Test {
     string somedata = "99";
     string getText() { return somedata; } 
     static string TTT = "0";
}

现在,我有以下用例:

Test item1 = new Test();
 item1.somedata = "200";

 Test item2 = new Test();

 Test.TTT = "1";

有什么价值?

in item1 TTT = 1 and somedata = 200
in item2 TTT = 1 and somedata = 99

换句话说,TTT是该类型的所有实例共享的数据。所以说没有道理

class Test {
         string somedata = "99";
         string getText() { return somedata; } 
  static string TTT = getText(); // error there is is no somedata at this point 
}

所以问题是为什么TTT是静态的,或者为什么getText()不是静态的?

删除static,它应该会越过此错误-但在不了解您的类型的情况下,直到下一个错误为止,它只能是膏药。有什么要求getText(),要求它成为非静态?


它是静态的,因为我从项目中的几个文件中调用它。当我删除“静态”错误代码不见了,但是现在我在使用此变量的其他文件中有很多错误。
陈M

但这是我的意思。您需要了解何时可以使用两者。
Preet Sangha

当我在主活动类中添加“ Constants notifications_values = new Constants();”行时,它可以编译,但在模拟器中运行此活动时它会崩溃
Chen M

11

已经有一些很好的答案,并解释了为什么不能与您的一起使用非静态Context方法的混合。getText()static final String

要问的一个好问题是:为什么要这样做?您正在尝试Stringstrings资源中加载a ,并将其值填充到public static字段中。我认为这样做是为了让您的其他一些班级可以访问它?如果是这样,则不需要这样做。而是将a传递Context到您的其他班级中,然后context.getText(R.string.TTT)从其中进行调用。

public class NonActivity {

    public static void doStuff(Context context) {
        String TTT = context.getText(R.string.TTT);
        ...
    }
}

并通过您的电话进行调用Activity

NonActivity.doStuff(this);

这将使您String无需使用public static字段即可访问资源。


1
非常感谢您,我根据您的建议更改了所有文件。
陈M

我正在尝试这样做,但是要使用字符串数组,并使用String a[] = context.getTextArray(R.array.myStringArray); ;。但是,它给了我一个错误The method getTextArray(int) is undefined for the type Context-为什么在与getText一起使用时为什么仍未定义?
auspicious99

1
@ auspicious99仅仅因为a Context没有调用方法getTextArray,但是确实有getText。也许您在想Resources哪一个有getTextArray
dave.c 2014年

啊,谢谢!传入资源而不是上下文(从活动到非活动),我的getStringArray工作了。
auspicious99

9

对于在搜索中找到此内容的其他用户:

当我不小心使用类名而不是对象名调用函数时,经常会得到这个。这通常是因为我给他们起的名字太相似了:P

即:

MyClass myclass = new MyClass();

// then later

MyClass.someFunction();

这显然是静态方法。(对某些事情很有用)但是我真正想做的(在大多数情况下是)

myclass.someFunction();

这是一个愚蠢的错误,但是每隔几个月,我就浪费了大约30分钟来弄乱“ MyClass”定义中的var,以弄清楚我在做什么的确是错字。

有趣的是:堆栈溢出突出显示了使错误在这里真正明显的语法。


您的IDE也不突出显示吗?我想您可以对其进行配置:)
Matthias Meid 2011年

2

您可以将变量设为非静态

public final String TTT =  (String) getText(R.string.TTT);

或将“ getText”方法设为静态(如果可能的话)


2

getText是您的Activity的成员,因此必须在“ this”存在时调用它。在创建Activity之前加载类时,将初始化静态变量。

由于要从资源字符串初始化变量,因此它不能是静态的。如果希望它是静态的,则可以使用String值对其进行初始化。


2

您不能通过非静态方法引用静态变量。要了解这一点,您需要了解静态和非静态之间的区别。

静态变量是类变量,它们属于类,只有一个实例,仅在第一个实例中创建。每次您创建类的对象时,都会初始化非静态变量。

现在来问您的问题,当您使用new()运算符时,我们将为每个对象创建每个非静态文件的副本,但对于静态字段则不是这样。这就是为什么如果您从非静态方法引用静态变量,则会产生编译时错误。


0

这个问题不是新问题,现有的答案提供了良好的理论背景。我只想添加一个更实用的答案。

getText是Context抽象类的一种方法,为了调用它,需要一个其子类实例(Activity,Service,Application或其他)的实例。问题在于,在创建Context的任何实例之前都要初始化公共静态最终变量。

有几种解决方法:

  1. 通过删除静态修饰符并将其放在类主体中,使变量成为Activity或Context的其他子类的成员变量(字段);
  2. 保持它为静态并将初始化延迟到以后(例如在onCreate方法中);
  3. 使其成为实际使用位置的局部变量。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.