简体   繁体   中英

Java Generics class and constructor

I want to create the parent class for doing the GetInstance. But I always got crash. mInstance = new Instance<>(); always crash this line

public class Instance<T> {

    public Instance<T> mInstance;

    public Instance<T> GetInstance() {
        return mInstance;
    }

    public <T> Instance() {
        mInstance = new Instance<>();
    }
}


public class Timer extends Instance<Timer> {

}

java.lang.StackOverflowError at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.g lobal.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.push ups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google .pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.familyfit.google.pushups.global.Instance.(Instance.java:21) at com.fami

You're doing it wrong

In your constructor, you're calling itself recursively hence stackoverflow.

Either move the initialization of mInstance to outside the class or make it static.

Try this:

public static class Instance<T> {

    private static final Instance<?> mInstance = new Instance<>();

    @SuppressWarnings("unchecked")
    public Instance<T> GetInstance() {
        // Make generic static instance. 
        // Strategy used similar to Collections.emptyList() implementation
        return (Instance<T>) mInstance;
    }

    private Instance() {

    }
}

This is how IntelliJ writes a Singleton using his wizard.

public final class Singleton{

private static final Singleton ourInstance = new Singleton();

public static Singleton getInstance() {
    return ourInstance;
}

/**
 * Private constructor
 */
private Singleton() {}
}

In this way, a singleton gets created only one time. Notice the private constructor, which does not allows you to create more instances, and the static final instance which has only one object of this class. At least, the public static Singleton getInstance method returns you the instance. Remember that for some case you would declare other methods of the singleton class as synchronized , but this is dependent to the business logic of your class.

Edit: as another user suggested, it is better to mark as final the class to prevent unwanted modification to the singleton logic.

You have 2 slight errors, which lead to, your singleton class not working. Firstly, your mInstance is not a static field of the class, which means that every instance of class Instance (badly choosen name TBH, use something more specific) will have it's own mInstance defeating the purpose of the whole, one single instance.

Secondly you have a generic class, which sadly doesn't work so well in a singleton context. Because when you always only have one instance, it doesn't make sense to introduce generics. because then you just could hardcode the generic variable T with String instead, or the type you're using.

To overcome those problems, you need to change your class as following:

public final class Instance {

     private static Instance mInstance;

     public static Instance getInstance(){
         if(mInstance == null){
             mInstance = new Instance();
         }
         return mInstance;
     }

     private Instance(){
         // your initialization logic
     }
}

I also made some normal decisions, eg making the class final , to not let a second instance pop up , eg by subclassing. Then also i made the constructor and the mInstnace field private . To prevent again, unwanted changes on the class itself, and not letting the user allow to create more than one instance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM