Java generics, singletons and static methods - java

So I have a few 'Manager' classes, for example GroupManager. All these Managers are singletons.
Using this method for instancing:
private static GroupManager groupManager = null;
private GroupManager()
{
}
public static GroupManager Instance()
{
if (groupManager == null)
{
groupManager = new GroupManager();
}
return groupManager;
}
I'm thinking I should start to use some inheritance as they have a lot of copied methods.
The Instance() methods for each Manager is the same.
So for inheritance i can do this (obviously):
GroupManager extends Manager
Is it possible to use generics to use the same Instance method for all managers, something like:
public class Manager<E>
{
private static E instance = null;
public static E Instance()
{
if (instance == null)
{
instance = new E();
}
return instance;
}
}
I think that makes sense :)
So then you would do GroupManager.Instance() like normal.

You don't understand how generics and statics work. If you have a static field or method (such as "instance" or instance()), which can be called without instantiating the class Manager, how do you expect the JVM (and the compiler even) to know what type E is supposed to be?
Here's an example, as per G_H's suggestion:
GeneralManager and AreaManager both extend Manager
The Manager class is the only one that has the getInstance() static method:
public class Manager {
private static Map<Class<? extends Manager>,Manager> INSTANCES_MAP = new java.util.HashMap<Class<? extends Manager>, Manager>();
//Also, you will want to make this method synchronized if your application is multithreaded,
//otherwise you mihgt have a race condition in which multiple threads will trick it into
//creating multiple instances
public static <E extends Manager> E getInstance(Class<E> instanceClass) throws InstantiationException, IllegalAccessException {
if(INSTANCES_MAP.containsKey(instanceClass)) {
return (E) INSTANCES_MAP.get(instanceClass);
} else {
E instance = instanceClass.newInstance();
INSTANCES_MAP.put(instanceClass, instance);
return instance;
}
}
}

Nope, it's not gonna work. Java uses generics at compile time for type checking, but doesn't generate extra classes or retain info regarding type parameters at runtime.
When you declare Manager<E> with that type parameter E, that's something that will only play a role in an actual instance. You could have a subclass like GroupManager extends Manager<String> or whatever, but that's not magically gonna generate a variety of the static method.
Static methods and members belong with a class, not an instance. So trying to use generics there, which are intended for typing instances, isn't gonna fly.

If you make your group manager class as follows then you can call your instance method.
public class GroupManager extends Manager<GroupManager>{}
And in your Manager class try this...
public class Manager<E>
{
private static E instance = null;
public static E Instance()
{
try {
return instance.newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
Or if you know the object you want an instance for, just make the method generic
public static <T> T getInstance(Class<T> t){
try {
return t.newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
I havn't tried any of this so not sure if it will work.

Injecting the constructor in a generic context. Cash is not thread safe, but is only used in static context so its fine if you don't miss use it
public class Example {
public static class MySingletonClass {
}
public interface Provider<T> {
T get();
}
static final Provider<MySingletonClass> myClassInstanceProvider = new Cash<MySingletonClass>(new Provider<MySingletonClass>() {
#Override
public MySingletonClass get() {
return new MySingletonClass();
}
});
public static class Cash<T> implements Provider<T> {
private Provider<T> provider;
public Cash(Provider<T> provider) {
this.provider = provider;
}
#Override
public T get() {
final T t = provider.get();
provider = new Provider<T>() {
#Override
public T get() {
return t;
}
};
return t;
}
}
}

public class Manager<E>{
private static Object instance = null;
public static E Instance() {
if (instance == null)
{
instance = new E();
}
return (E)instance;
}
}

Related

How to create an instance just by generic type T [duplicate]

This question already has answers here:
Create instance of generic type in Java?
(29 answers)
Closed 5 years ago.
I want to create an instance just by defining the type for a generic class
public abstract class Base<T> {
private final T genericTypeObject;
protected Base(){
//Create instance of T here without any argument
}
}
So that I just can call the default constructor:
public class Child extends Base<SomeClass>{
public Child () {
super();
}
}
and the Base-class implementation will create me an instance of the GenericType.
The generic information will be erased at compile time, so there will be no T anymore during runtime (you loose the information). Thats why you somewhere will need a Class<> to store the information.
The most clean & simple solution form my point of view is to pass in the class to to the constructor. I know you requested it to be without any constructor argument, but I do not think this is possible.
Code Sample
public abstract class AbstractBase<T> {
private final T genericTypeObject;
protected Base(Class<T> type){
try {
genericTypeObject = type.newInstance();
} catch (InstantiationException e) {
// Handle
} catch (IllegalAccessException e) {
// Handle
}
}
}
public class Child extends Base<SomeClass> {
public Child () {
super(SomeClass.class);
}
}
Alternative Solution
Using a Supplier (thanks for the comment #Jorn Vernee):
public abstract class AbstractBase<T> {
private final T genericTypeObject;
public AbstractBase(Supplier<T> supplier) {
genericTypeObject = supplier.get();
}
}
public class Child extends AbstractBase<SomeClass> {
public Child() {
super(SomeClass::new);
}
}
You must have access to the class to create an instance, so creating an instance without an argument is not possible. You must pass a Class<T>.
UPDATE:
See #JDC's answer.
At runtime this returns me a Class instance:
public static Class<?> getGenericClassOfType(Object object){
Class<?> clazz = (Class<?>) ((ParameterizedType) object.getClass() .getGenericSuperclass()).getActualTypeArguments()[0];
return clazz;
}
and afterwards I can initiate it with:
public static <T> T getDefaultInstance(Class<T> clazz) throws IllegalAccessException, InvocationTargetException, InstantiationException {
T instance = null;
Constructor<T>[] constructors = (Constructor<T>[]) clazz.getDeclaredConstructors();
Constructor<T> constructor = null;
for (Constructor cstr : constructors) {
//Only if default constructor
if (cstr.getParameters().length == 0) {
constructor = (Constructor<T>) cstr;
break;
}
}
if (constructor != null) {
constructor.setAccessible(true);
instance = constructor.newInstance();
}
return instance;
}
so the code in my base constructor looks like:
public abstract class BaseScene<T extends SceneController> {
private final static Logger LOGGER = LogManager.getLogger(BaseScene.class);
private final T sceneController;
//public T getSceneController() {
// return sceneController;
//}
protected BaseScene(){
T newInstance = null;
try {
Class<T> clazz = (Class<T>)ReflectionHelper.getGenericClassOfType(this);
newInstance = ReflectionHelper.getDefaultInstance(clazz);
} catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
LOGGER.error("Error while trying to initiate BaseScene",e);
}
sceneController = newInstance;
}
}
which works perfectly as I tested it.

The blank final field INSTANCE may not have been initialized

I follow this post to create a thread safe singleton classs, but there is an compile error in INSTANCE. It said The blank final field INSTANCE may not have been initialized. My requirement is I want INSTANCE is null and the program log this error and try init this object again. If still fail, the program exit.
public class ServiceConnection {
private static class SingletonObjectFactoryHolder{
private static final ServiceSoapBindingStub INSTANCE;
static
{
try {
INSTANCE = new ServiceSoapBindingStub();
} catch (AxisFault e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static ServiceSoapBindingStub getInstance() {
return SingletonObjectFactoryHolder.INSTANCE;
}
}
But If I use the Code as follows, another error: The final field INSTANCE may already have been assigned
public class ServiceConnection {
private static class SingletonObjectFactoryHolder{
private static final ServiceSoapBindingStub INSTANCE;
static
{
try {
INSTANCE = new ServiceSoapBindingStub();
} catch (AxisFault e) {
INSTANCE = null;
e.printStackTrace();
}
}
}
public static ServiceSoapBindingStub getInstance() {
return SingletonObjectFactoryHolder.INSTANCE;
}
}
But If I use the Code as follows no error pop up.
public class ServiceConnection {
private static class SingletonObjectFactoryHolder{
private static final ServiceSoapBindingStub INSTANCE;
static
{
try {
INSTANCE = new ServiceSoapBindingStub();
} catch (AxisFault e) {
e.printStackTrace();
throw new RuntimeException();
}
}
}
public static ServiceSoapBindingStub getInstance() {
return SingletonObjectFactoryHolder.INSTANCE;
}
}
Why this happens?
Given what you've said, you shouldn't be using class initialization for this. In particular:
You want to try multiple times
You want to use a checked exception
Both of those are feasible, but you'll need to move the initialization into the getInstance method:
public class ServiceConnection {
private static final Object lock = new Object();
private static ServiceSoapBindingStub instance;
public static ServiceSoapBindingStub getInstance() throws AxisFault {
// Note: you could use double-checked locking here if you really
// wanted.
synchronized (lock) {
if (instance == null) {
instance = new ServiceSoapBindingStub();
}
return instance;
}
}
}
(You can catch the exception to log it and then rethrow, of course - but consider whether a higher level would be logging it anyway.)

How to cast from class type to interface

I have an interface which is implemented by few classes. Based on the full name of the class I want to initialize the class objects.
Interface,
public interface InterfaceSample{
}
Class files,
public class ABC implements InterfaceSample{
}
public class XYZ implements InterfaceSample{
}
A sample test class,
public class SampleManager{
public static InterfaceSample getInstance(String className) {
InterfaceSample instance = null;
try {
instance = (InterfaceSample) Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return instance;
}
}
I am getting the following error,
"Cannot cast from Class<capture#1-of ?> to InterfaceSample"
How can I initialize the classes based on its name.
You're almost there:
instance = (InterfaceSample) Class.forName(className).newInstance();
remember to mark the method with:
throws Exception
because newInstance() is marked so as well (it throws InstantiationException and IllegalAccessException to be precise).
You must invoke newInstance() on the class to get an instance.
public class SampleManager{
public static InterfaceSample getInstance(String className) throws Exception {
InterfaceSample instance = null;
try {
instance = (InterfaceSample) Class.forName(className).newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return instance;
}
}

Case Study: Singleton class inheritance - Good or bad?

I have an example code of Singleton class inheritance below. However, I've not forseen if there's any hidden issue might happen with this code. Can someone analyze and give me a hint?
interface ChairIF {
public int getLeg();
public void test();
}
class ChairImpl implements ChairIF {
private static final Lock lock = new ReentrantLock();
private static ChairIF instance = null;
public static ChairIF getInstance(String clazzName) {
//get class by clazzName
Class clazz = null;
try {
clazz = Class.forName(clazzName);
} catch (ClassNotFoundException ex) {
lock.lock();
try {
if (instance == null) {
instance = new ChairImpl();
}
} finally {
lock.unlock();
}
}
//init singleton instance of clazzName
if (instance == null) {
lock.lock();
try {
if (instance == null) {
instance = (ChairIF) clazz.newInstance();
} else {
if (instance.getClass() != clazz) {
instance = (ChairIF) clazz.newInstance();
}
}
} catch (Exception ex) {
instance = new ChairImpl();
} finally {
lock.unlock();
}
} else {
lock.lock();
try {
if (!instance.getClass().getName().equals(clazz.getName())) {
instance = (ChairIF) clazz.newInstance();
}
} catch (Exception ex) {
instance = new ChairImpl();
} finally {
lock.unlock();
}
}
return instance;
}
public int getLeg() {
return 4;
}
public void test() {
throw new UnsupportedOperationException();
}
}
class ThreeLegChair extends ChairImpl {
public ThreeLegChair() {}
public int getLeg() {
return 3;
}
public void test() {
int i = 0;
while(i < 10000) {
System.out.println("i: " + i++);
}
}
}
class NoLegChair extends ChairImpl {
public NoLegChair() {}
public int getLeg() {
return 0;
}
public void test() {
int j = 0;
while(j < 5000) {
System.out.println("j: " + j++);
}
}
}
public class Test {
public static void main(String[] args) {
System.out.println(ChairImpl.getInstance("ThreeLegChair").getLeg());
System.out.println(ChairImpl.getInstance("NoLegChair").getLeg());
/***
TODO: build logic to run 2 test() simultaneously.
ChairImpl.getInstance("ThreeLegChair").test();
ChairImpl.getInstance("NoLegChair").test();
****/
}
}
As you can see, I did put some test code in 2 subclasses. ThreeLegChair is to loop from 0 to 10000 and print it out. NoLegChair is to loop only from 0 to 5000 and print it out.
The result I got in the console log is correct. ThreeLegChair printed i from 0 to 10000. NoLegChair printed j from 0 to 5000.
Please share me your thought :)
Singleton pattern is achieved using the concept of private constructor i.e. the class itself is responsible for creating single instance of the class (singleton) and preventing other classes from creating objects.
Now as the constructor is private, you cannot inherit the singleton class at first place. In your case, I do not see a private constructor which makes it vulnerable to object creation from other classes accessing it.
Singleton pattern examples:
Using enumerations in Java
enum SingletonEnum {
SINGLE_INSTANCE;
public void doStuff() {
System.out.println("Singleton using Enum");
}
}
Lazy initialization approach
class SingletonClass {
private static SingletonClass singleInstance;
private SingletonClass() {
// deny access to other classes
}
// The object creation will be delayed until getInstance method is called.
public static SingletonClass getInstance() {
if (null == singleInstance) {
// Create only once
singleInstance = new SingletonClass();
}
return singleInstance;
}
}
However, the above example may not guarantee singleton behavior in multithreaded environment. It is recommended to use double checked locking mechanism to ensure that you have created a single instance of this class.
The code you post isn't an implementation of the singleton pattern.
Quite simply, you can do:
ChairImpl ci = new ChairImpl();
And instantiate as many as you want.
The traditional method of implementing the singleton pattern is the make the constructor private, have a private static field that holds the single instance of the class, and a static getInstance() method that either instantiates that instance or returns the existing one. Making that threadsafe involves either declaring it synchronized or using a locking scheme.
The private constructor bit makes it so you can't inherit from it.
That said, in Java the preferred way is using an enum which provides all the hard parts for free:
public enum MySingleton {
INSTANCE;
public int getLeg() {
return 4;
}
}
And using as:
MySingleton ms = MySingleton.INSTANCE;
int leg = ms.getLeg();
Singletons usually have private constructor. Your class is not following proper Singleton pattern. otherwise you would not be inherit your singleton class.

How to 'wrap' two classes with identical methods?

I have to handle two classes with identical methods but they don't implement the same interface, nor do they extend the same superclass. I'm not able / not allowed to change this classes and I don't construct instances of this classes I only get objects of this.
What is the best way to avoid lots of code duplication?
One of the class:
package faa;
public class SomethingA {
private String valueOne = null;
private String valueTwo = null;
public String getValueOne() { return valueOne; }
public void setValueOne(String valueOne) { this.valueOne = valueOne; }
public String getValueTwo() { return valueTwo; }
public void setValueTwo(String valueTwo) { this.valueTwo = valueTwo; }
}
And the other...
package foo;
public class SomethingB {
private String valueOne;
private String valueTwo;
public String getValueOne() { return valueOne; }
public void setValueOne(String valueOne) { this.valueOne = valueOne; }
public String getValueTwo() { return valueTwo; }
public void setValueTwo(String valueTwo) { this.valueTwo = valueTwo; }
}
(In reality these classes are larger)
My only idea is now to create a wrapper class in this was:
public class SomethingWrapper {
private SomethingA someA;
private SomethingB someB;
public SomethingWrapper(SomethingA someA) {
//null check..
this.someA = someA;
}
public SomethingWrapper(SomethingB someB) {
//null check..
this.someB = someB;
}
public String getValueOne() {
if (this.someA != null) {
return this.someA.getValueOne();
} else {
return this.someB.getValueOne();
}
}
public void setValueOne(String valueOne) {
if (this.someA != null) {
this.someA.setValueOne(valueOne);
} else {
this.someB.setValueOne(valueOne);
}
}
public String getValueTwo() {
if (this.someA != null) {
return this.someA.getValueTwo();
} else {
return this.someB.getValueTwo();
}
}
public void setValueTwo(String valueTwo) {
if (this.someA != null) {
this.someA.setValueTwo(valueTwo);
} else {
this.someB.setValueTwo(valueTwo);
}
}
}
But I'm not realy satisfied with this solution. Is there any better / more elegant way to solve this problem?
A better solution would be to create an interface to represent the unified interface to both classes, then to write two classes implementing the interface, one that wraps an A, and another that wraps a B:
public interface SomethingWrapper {
public String getValueOne();
public void setValueOne(String valueOne);
public String getValueTwo();
public void setValueTwo(String valueTwo);
};
public class SomethingAWrapper implements SomethingWrapper {
private SomethingA someA;
public SomethingWrapper(SomethingA someA) {
this.someA = someA;
}
public String getValueOne() {
return this.someA.getValueOne();
}
public void setValueOne(String valueOne) {
this.someA.setValueOne(valueOne);
}
public String getValueTwo() {
return this.someA.getValueTwo();
}
public void setValueTwo(String valueTwo) {
this.someA.setValueTwo(valueTwo);
}
};
and then another class just like it for SomethingBWrapper.
There, a duck-typed solution. This will accept any object with valueOne, valueTwo properties and is trivially extensible to further props.
public class Wrapper
{
private final Object wrapped;
private final Map<String, Method> methods = new HashMap<String, Method>();
public Wrapper(Object w) {
wrapped = w;
try {
final Class<?> c = w.getClass();
for (String propName : new String[] { "ValueOne", "ValueTwo" }) {
final String getter = "get" + propName, setter = "set" + propName;
methods.put(getter, c.getMethod(getter));
methods.put(setter, c.getMethod(setter, String.class));
}
} catch (Exception e) { throw new RuntimeException(e); }
}
public String getValueOne() {
try { return (String)methods.get("getValueOne").invoke(wrapped); }
catch (Exception e) { throw new RuntimeException(e); }
}
public void setValueOne(String v) {
try { methods.get("setValueOne").invoke(wrapped, v); }
catch (Exception e) { throw new RuntimeException(e); }
}
public String getValueTwo() {
try { return (String)methods.get("getValueTwo").invoke(wrapped); }
catch (Exception e) { throw new RuntimeException(e); }
}
public void setValueTwo(String v) {
try { methods.get("setValueTwo").invoke(wrapped, v); }
catch (Exception e) { throw new RuntimeException(e); }
}
}
You can use a dynamic proxy to create a "bridge" between an interface you define and the classes that conform but do not implement your interface.
It all starts with an interface:
interface Something {
public String getValueOne();
public void setValueOne(String valueOne);
public String getValueTwo();
public void setValueTwo(String valueTwo);
}
Now you need an InvocationHandler, that will just forward calls to the method that matches the interface method called:
class ForwardInvocationHandler implements InvocationHandler {
private final Object wrapped;
public ForwardInvocationHandler(Object wrapped) {
this.wrapped = wrapped;
}
#Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Method match = wrapped.getClass().getMethod(method.getName(), method.getParameterTypes());
return match.invoke(wrapped, args);
}
}
Then you can create your proxy (put it in a factory for easier usage):
SomethingA a = new SomethingA();
a.setValueOne("Um");
Something s = (Something)Proxy.newProxyInstance(
Something.class.getClassLoader(),
new Class[] { Something.class },
new ForwardInvocationHandler(a));
System.out.println(s.getValueOne()); // prints: Um
Another option is simpler but requires you to subclass each class and implement the created interface, simply like this:
class SomethingAImpl extends SomethingA implements Something {}
class SomethingBImpl extends SomethingB implements Something {}
(Note: you also need to create any non-default constructors)
Now use the subclasses instead of the superclasses, and refer to them through the interface:
Something o = new SomethingAImpl(); // o can also refer to a SomethingBImpl
o.setValueOne("Uno");
System.out.println(o.getValueOne()); // prints: Uno
i think your original wrapper class is the most viable option...however it can be done using reflection, your real problem is that the application is a mess...and reflection is might not be the method you are looking for
i've another proposal, which might be help: create a wrapper class which has specific functions for every type of classes...it mostly copypaste, but it forces you to use the typed thing as a parameter
class X{
public int asd() {return 0;}
}
class Y{
public int asd() {return 1;}
}
class H{
public int asd(X a){
return a.asd();
}
public int asd(Y a){
return a.asd();
}
}
usage:
System.out.println("asd"+h.asd(x));
System.out.println("asd"+h.asd(y));
i would like to note that an interface can be implemented by the ancestor too, if you are creating these classes - but just can't modify it's source, then you can still overload them from outside:
public interface II{
public int asd();
}
class XI extends X implements II{
}
class YI extends Y implements II{
}
usage:
II a=new XI();
System.out.println("asd"+a.asd());
You probably can exploit a facade along with the reflection - In my opinion it streamlines the way you access the legacy and is scalable too !
class facade{
public static getSomething(Object AorB){
Class c = AorB.getClass();
Method m = c.getMethod("getValueOne");
m.invoke(AorB);
}
...
}
I wrote a class to encapsulate the logging framework API's. Unfortunately, it's too long to put in this box.
The program is part of the project at http://www.github.com/bradleyross/tutorials with the documentation at http://bradleyross.github.io/tutorials. The code for the class bradleyross.library.helpers.ExceptionHelper in the module tutorials-common is at https://github.com/BradleyRoss/tutorials/blob/master/tutorials-common/src/main/java/bradleyross/library/helpers/ExceptionHelper.java.
The idea is that I can have the additional code that I want to make the exception statements more useful and I won't have to repeat them for each logging framework. The wrapper isn't where you eliminate code duplication. The elimination of code duplication is in not having to write multiple versions of the code that calls the wrapper and the underlying classes. See https://bradleyaross.wordpress.com/2016/05/05/java-logging-frameworks/
The class bradleyross.helpers.GenericPrinter is another wrapper that enables you to write code that works with both the PrintStream, PrintWriter, and StringWriter classes and interfaces.

Categories

Resources