问题
I'm about 6 weeks into learning Java and still struggling with implementing static methods (thought I really understood it, but this proved me wrong!).
I'm trying to make the value of a locally stored key-value pair available publicly. Here's my initial code:
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;
}
Of course, I get an error "Cannot make a static reference to the non-static method getSharedPreferences(String, int) from the type ContextWrapper", so I try to wrap the non-static method in my own public method, as a similar StackOverflow answer indicated:
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;
}
But this just caused the same error as I haven't resolved the call to the non-static getSharedPreferences method. What's the best way to resolve this? Is it to create a class that wraps getSharedPreferences instead?
Thanks for your patience while I struggle with static nomenclature.
回答1:
If you want to write a static method that utilizes non-static methods, you just pass an instance to it like this:
public static void invokeMethod(SomeObject foo) {
foo.bar();
}
So what you're doing is a great pattern. I use it all the time for "helpers" that can be reused across many classes (aka composition) Just make your "SomeObject" the Context.
Here's the pattern I use in Android to get a nice central point to define default preferences:
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);
}
...
This pattern allows the definition of default values to be in one place.
回答2:
I think you might be misunderstanding how static works.
A static method (or variable) is one that has a single copy for all instances of the class and does not require and instance of the class to invoke it. For example,
class MyClass {
public static void sayHello() {
System.out.println("hello");
}
}
That can be invoked as
MyClass.sayHello();
Notice there is no new instance of MyClass created.
An instance method is one that requires a particular instance of a class and usually relies on some internal state of the class.
class MyClass {
// assume this is initialized somewhere in the constructor
private final String myName;
public void sayMyName() {
System.out.println(myName);
}
}
Now you would need a specific instance of the class
MyClass m = new MyClass("Bill");
m.sayMyName();
A static method cannot reference an instance method (or instance variable) because a static method is not tied to a particular instance of a class.
Non-static methods can access both non-static and static methods.
In general, if a method relies on state of the instance, it should be a non-static method. If it does not rely on internal state of the instance, then it can be a static method.
In your case, getSharedPref
does not access any state from the instance of Settings
, so it can be made into a static method and can then be accessed by other static methods in the class.
回答3:
You can't access a non-static
method from inside of a static method. what you are doing here is the same thing. You are accessing a non-static
method, namely, getSharedPref()
from inside of a static method getDriverNum
回答4:
Simply, you need to know two things:
you can call static methods in non-static methods
you cannot call non-static methods in static methods in the same class (except you new a instance of another class, and call non-static methods by that objects)
that's why you get error, you break the second rule when you callgetSharedPref()
in getDriverNum()
.
To solve this, try to make getSharedPref()
static, and in return make getSharedPreferences()
static.
回答5:
In your Helper class, just pass it the static variable of the Activity class. e.g.
HelperClass:
public static int getDefaultYear()
{
return HomeActivity.prefs.getInt("myYear", 10);
}
HomeActivity:
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);
...
}
来源:https://stackoverflow.com/questions/11321853/having-a-difficult-time-making-a-static-method-which-utilizes-non-static-methods