Lazy initialization of static variables in Java - execute around? - java

That's how I do it (android code)
private volatile static WifiManager wm;
private static WifiManager wm(Context ctx) {
WifiManager result = wm;
if (result == null) {
synchronized (WifiMonitor.class) { // the enclosing class
result = wm;
if (result == null) {
result = wm = (WifiManager) ctx
.getSystemService(Context.WIFI_SERVICE);
if (result == null) throw new WmNotAvailableException();
}
}
}
return result;
}
Bloch in Effective Java recommends :
// Lazy initialization holder class idiom for static fields
private static class FieldHolder {
static final FieldType field = computeFieldValue();
}
static FieldType getField() {
return FieldHolder.field;
}
This has the advantages of dispensing with the synchronization and that the JVM optimizes out the field access. The problem is that I need a Context object in my case. So :
Is there a way to adapt Bloch's pattern to my case (computeFieldValue() needs a param) ?
If not, is there a way to execute around ? The code is subtle and I'd rather have it in one place and pass only required behavior in
Last but not least - is there a way to enforce access to the cache field (wm) only via the wm() method ? So I can avoid NPEs and such. Other languages use properties for this

You can do the following
static int param1;
static String param2;
public static void params(int param1, String param2) {
this.param1 = param1;
this.param2 = param2;
}
private static class FieldHolder {
static final FieldType field = new FieldType(param1, param2);
}
static FieldType getField() {
return FieldHolder.field;
}
Note: even simpler than this is to use an enum,
enum Singleton {
INSTANCE;
}
or
class SingletonParams {
static X param1;
}
enum Singleton implements MyInterface {
INSTANCE(SingletonParams.param1, ...);
}

Related

How does initialization on demand holder idiom work with parameters?

Here is the link to initialization on demand holder idiom
I've created a class with Singleton design pattern and double locking strategy. I want to change this class to use initialization on demand holder, but I couldn't accross examples where this is parameterized.
How should I pass the parameters basePath1, basePath2 while using initialization on demand holder pattern ?
Would the present code and code with initialization on demand holder pattern cause any concurrency issues ?
public class Api {
private String basePath1;
private String basePath2;
private StringBuilder temporalEndpoint;
private StringBuilder spatialEndpoint;
private StringBuilder fileUploadEndpoint;
private StringBuilder fileDownloadEndpoint;
private StringBuilder fileDeleteEndpoint;
private StringBuilder listMetaDataEndpoint;
private static final Logger LOG = LogManager.getLogger(Api.class);
private static volatile Api apiInstance;
private Api(String basePath1, String basePath2) {
this.basePath1 = basePath1;
this.basePath2 = basePath2;
buildEndpoints();
}
public static Api getInstance(String basePath1, String basePath2)
{
if(apiInstance == null)
{
synchronized(Api.class)
{
if(apiInstance == null)
{
apiInstance = new Api(basePath1, basePath2);
}
}
}
return apiInstance;
}
public void buildEndpoints() {
temporalEndpoint = new StringBuilder(basePath1).append(API_TEMPORAL);
spatialEndpoint = new StringBuilder(basePath1).append(API_SPATIAL);
fileUploadEndpoint = new StringBuilder(basePath1).append(API_FILE_UPLOAD);
fileDownloadEndpoint = new StringBuilder(basePath1).append(API_FILE_DOWNLOAD);
fileDeleteEndpoint = new StringBuilder(basePath2).append(API_FILE_DELETE);
listMetaDataEndpoint = new StringBuilder(basePath2).append(API_LIST_METADATA);
}

return a long list of constant in Java

I have a class in which 100+ consts are defined
public class Codes {
static final public ErrorCode ISSUE_1 = new ErrorCode(XXX);
static final public ErrorCode ISSUE_2 = new ErrorCode(XXX);
// 100+ error codes
}
Now I need to define a Codes.getAll() to return all the ErrorCode defined in the class.
Is there any elegant way to implement it?
using reflection could be a solution;
List<ErrorCode> list = new ArrayList<>();
for (Field field : Codes.class.getFields()) {
if (field.getType() == ErrorCode.class) {
list.add((ErrorCode) field.get(null));
}
}

Singleton returning two instances

I'm trying to use a singleton (PhotoStorage) to provide an arrayList of Photo objects, but it seems that the PhotoStorage instance is not behaving as a singleton (two instances).
I am using dagger to inject this singleton into a class named PhotoInteractor. The objectGraph seems A-OK up to this point.
The same PhotoInteractor instance is used in three fragments in a viewpager. These fragments are all instantiated at runtime:
RecentFragment:
HistoryFragment:
Notice how the instance #4067 of the PhotoInteractor is the same for both fragments.
Also:
mAppContext#4093: same
photoStorage#4094: same
When I click a photo object (grid image) from RecentFragment, the PhotoStorage.addPhoto(url) method is called. This correctly adds the photo object to the photoStorage instance array (4094). That much is OK.
Problem:
When I close the applicaton, it is intended that the PhotoStorage.savePhotosToFile method serialzes this arrayList object into JSON on the filesystem.
The following method is called from the same PhotoInteractor instance:
#Override
public void savePhotos(){
photoStorage.get(mAppContext).savePhotosToFile();
}
When I debug the application, the PhotoStorage.get method already has a singleton instance, but what appears to be a 2nd instance!
//Singleton enforcement
public static PhotoStorage get(Context c){
if(sPhotoStorage == null){
sPhotoStorage = new PhotoStorage(c.getApplicationContext());
}
return sPhotoStorage;
}
This means that the ArrayList of photos will always be empty since it is a new instance of PhotoStorage. Iā€™m not sure where it is instantiating itself from.
Edit - Added PhotoStorage.class:
public class PhotoStorage{
private ArrayList<Photo> mPhotos;
private PhotoJSONer mSerializer;
private static PhotoStorage sPhotoStorage;
private static Context mAppContext;
private static final String PHOTOS_DATABASE = "photos.json";
public static final String TAG = PhotoStorage.class.getSimpleName();
public PhotoStorage(Context appContext){
mSerializer = new PhotoJSONer(appContext, PHOTOS_DATABASE);
try{
mPhotos = mSerializer.loadPhotos();
}catch(Exception e){
mPhotos = new ArrayList<Photo>();
}
}
//Singleton enforcement
public static PhotoStorage get(Context c){
if(sPhotoStorage == null){
sPhotoStorage = new PhotoStorage(c.getApplicationContext());
}
return sPhotoStorage;
}
public ArrayList<Photo> getPhotos(){
return mPhotos;
}
public Photo getPhoto(String url){
for(Photo p: mPhotos){
if(p.getUrl() == url)
return p;
}
return null;
}
public void deletePhoto(String url){
Log.i(TAG, "deleted photo");
mPhotos.remove(url);
}
public void addPhoto(Photo photo){
Log.i(TAG, "added photo");
mPhotos.add(photo);
}
public boolean savePhotosToFile(){
try{
mSerializer.savePhotos(mPhotos);
return true;
}catch (Exception e){
return false;
}
}
}
You are not executing Singletton pattern in the correct way,
The Singleton design pattern addresses all of these concerns. With the Singleton design pattern you can:
Ensure that only one instance of a class is created
Provide a global point of access to the object
In your case, we don't see PhotoStorage class but this call comes from an instance, what is not allowed by Singletton pattern:
photoStorage.get(mAppContext).savePhotosToFile();
//ā†‘ instance call WRONG!!
This line works, but as your get method is static is not a good practice as Karakuri pointed and also breaks the Singletton pattern definition.
public static PhotoStorage get(Context c){
SOLUTION
To make photoStorage.get() invalid and create a correct Singletton pattern you must:
declare the getInstance() method static in the class (here PhotoStorage)
hide default constructor to avoid instances of the class
create private constructors if necessary
call getInstance() it in a static way:
class PhotoStorage {
// hidding default constructor
private PhotoStorage () {};
// creating your own constructor but private!!!
private PhotoStorage(Context appContext){
mSerializer = new PhotoJSONer(appContext, PHOTOS_DATABASE);
try{
mPhotos = mSerializer.loadPhotos();
}catch(Exception e){
mPhotos = new ArrayList<Photo>();
}
}
//Singleton enforcement
public synchronized static PhotoStorage get(Context c){
if(sPhotoStorage == null){
sPhotoStorage = new PhotoStorage(c.getApplicationContext());
}
return sPhotoStorage;
}
}
Then you can make static call from everywhere the class scope allows:
#Override
public void savePhotos(){
PhotoStorage.get(mAppContext).savePhotosToFile();
//ā†‘ static call CORRECT!!
}
UPDATE: if your app have several threads and singleton getInstance requests may overlapp, there is a double check syncronized singletton pattern you can apply:
//Singleton enforcement
public synchronized static PhotoStorage get(Context c){
if(sPhotoStorage == null){
synchronized(PhotoStorage.class) {
if(sPhotoStorage == null) {
sPhotoStorage = new PhotoStorage(c.getApplicationContext());
}
}
}
}

Lazy initialization using single check idiom

In Item 71 in 'Effective Java, Second Edition' the Double-check idiom and the single-check idiom are introduced for lazily instantiating instance fields.
Double-check idiom
private volatile FieldType field;
FieldType getField() {
FieldType result = field;
if (result == null) {
synchronized(this) {
result == field;
if (result == null)
field = result = computeFieldValue();
}
}
return result;
}
Single-check idiom
private volatile FieldType field;
FieldType getField() {
FieldType result = field;
if (result == null) {
field = result = computeFieldValue();
}
return result;
}
In the double-check idiom Joshua states, that the result variable is used to make sure that the volatile field is only read once, which improves performance. This I understand, however I don't see why we need it in the single-check idiom, since we only read field once anyway.
In the single-check idiom, without the result variable you'd still be reading it twice; once for the null check and once for the return value.
I prefer the following implementation of lazy evaluation:
#ThreadSafe
class MyClass {
private static class MyClassHelper {
public static final MyClass helper = new MyClass();
}
public static MyClass getInstance() {
return MyClassHelper.helper;
}
}

Enum-like structure with instances?

I use the following enum type:
enum Status {OK,TIMEOUT,EXCEPTION}
But now I want to store what exactly the Exception is. Unfortunately you cannot instantiate an enum type. What is the best way to make something like the following possible?
switch(status)
{
case(OK) {System.out.println("Everything OK!");break;}
case(TIMEOUT) {System.out.println("Timeout :-(");break;}
case(EXCEPTION) {System.out.println("We have an exception: "+status.exception);break;}
}
My ideas
Class with singletons
class Status
{
final Exception e;
public final Status OK = new Status(null);
public final Status TIMEOUT = new Status(null);
public Status(Exception e) {this.e=e;}
}
Then I could do:
if(status==Status.OK) {System.out.println("Everything OK!");}
else if(status==Status.TIMEOUT) {System.out.println("Timeout :-(");}
else {System.out.println("We have an exception: "+status.exception);}
2. Several Classes
class Status {}
class StatusOK extends Status {}
class StatusTimeout extends Status {}
class StatusException extends Status
{
final Exception e;
public StatusException(Exception e) {this.e=e;}
}
Then I would need a bunch of "instanceOf"-statements.
P.S.: OK it seems that I didn't explain it clearly enough. In my program I answer requests and I store the status of the processing of those requests:
Map<Request,Status> request2Status;
Thus I cannot use something like Status.getMessage(exception); because at that position in my code I do not know which exception it was. That why I want to save it inside the status.
Chosen solution
private static class LearnStatus implements Serializable
{
private static final long serialVersionUID = 1L;
public static final LearnStatus OK = new LearnStatus(null);
public static final LearnStatus TIMEOUT = new LearnStatus(null);
public static final LearnStatus NO_TEMPLATE_FOUND = new LearnStatus(null);
public static final LearnStatus QUERY_RESULT_EMPTY = new LearnStatus(null);
public static final LearnStatus NO_QUERY_LEARNED = new LearnStatus(null);
public final Exception exception;
private LearnStatus(Exception exception) {this.exception = exception; }
public static LearnStatus exceptionStatus(Exception cause)
{
if (cause == null) throw new NullPointerException();
return new LearnStatus(cause);
}
#Override public String toString()
{
if(this==OK) {return "OK";}
if(this==TIMEOUT) {return "timeout";}
if(this==NO_TEMPLATE_FOUND) {return "no template found";}
if(this==QUERY_RESULT_EMPTY) {return "query result empty";}
if(this==NO_QUERY_LEARNED) {return "no query learned";}
return "<summary>Exception: <details>"+exception.getLocalizedMessage()+"</details></summary>";
}
}
Problems with that
If I serialize an object with Status.OK in it, after deserialization if(status==Status.OK) does not work anymore.
New solution
I now included an enum type within the class. What do you think about it?
private static class LearnStatus implements Serializable
{
public enum Type {OK, TIMEOUT, NO_TEMPLATE_FOUND,QUERY_RESULT_EMPTY,NO_QUERY_LEARNED,EXCEPTION}
public final Type type;
private static final long serialVersionUID = 1L;
public static final LearnStatus OK = new LearnStatus(Type.OK,null);
public static final LearnStatus TIMEOUT = new LearnStatus(Type.TIMEOUT,null);
public static final LearnStatus NO_TEMPLATE_FOUND = new LearnStatus(Type.NO_TEMPLATE_FOUND,null);
public static final LearnStatus QUERY_RESULT_EMPTY = new LearnStatus(Type.QUERY_RESULT_EMPTY,null);
public static final LearnStatus NO_QUERY_LEARNED = new LearnStatus(Type.NO_QUERY_LEARNED,null);
public final Exception exception;
private LearnStatus(Type type, Exception exception) {this.type=type;this.exception = exception;}
public static LearnStatus exceptionStatus(Exception cause)
{
if (cause == null) throw new NullPointerException();
return new LearnStatus(Type.EXCEPTION,cause);
}
#Override public String toString()
{
switch(type)
{
case OK: return "OK";
case TIMEOUT: return "timeout";
case NO_TEMPLATE_FOUND: return "no template found";
case QUERY_RESULT_EMPTY:return "query result empty";
case NO_QUERY_LEARNED: return "no query learned";
case EXCEPTION: return "<summary>Exception: <details>"+exception.getLocalizedMessage()+"</details></summary>";
default: throw new RuntimeException("switch type not handled");
}
}
}
I would use an Exception unless everything is OK.
Like
System.out.println("Everything OK!");
} catch(TimeoutException te) {
System.out.println("Timeout :-(")
} catch(Exception e) {
System.out.println("We have an exception: " + e);
}
I don't see any need to use an enum when Exceptions are designed to do this sort of thing.
Adding yet another layer on top of the layer between you and the original exception you can do this.
interface Status {
String getMessage();
}
enum Statuses implements Status {
OK("Everything OK"), TIMEOUT("Timeout :-(");
private final String message;
private Statuses(String message) { this.message = message; }
String getMessage() { return message; }
}
class ExceptionStatus implement Status {
private final String message;
String getMessage() { return "Exception: " + message; }
}
// to print the message
System.out.println(status.getMessage());
There are several approaches to this, but all of them depend that you don't use Enums or that you don't use them exclusively. Keep in mind that an enum is basically a class that only has well-defined singletons as value.
One possible refactoring of this is to use a normal class with well-defined singletons instead of enums:
class Status implements Serializable {
// for serialization
private enum InternalStatus {
OK, TIMEOUT, EXCEPTION
}
public static final Status OK = new Status(null, InternalStatus.OK);
public static final Status TIMEOUT = new Status(null, InternalStatus.TIMEOUT);
private final Exception exception;
private final InternalStatus internalStatus;
private Status(Exception exception, InternalStatus internalStatus) {
this.exception = exception;
this.internalStatus = internalStatus;
}
public Exception getException() {
return exception;
}
public static Status exceptionStatus(Exception cause) {
if (cause == null) throw new NullPointerException();
return new Status(cause, InternalStatus.EXCEPTION);
}
// deserialization logic handling OK and TIMEOUT being singletons
private final Object readResolve() {
switch (internalStatus) {
case InternalStatus.OK:
return OK;
case InternalStatus.TIMEOUT:
return TIMEOUT;
default:
return this;
}
}
}
You can now check for status == Status.OK and status == Status.TIMEOUT. If your status variable is neither OK nor TIMEOUT, it must be caused by an exception, which you can retrieve via getException.
As a downside, you lose the switch functionality and must check via if.

Categories

Resources