STATIC variable and method causes the MEMORY LEAK
This is true only for static fields of a class, not the methods as well. And this is true because the values of static members will live in memory for as long as the class declaring them will reside in memory - (or, at least, as long as you don't set the static vars value to null
allowing the GC to recycle the memory).
(btw: the correct terminology is "instances stored cause long term memory consumption" It only becomes a leak if those instances are never used, otherwise they become "useful long term memory use").
As for static methods - if they don't store in static variables any instances they are creating, then those instances will either:
if local vars/non-return instances - be CG-ed asap after going out-of-scope (note: "asap" doesn't guarantee "immediately" - this is what "as possible" means after all)
if they are return value - they'll be GC-ed only after the caller release them (i.e. no longer "store" them for future uses). In respect with the returned values, your static method acts like a 'factory': ignoring the specific sequence of configuration (assumed to be more complex than a constructor can provide), they are no different from an instance create with just new ClassOfTheReturnedValue(...)
In regards with public boolean isNetworkConnected()
versus static public boolean isNetworkConnected()
: in your example of use, there's no difference between them in respect with memory-leaking or the ability to create instances that will be GC-ed - because your NetworkCheck check=new NetworkCheck(this);
is just a temporary/local variable which will be collectable once it goes out of scope.
The only difference between the two approaches: the non-static really creates an object (thus more work for CG down the track), while the static form doesn't.
Regarding public static <T> void saveLocalData(Context context, String key, T value)
Well, the way you posted it is grossly suboptiomal.
if calling that method with anything except String
, Boolean
, Integer
, Long
or Float
the compiler will wire the call as requested. At execution time, you'll spend unnecessary type checks (all failing), only to call editor.commit()
with no real change
In regards with type-safety, you deny the compiler any possibility of perform the type checking at compile time to go with an all runtime type-check. Your method is no different to public static void saveLocalData(Context context, String key, Object value)
- all the type checking are deferred to runtime. The only difference between the generic and 'plain-object' forms is: the compiler will work harder to compile the generic method, but will reach the same final result as for the 'Object value' method.
The best way to achieve the same is to drop all the smartness of generics and use the plain-old-method-overload, like this:
protected static SharedPreferences.Editor resolveEditor(
Context context, String prefOwner
) {
SharedPreferences prefs = context.getSharedPreferences(
prefOwner, Context.MODE_PRIVATE
);
return prefs.edit();
}
public static void saveLocalData(Context context, String key, boolean value) {
SharedPreferences.Editor editor = resolveEditor(context, "sushildlh");
editor.putBoolean(key, value);
editor.commit();
}
public static void saveLocalData(Context context, String key, int value) {
SharedPreferences.Editor editor = resolveEditor(context, "sushildlh");
editor.putInt(key, value);
editor.commit();
}
public static void saveLocalData(Context context, String key, String value) {
SharedPreferences.Editor editor = resolveEditor(context, "sushildlh");
editor.putString(key, value);
editor.commit();
}
// etc
With the above:
the compiler can verify that the method is not called with values of types that don't make sense
the code is optimal
After all, the SharedPreferences.Editor
does have a reason for not implementing a generified void putValue<T>(T value)
- what makes you think you can do better from outside of it? If that would be possible, I reckon the authors of SharedPreferences.Editor
would have done it inside their implementation.