【问题标题】:Having a difficult time making a static method which utilizes non-static methods很难制作使用非静态方法的静态方法
【发布时间】:2012-07-04 02:55:18
【问题描述】:

我学习 Java 大约 6 周,但仍在努力实现静态方法(我以为我真的理解它,但这证明我错了!)。

我正在尝试公开本地存储的键值对的值。这是我的初始代码:

public class Settings extends Activity implements OnClickListener {
        public Settings(TextView loginText, TextView passwdText) {
    super();
    this.loginText = loginText;
    this.passwdText = passwdText;
}

public static String getDriverNum() {
    SharedPreferences sp = getSharedPreferences(DELEX_SP, MODE_PRIVATE); <---ERROR
    String Login = sp.getString("KeyLgn", "No Login Found");
    return Login;
}

当然,我得到一个错误“Cannot make a static reference to the non-static method getSharedPreferences(String, int) from type ContextWrapper”,所以我尝试将非静态方法包装在我自己的公共方法中,正如类似的 StackOverflow answer 所示:

public class Settings extends Activity implements OnClickListener {
public Settings(TextView loginText, TextView passwdText) {
    super();
    this.loginText = loginText;
    this.passwdText = passwdText;
}

public static String getDriverNum() {
    String Login = getSharedPref().getString("KeyLgn", "No Login Found"); <-- SAME ERROR
    return Login;
}

public  SharedPreferences getSharedPref() {
    SharedPreferences sp = getSharedPreferences(DELEX_SP, MODE_PRIVATE);
    return sp;
}

但这只是导致了同样的错误,因为我还没有解决对非静态 getSharedPreferences 方法的调用。解决此问题的最佳方法是什么?是不是要创建一个包装 getSharedPreferences 的类?

感谢您在我为静态命名法苦苦挣扎时的耐心等待。

【问题讨论】:

  • 我正在尝试公开本地存储的键值对的值。 - 除了静态方法的问题之外,基本上不要 尝试使用 Android Activity 执行您正在执行的操作。这违背了Android的设计理念。 Android Activity 是一个特例类,您不应公开(静态或其他)任何字段或方法 - 学习/接受这一点或为将来的问题做好准备。要做你想做的事,你可能应该扩展 Application 类 - 永远不要在 Activity 中这样做。
  • 谢谢。我实际上已经创建了一个非 Activity 类来实现我的键值方法,但在那里也遇到了问题(当然)。因此,尝试将其暂时移至 Settings(一个 Activity 类),作为测试平台,看看是否存在 onCreate 固有的东西会有所帮助(是的,我知道,现在回想起来很愚蠢,但我很绝望)。将把它移回非 Activity 类。
  • 还有哪些“类”需要该方法?
  • @Squonk - 几个课程,请看我对 Tom 的回复,如下所示。
  • 对不起,我应该问什么类“类型”。例如,如果有几个扩展 Activity 的类,并且您试图避免代码重复,您可以简单地创建一个“基础”Activity 类并在其上实现该方法,然后为所有其他类扩展它Activities。就个人而言,我可能会在单例模型中扩展 SQLiteOpenHelper 并将 DriverNum 存储在数据库中。这样你就可以在SQLiteOpenHelper 上拥有访问DriverNum 的公共方法。只是另一个需要考虑的角度,因为我倾向于使用 SQLite DB 而不是SharedPreferences。祝你好运。

标签: java android instantiation static


【解决方案1】:

我认为您可能误解了静态的工作原理。

静态方法(或变量)是一个对类的所有实例都有一个副本并且不需要类的实例来调用它的方法。例如,

class MyClass {
      public static void sayHello() {
          System.out.println("hello");
      }
 }

可以这样调用

MyClass.sayHello();

请注意,没有创建 MyClass 的新实例。

实例方法是需要类的特定实例并且通常依赖于类的某些内部状态的方法。

class MyClass {

    // assume this is initialized somewhere in the constructor
    private final String myName;

    public void sayMyName() {
        System.out.println(myName);
    }
}

现在你需要一个特定的类实例

MyClass m = new MyClass("Bill");
m.sayMyName();

静态方法不能引用实例方法(或实例变量),因为静态方法未绑定到类的特定实例。

非静态方法可以访问非静态和静态方法。

一般来说,如果一个方法依赖于实例的状态,它应该是一个非静态方法。如果它不依赖于实例的内部状态,那么它可以是一个静态方法。

在您的情况下,getSharedPref 不会从Settings 的实例中访问任何状态,因此可以将其制成静态方法,然后可以被类中的其他静态方法访问。

【讨论】:

  • 好的,谢谢。我将其实现为一个类(根据下面的 Tom Dignan 代码)。我习惯于过度使用方法(我的程序背景在这里对我没有任何帮助)而不是使用类。从现在开始我会知道的更多。
【解决方案2】:

如果你想编写一个使用非静态方法的静态方法,你只需像这样传递一个实例:

public static void invokeMethod(SomeObject foo) {
    foo.bar();
}

所以你正在做的是一个很棒的模式。我一直将它用于可以在许多类(也称为组合)中重复使用的“助手”,只需将“SomeObject”设置为上下文。

这是我在 Android 中使用的模式,以获得一个很好的中心点来定义默认首选项:

import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;

import java.util.HashMap;
/**
 * Provides support functions for getting preferences as well as a
 * central place for storing default preferences.
 */
public final class PreferencesHelper {
    public static class Preferences {
        public static final String SOME_SETTING = "SOME_SETTING";
    }

   /** This allows us to define our default preferences all in one place */
    private static HashMap<String, Object> sDefaultPreferences =
        new HashMap<String, Object>(){{
        put(Preferences.SOME_SETTING, "value");
    }};

    public static SharedPreferences getDefaultPreferences(Context context) {
        return PreferenceManager.getDefaultSharedPreferences(context);
    }

    public static String getString(SharedPreferences prefs, String key) {
        return prefs.getString(key, (String) sDefaultPreferences.get(key));
    }

    /* Convenience method (use when getting only one preference) */
    public static String getString(Context context, String scanner) {
        SharedPreferences prefs = getDefaultPreferences(context);
        return getString(prefs, scanner);
    }

...

这种模式允许在一个地方定义默认值。

【讨论】:

  • 很遗憾,我无法实例化 SharedPreferences 的对象。所以不能将它的对象作为方法参数传递。 (我一定是误解了答案)。
  • @stuckInOldLodiAgain 传递上下文并调用 context.getSharedPreferences()!
  • 您可以从任何活动或服务中调用它们,例如 Helper.foo(this);
  • @Tom Dignan:当我读到你的 cmets 时,我已经将我的答案更改为评论。同意 POJO 可能比使用Application 更好,但后者肯定是两害相权取其轻(而不是在Activity 中这样做)。问题是 OP 没有解释调用静态方法需要哪些其他“类”,并且请记住,SharedPreferences 可以从任何主要的 Android 组件类型访问,无论如何这通常是不必要的练习。跨度>
  • 不,明白了,额外的卷线 13 正在关闭课程,一旦删除效果很好!感谢您的实现,这是一个非常简洁的编写/访问首选项的类!
【解决方案3】:

您不能从静态方法内部访问static 方法。你在这里做的是同样的事情。您正在访问非static 方法,即从静态方法getDriverNum 内部的getSharedPref()

【讨论】:

  • 您可以从非静态方法调用静态方法。你的回答有误吗?
  • 哈!换了词。我的错。
  • 是的,完全正确(换了单词)。这就是为什么我要求正确的方法来做到这一点。我觉得有点受限,因为我无法实例化 SharedPreferences 的对象以访问 getSharedPreferences
  • @stuckInOldLodiAgain 记住在 Java 中 main() 是一个静态方法,它当然能够调用各种对象的实例方法。问题是它必须通过对象调用它们。
【解决方案4】:

简单来说,你需要知道两件事:

  1. 可以在非静态方法中调用静态方法

  2. 您不能在同一类的静态方法中调用非静态方法(除非您新建另一个类的实例,并通过该对象调用非静态方法)

这就是你得到错误的原因,当你在getDriverNum() 中调用getSharedPref() 时,你违反了第二条规则。

要解决此问题,请尝试将getSharedPref() 设为静态,然后将getSharedPreferences() 设为静态。

【讨论】:

  • 是的,除了 getSharedPreferences() 是接口 SharedPreferences 的非静态抽象方法之外,一切正常。我没有定义它们,它们是 Android 库的一部分。而且我宁愿避免尝试用我有限的Java知识重写那些! :)
  • 好吧,你最终会摇滚的:)
【解决方案5】:

在您的 Helper 类中,只需将 Activity 类的静态变量传递给它。例如

HelperClass:

public static int getDefaultYear()
{
    return HomeActivity.prefs.getInt("myYear", 10);
}

家庭活动:

public class HomeActivity extends AppCompatActivity {

public static SharedPreferences prefs;

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   prefs = this.getSharedPreferences(getString(R.string.applicationIdString), Context.MODE_PRIVATE);
   ...
   }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-07
    • 1970-01-01
    • 1970-01-01
    • 2011-01-17
    • 2013-03-20
    • 1970-01-01
    相关资源
    最近更新 更多