Static Variables : Good or Bad? [duplicate]

2019-01-19 11:06发布

问题:

Possible Duplicate:
Why are static variables considered evil?

I have the habit of using static variables extensively in all my programs, especially when I am working with Android. I tend to use them because sometimes it feels so cumbersome to send 10 or more values via Intents. So, I just declare them as static variables and access them in the other classes easily by using the "dot" operator. Another reason for using static variables is when I am making a Utility class to be used throughout my application. Like the code I have given below helps me to use the variables in different activities.

Utility.java

public class Utility {
public static Facebook fb;
public static AsyncFacebookRunner fbAsyncRunner;
public static String[] fbPermissions = {"email", "read_stream", "user_birthday"};
public static final String PREF_UTILITY_FILE_NAME = "PrefUtilityFile";
public static SharedPreferences prefs;
public static Editor editor;
public static String access_token;
public static long expires;
}

I searched online for similar questions and came across this and this, but they do not seem to give a final answer to the issue. And in most of the places, I see conflicting opinions and hence am totally confused.

Is it a good programming practice or bad ? Should I be using it or not ?

回答1:

You can replace all you static fields with a "Context" object which you can pass around or make a Singleton. It is possible to remove almost all your static fields away. Whether this is a good idea or not is up to you, but I wouldn't assume that it has to be much harder to use instance fields.

BTW: I would suggest

  • placing static fields/constant with the class or package which uses them
  • treat static arrays as immutable if possible making them final as well.

You can use a non-static Context with

public class Context {
    public static final String PREF_UTILITY_FILE_NAME = "PrefUtilityFile";

    public Facebook fb;
    public AsyncFacebookRunner fbAsyncRunner;
    public String[] fbPermissions = {"email", "read_stream", "user_birthday"};
    public SharedPreferences prefs;
    public Editor editor;
    public String access_token;
    public long expires;
}

// pass to constructor as required
class UsesContext {
    final Context context;
    public UsesContext(Context context) {
        this.context = context;
    }

    public void method() {
        // can use context
    }
}

This allows you to create unit tests with multiple Contexts.

The only thing I would leave static are constants.



回答2:

This programming practice is bad in purely object oriented languages (like Java) because it undermines the object oriented programming paradigm. They work, but once you realize you DO need more than one version of them, you will need a lot of refactoring to achieve that.

If you think that handing too many parameters via method calls is cumbersome. Simply create an object that holds all of them (see Peter Lawrey's answer, "Context" object) and pass only this object. Then you can again use your "simple dot notation" on that object.

Next point: Testing. If you need to replace some static fields with proxy or other testing stuff for unit tests, you are basically screwed. With a context object, you can simply hand a different context object into the unit tests.

The Utility class you mentioned is basically a good candidate for such context object. Simply make all its fields non-static and hand in an object of that class to code that needs it.

I can tell you about one example where I got screwed by using statics: I once wrote a compiler. And since I thought that during a compilation run, there are many context things that are only necessary once (the symbol table, for example), I added them all as static variables. Later I decided to allow multi-threaded compilation and a "server" mode where the compiler runs all the time in idle mode until a client sends a compile request (this saves Java's long startup time). Now I was screwed. Now there was more than one concurrent context (concurrent compiler threads), but all context was shared via static variables. I needed around one week to replace all statics by context objects and introduced numerous bugs.



回答3:

I am all for static variables if you keep using them regularly and the values never change if you make them final.

Why do things the difficult way?

That is what static variables are all for.

Basically what they do is provide a generic access point you can access from any context(static, program flow, external).

You are basically stating the front door is here and it's yellow. Someone peeking from the outside will see the door which is yellow. Someone on the inside walking will see the door and that it's yellow. Someone in a room can look into the hallway and see that it's yellow.

And if you paint it red, it will be clearly visible to everyone.

Also, there will always be 1 instance throughout the ENTIRE program with the same value. which saves memory.

take for example

class test {
public int ten = 10;
   public test() {
   }
}

Every time you make a new test() an integer memory space will be assigned for the ten variable. So if you have 10 test instances you will have 10 seperate integers all holding the same value.

if you have this

class test {
public static int ten = 10;
   public test() {
   }
}

and you have ten test instances, you will only have one integer instance ten. This saves memory assignment, garbage collection. Although I only advice this for persistent lists/variables that do not change and you can afford to keep in memory indefenately. Don't do this with every variable. Do this for large things like an image that you re-use over and over. No use to keep the same image in memory multiple times.

When I originally wrote my answer I didn't know how static variables really worked. I got static final and static mixed up. On static variables you can assign new values. static final are immutable. those can't be changed.



回答4:

Bad. See Cutting out Static.

In my opinion, static variables comprise one or more objects, but that objects are ill-formed: not organized in classes (no type hierarchy), bad encapsulation, limited to single instance (this may cause trouble when in future, multiple instances required).



回答5:

Variables that are declared static stays in the memory till the program executes thus taking extra space.

The use of static may be beneficial if you want to use/retain a value for a long period of time, however declaring all variables as static is not recommended and is not a good practice . If you make a habit of declaring all value as static your program will eat unnecessary memory.

Other than that static variable doesn't comply with OOPS concept where scopes, abstraction and encapsulation are defined along with the effervescence object. Through which you can call and delete variables at will.

The biggest disadvantage of using static variables will appear if you are working in limited memory space (such as mobile applications) in that case you application will crash if it is overhogged by variables and less memory space.

If you want to store a value permanently there are other ways around like database, files etc makes the job easier and cleaner. Just my 2 cents.



标签: java static