无法将静态引用方法应用于非静态方法。

114

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

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

这是错误信息:

错误:无法对类型Context中的非静态方法getText(int)进行静态引用

这是什么原因造成的,我该怎样解决它?


1
为什么对于“多语言应用程序”需要它是静态的?我不太理解。 - xil3
3
使用静态数据成员存储字符串资源是不可取的,应该在需要时通过getString()方法请求它们。这样,您的应用程序就可以适应用户更改所选择的语言。 - CommonsWare
Java基础 :: 学习路径 - Edward J Beckett
8个回答

155

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()非静态吗?


它是静态的,因为我在项目中从多个文件中调用它。 当我删除了“static”后,错误代码消失了,但现在在使用此变量的其他文件中出现了许多错误。 - Chen M
但这正是我的观点。你需要理解什么时候可以使用这两个。 - Preet Sangha
当我在我的主活动类中添加行“Constants notifications_values = new Constants();”时,它可以编译通过,但在模拟器上运行此活动时会崩溃。 - Chen M

12

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

一个好问题是:你为什么想这样做?你试图从你的strings 资源中加载一个 String ,并将其值填充到一个public static字段中。我假设这样做是为了让其他类可以访问它?如果是这样,那么没有必要这样做。相反,将一个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
非常感谢,我已经根据你的建议修改了所有文件。 - Chen M
我尝试着用String a[] = context.getTextArray(R.array.myStringArray);来操作字符串数组,但是出现了错误The method getTextArray(int) is undefined for the type Context。为什么它对getText有效而对getTextArray无效呢? - auspicious99
1
@auspicious99,这是因为Context没有名为getTextArray的方法,但确实有getText方法。也许你想到的是Resources,它确实有getTextArray方法。 - dave.c

10

对于那些通过搜索找到这篇文章的人:

当我意外使用了类名而不是对象名调用函数时,我经常遇到这个问题。这通常发生在我给它们起的名字太相似时:P

例如:

MyClass myclass = new MyClass();

// then later

MyClass.someFunction();

显然这是一个静态方法(适用于某些情况)。 但我真正想做的事情(在大多数情况下)是:

myclass.someFunction();

这是一个非常愚蠢的错误,但每隔几个月,我都会浪费大约30分钟在"MyClass"定义中搞清楚我做错了什么,而实际上只是一个打字错误。

有趣的是:stackoverflow会突出显示语法,使这个错误非常明显。


你的IDE没有突出显示这个吗?我猜你可以配置它来这样做 :) - Matthias Meid
这节省了我几个小时的时间,谢谢!! - Daria M

2
你不能从非静态方法中引用静态变量。 要理解这一点,你需要了解静态和非静态之间的区别。 静态变量是类变量,它们属于类,只有一个实例,在第一次创建时创建。 非静态变量在每次创建类的对象时都会初始化。 现在回答你的问题,当你使用new()运算符时,我们将为每个对象创建每个非静态字段的副本,但对于静态字段却不是这样。这就是为什么如果你从非静态方法中引用静态变量会导致编译时错误的原因。

2
你可以把变量变成非静态的。
public final String TTT =  (String) getText(R.string.TTT);

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

2

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

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


0

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

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

有几种解决方法:

  1. 通过删除static修饰符并将变量放置在类体内部,将变量作为Activity或其他Context子类的成员变量(字段);
  2. 保持它的静态性,并将初始化延迟到稍后的时间点(例如,在onCreate方法中);
  3. 将其作为实际使用的地方的局部变量。

0

是的,您可以在静态方法中调用非静态方法,因为我们需要记住首先'我们可以创建一个对象,该对象的类可以轻松地调用非静态方法进入静态方法


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接