【问题标题】:Cannot make a static reference to the non-static method无法对非静态方法进行静态引用
【发布时间】:2011-06-25 13:06:20
【问题描述】:

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

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

这是错误信息:

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

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

【问题讨论】:

  • 为什么对于“多语言应用程序”需要它是静态的?不太明白。
  • 永远不要在静态数据成员中存储字符串资源。当您需要它们时,请始终通过getString() 请求它们。这样,您的应用程序就会正确地适应用户更改他们选择的语言。

标签: java compiler-errors static-methods


【解决方案1】:

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

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

实例(非静态)方法适用于特定类型(类)的对象。这些是用新的这样创建的:

SomeClass myObject = new SomeClass();

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

myObject.getText(...)

但是,静态方法/字段可以直接在类型上调用,如下所示: 前面的说法不正确。 One can also refer to static fields with an object reference like 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() 的非静态要求是什么?

【讨论】:

  • 它是静态的,因为我从项目中的多个文件中调用它。当我删除“静态”时,错误代码消失了,但现在我在使用此变量的其他文件中有很多错误。
  • 但这就是我的观点。您需要了解何时可以使用这两者。
  • 当我将“Constants notifications_values = new Constants(); 添加到我的主要活动类中时,它编译正常,但在模拟器中它在此活动运行时崩溃
【解决方案2】:

已经有一些很好的答案解释了为什么非静态 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 字段。

【讨论】:

  • 非常感谢,我根据您的建议更改了所有文件。
  • 我试图这样做,但是对于一个字符串数组,并且使用 String a[] = context.getTextArray(R.array.myStringArray); ;但是,它给了我一个错误The method getTextArray(int) is undefined for the type Context - 为什么它会在与 getText 一起使用时未定义?
  • @auspicious99 仅仅是因为Context 没有名为getTextArray 的方法,但有getText。也许您正在考虑Resources,其中确实有getTextArray
【解决方案3】:

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

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

即:

MyClass myclass = new MyClass();

// then later

MyClass.someFunction();

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

myclass.someFunction();

这是一个愚蠢的错误,但每隔几个月,我就会浪费大约 30 分钟来处理“MyClass”定义中的 vars 来找出我做错了什么,而实际上,这只是一个错字。

有趣的提示:堆栈溢出突出显示了使错误在这里非常明显的语法。

【讨论】:

  • 您的 IDE 是否也突出显示了这一点?我想你可以配置它这样做:)
  • 这为我节省了几个小时的时间,谢谢!!
【解决方案4】:

你可以让你的变量非静态

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

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

【讨论】:

    【解决方案5】:

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

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

    【讨论】:

      【解决方案6】:

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

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

      现在来回答您的问题,当您使用 new() 运算符时,我们将为每个对象创建每个非静态字段的副本,但静态字段并非如此。这就是为什么如果您从非静态方法中引用静态变量,它会给出编译时错误。

      【讨论】:

        【解决方案7】:

        这个问题并不新鲜,现有的答案提供了一些很好的理论背景。我只是想补充一个更务实的答案。

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

        有几种方法可以解决这个问题:

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

        【讨论】:

          猜你喜欢
          • 2023-04-02
          • 2013-06-30
          • 2014-06-08
          • 2013-03-31
          相关资源
          最近更新 更多