Singleton Factory - Implementation using Java 8 - java

I want to implement a generic singleton factory pattern where I pass the Class of the required object as a parameter and the factory class should check in the map if there's already an object created for it, if its, return the object from map. If not, create a new instance, put it in the map and return the instance.
I can have a generic return type as Object, but I don't want to cast the returned object at every place I call the get instance method.
The below is the code: I get a compilation error at the line c.cast(instance);
We do not use spring/dependency injection, but trying implement common class to take care of creating all singleton objects.
public class SingletonFactory {
public static Map<String,Object> objectFactory = new HashMap<String, Object>();
public static <T extends Object> T getInstance(Class<?> c){
String key = c.toString();
Object instance= objectFactory.get(key);
if (instance == null) {
synchronized (c) {
try {
instance = c.newInstance();
objectFactory.put(key, instance);
} catch(IllegalAccessException | InstantiationException e) {
throw new RuntimeException("Exception while creating singleton instance for class : "+key+" - Exception Message : "+e);
}
}
}
return c.cast(instance);
}
}

First, I can point out that <T extends Object> can be replaced with just <T> because everything in Java, involving generics, must be an Object.
The second part that you're really close on is Class<?> c. That says that you can pass any class in and it will return whatever type T is. c.cast(instance) can be replaced with (T) instance if you think that looks better but, there's actually a difference which goes into more detail here: Java Class.cast() vs. cast operator .
The final code looks like this:
public class SingletonFactory {
public static Map<String,Object> objectFactory = new HashMap<String, Object>();
public static <T> T getInstance(Class<T> c){
synchronized (c) {
String key = c.toString();
Object instance= objectFactory.get(key);
if (instance == null) {
try {
instance = c.newInstance();
objectFactory.put(key, instance);
} catch(IllegalAccessException | InstantiationException e){
throw new RuntimeException("Exception while creating singleton instance for class : "+key+" - Exception Message : "+e);
}
}
return c.cast(instance);
// or
return (T) instance;
}
}
}
Also if you really wanted to, you could keep everything in your original code and cast instance to T at the end of the method and it should work. The only thing is your method calls would look like SingletonFactory.getInstance<Foo>(Foo.class) instead of SingletonFactory.getInstance(Foo.class). That is because of the Class<?> in your original code instead of Class<T>.
EDIT: I also changed the code to synchronize earlier thanks #Khan9797

Firstly, you need to synchronize much earlier, you should simply synchronize the method, otherwise, you can create extra instance in a race condition.
Secondly, you should define the generic of the method like this:
public static <T> T getInstance(Class<? extends T> c)

First of all, getInstance() is not thread-safe in terms of creating the new instance. There is a chance that you could create multiple instances of a given class when multiple threads running simultaneously and variable == null is true.
public class SingletonFactory {
private static Map<Class, Object> objectHolder = new HashMap<>();
public <T> T getInstance(Class<T> clazz) {
Object instance = objectHolder.get(clazz);
if(instance == null) {
synchronized (clazz) {
if(instance == null) {
try{
instance = clazz.newInstance();
objectHolder.put(clazz, instance);
} catch (Exception e) {
// do some logging and maybe exit the program. Since the it would affect how whole system works.
}
}
}
}
return clazz.cast(instance);
}
}
But the better approach would be using eager initialization instead of lazy initialization. The reason why we need to synchronize the critical section is that we are creating those instances when we need it. So it became a readers-writers problem. But if we only do reading process then we don't need to synchronize since we are not going to modify its value. If you know all the classes which are going to be created and need to be accessed we could just initialize them in the first place. So that we would get rid off the synchronized performance drawback
public class SingletonFactory {
private static Map<Class, Object> objectHolder = new HashMap<>();
private Map<Class, Object> initialize() {
Map<Class, Object> objectHolder = new HashMap<>();
// create some objects and put it into Map
return objectHolder;
}
public <T> T getInstance(Class<T> clazz) {
Object instance = objectHolder.get(clazz);
return clazz.cast(instance);
}
}

Related

Safely call setter after getter chain eg foo.getX().getY().setZ(...);

How do I safely call setter after getter chain eg foo.getX().getY().setZ(...);? For example, suppose I have a nested POJO, and I want to be able to set a field of a nested object.
Foo foo = ...
foo.getX().getY().setZ(...);
I want the behavior to be such that if X and Y do not exist then they are created automatically; otherwise it reuses the existing object.
In other words, I want it to be behave equivalent to
Foo foo = ...
X x = foo.getX();
if (x == null) {
x = new X();
foo.setX(x);
}
Y y = x.getY();
if (y == null) {
y = newY();
x.setY(y);
}
y.setZ(...);
I'm wondering if there is a trick out there using reflection/functional that comes close to this.
I also have the following constraints:
I cannot modify any of the classes
The solution must know about only the public getters and setters, not the private instance variables
I want the getter to modify the internal state only when specifically requested; I don't want x = foo.getX() to modify foo.
Use functional programming. Create a method that accepts a getter, a setter and a supplier for the default value, that returns a getter encapsulating the logic you need:
public static <T, U> Function<T, U> getOrSetDefault(
Function<T, U> getter,
BiConsumer<T, U> setter,
Supplier<U> defaultValue) {
return t -> {
U u = getter.apply(t);
if (u == null) {
u = defaultValue.get();
setter.accept(t, u);
}
return u;
};
}
Then create these decorated getters:
Function<Foo, X> getX = getOrSetDefault(Foo::getX, Foo::setX, X::new);
Function<X, Y> getY = getOrSetDefault(X::getY, X::setY, Y::new);
Finally, chain them and apply the resulting function passing in your foo instance as an argument:
Foo foo = ...
getX.andThen(getY).apply(foo).setZ(...);
EDIT: This assumes that both X and Y have a no-args constructor that is referenced by X::new and Y::new, respectively. But you could use anything as the Supplier, i.e. an already created instance, or the return value of a method, etc.
TL;DR: Don't try to force functional Java where there clearly is no place for it.
The only way you can do this functionally in Java 8 without modifying any of the classes is using Optionals and their .orElse() method. It gets really long really quick, but it's the only way that actually makes sense using functional if you want to do it in one line only.
Optional.ofNullable(foo.getX()).orElseGet(() -> { foo.setX(new X()); return foo.getX(); }).setY(...);
If foo.setX() also returns the setted value it can be simplified as:
Optional.ofNullable(foo.getX()).orElseGet(() -> foo.setX(new X())).setY(...);
This is the only generic and functional way of doing it that I can think of. Stated the above, you can clearly see that this becomes huge and ugly even for just a chain of two getters, so I wouldn't advise it. I would definitely suggest you to use the classic multi-statement approach if you have to chain more than one call.
Another option, even thought not really that functional, is to use the tristate operator, still only if the setter returns the setted value:
(foo.getX() == null ? foo.setX(new X()) : foo.getX()).setY(...);
This has the probably unwanted side effect of calling the getter twice if the element is found, which you may not like, but could be possibly ignored if the getter caches the value somehow.
To start off I just want to mention that this probably isn't the best solution and I'm sure there are ways to optimize this. That said, I wanted to try my hand at CGLIB and ObjenesisHelper again.
Using CGLIB and ObjenesisHelper we can wrap the data object in a proxy which will intercept the get methods. Using this interceptor we can add the logic you described in your post. Lets start off by assume these are our data types (using lombok for brevity).
#Data class W { private X x; }
#Data class X { private Y y; }
#Data class Y { private Z z; }
#Data class Z { private int alpha; }
Our final solution can be used like the following:
public static void main(String[] args) {
final W w = ProxyUtil.withLazyDefaults(new W());
System.out.println(w.getX().getY().getZ().getAlpha());
}
Implementation
Currently, if we try to invoke new W().getX().getY().getZ().getAlpha() we will get a NullPointerException when invoking getY() because getX() returned null. Even if we manage to produce a default X value, we will still need a default Y value to not get a null pointer on getZ() and getAlpha() and so forth. The proxy we create needs to be generic and be able to wrap its sub components recursively.
Okay, so lets start. The first thing we need to do is create a MethodInterceptor. Whenever any call hits our proxy instance it will perform the logic of our MethodInterceptor. We need to first determine if the method called is a getter. If not we will ignore it. During this getter call, if the value is not present in our data we will create it and update the object. If the value contained by the getter is an original unwrapped class, we will replace it with a wraped version. Finally we will return the wrapped instance. Edit I updated this to not inject wrapped instances into the real Data objects. This will be less performant if the object is accessed mutliple times this way
public class ProxyUtil {
public static <T> T withLazyDefaults(final T data) {
final MethodInterceptor interceptor = (object, method, args, proxy) -> {
if (method.getName().startsWith("get")) {
final Class<?> returnType = method.getReturnType();
Object response = method.invoke(data, args);
if (response == null) {
response = returnType.newInstance();
data.getClass()
.getDeclaredMethod(
method.getName().replaceFirst("get", "set"),
returnType)
.invoke(data, response);
}
if (!returnType.isPrimitive()) {
response = withLazyDefaults(response);
}
return response;
}
return method.invoke(data, args);
};
...
The rest of this method involves using CGLIB and Objenisis Helper to construct the wrapper instance. CGLib will allow you to proxy both classes and interfaces and ObjenesisHelper will allow you to construct an instance of a class without having to invoke a constructor. See here for a CGLib example and here for a ObjenesisHelper example.
...
final Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(data.getClass());
final Set<Class<?>> interfaces = new LinkedHashSet<>();
if (data.getClass().isInterface()) {
interfaces.add(data.getClass());
}
interfaces.addAll(Arrays.asList(data.getClass().getInterfaces()));
enhancer.setInterfaces(interfaces.toArray(new Class[interfaces.size()]));
enhancer.setCallbackType(interceptor.getClass());
final Class<?> proxyClass = enhancer.createClass();
Enhancer.registerStaticCallbacks(proxyClass, new Callback[]{interceptor});
return (T) ObjenesisHelper.newInstance(proxyClass);
}
}
Caveats
This is not a thread safe operation.
Reflection will slow down your code.
Better error handling needs to added for the reflection calls.
If a class does not have a no-arg constructor this will not work.
Does not account for inheritance of data classes
This could be best effort by checking for a no-arg ctor/setter first.
I ended up using a combination of functional and reflection and tried to make the interface similar to Java's Optional. Here is an example of how I would write foo.getX().getY().setZ(val);
MutableGetter.of(foo).map(Foo::getX).map(x::getY).get().setZ(val);
This is the code (It's still WIP).
I used reflection to avoid having to pass the setter and constructor
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Supplier;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.ProxyFactory;
import lombok.Getter;
import lombok.NonNull;
public class MutableGetter<T>
{
private T object;
private MutableGetter(T object)
{
this.object = object;
}
public static <T> MutableGetter<T> of(#NonNull T object)
{
return new MutableGetter<>(object);
}
public <U> MutableGetter<U> map(Function<T, U> getter)
{
Method getterMethod = getGetterMethod(object.getClass(), getter);
BiConsumer<T, U> setter = getSetter(getterMethod);
Supplier<U> defaultValue = getDefaultValue(getterMethod);
U nextObject = getter.apply(object);
if (nextObject == null) {
nextObject = defaultValue.get();
setter.accept(object, nextObject);
}
return new MutableGetter<>(nextObject);
}
public T get()
{
return object;
}
private static <U> Supplier<U> getDefaultValue(Method getterMethod)
{
return () -> {
try {
Constructor<?> constructor = getterMethod.getReturnType().getConstructor();
constructor.setAccessible(true);
return (U) constructor.newInstance();
} catch (Exception e) {
throw new IllegalStateException(e);
}
};
}
private static <T, U> BiConsumer<T,U> getSetter(Method getterMethod)
{
return (obj, arg) -> {
Method setterMethod = getSetterFromGetter(getterMethod);
setterMethod.setAccessible(true);
try {
setterMethod.invoke(obj, arg);
} catch (Exception e) {
throw new IllegalStateException(e);
}
};
}
private static Method getSetterFromGetter(Method getter)
{
if (!getter.getName().startsWith("get")) {
throw new IllegalStateException("The getter method must start with 'get'");
}
String setterName = getter.getName().replaceFirst("get", "set");
Method[] methods = getter.getDeclaringClass().getMethods();
for (Method method: methods) {
if (method.getName().equals(setterName)) {
return method;
}
}
throw new IllegalStateException(String.format("Couldn't find setter in class %s with name %s", getter.getDeclaringClass(), setterName));
}
private static <T, U> Method getGetterMethod(Class<?> clazz, Function<T, U> getter)
{
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setSuperclass(clazz);
MethodRecorder methodRecorder = new MethodRecorder();
T proxy;
try {
proxy = (T) proxyFactory.create(new Class<?>[0], new Object[0], methodRecorder);
} catch (Exception e) {
throw new IllegalStateException(e);
}
getter.apply(proxy);
return methodRecorder.getLastInvokedMethod();
}
private static class MethodRecorder implements MethodHandler
{
#Getter
private Method lastInvokedMethod;
#Override
public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args)
{
this.lastInvokedMethod = thisMethod;
return null; // the result is ignored
}
}
}
Let me know if you have any suggestions

Effective version of writing the following method

Is there an elegant and best approach to write the following method?
private void throwException(Object obj) {
if (obj instanceof ClassA) {
ClassA resp = (ClassA) obj;
throw new CustomException(resp.getMessage(), resp.getCode());
} else if (obj instanceof ClassB) {
ClassB resp = (ClassB) obj;
throw new CustomException(resp.getMessage(), resp.getCode());
}
}
Note that ClassA and ClassB has the same exact properties. My point is that, I don't want to repeat the throw statement as much as possible.
Define a map like
Map<Class<?>, Function<Object, ? extends RuntimeException>> handlers = new LinkedHashMap<>();
The handlers will contain a Function that you can use to map the Object passed to throwException to get an exception. The key of the map is a class and value is the function that will map an object of the type (class) of the key to an exception.
Populate the above map as
handlers.put(ClassA.class, (obj) -> new CustomException(((ClassA) obj).getMessage(), ((ClassA) obj).getCode));
handlers.put(ClassB.class, (obj) -> new CustomException(((ClassB) obj).getMessage(), ((ClassB) obj).getCode));
With this, throwException would look like,
private void throwException(Object obj) {
Function<Object, ? extends RuntimeException> handler = handlers.entrySet().stream()
.filter(entry -> entry.getKey().isAssignableFrom(obj.getClass()))
.map(Map.Entry::getValue)
.findFirst()
.orElseThrow(() -> new RuntimeException("No handler found")); //Or use a default using orElseGet
throw handler.apply(obj);
}
I agree that it moves the casting elsewhere to make the method look clean.
The key part is the line
.filter(entry -> entry.getKey().isAssignableFrom(obj.getClass()))
We are checking if the object (passed to throwException) is of type returned by entry.getKey (the class of the map key). So, if you have inheritance hierarchy among the classes (ClassA, ClassB..), then you must populate the map in such an order so that the most generic ones (say like Object.class) comes after more specific ones.
A consequence of putting an entry into handlers with Object.class as the first entry would mean that the function (value) of Object.class will always be picked up for any object passed to it.
You can use Function<>s to wrap the getters into a custom interface beforehand.
interface Wrapper {
String getMessage();
int getCode();
<T> Function<T, Wrapper<T>> of(Function<T,String> getMsg, Function<T, Integer> getCde) {
return object -> new Wrapper() {
public String getMessage() { return getMsg.apply(object); }
public int getCode() { return getCde.apply(object); }
}
}
}
class Thrower {
Map<Class<?>, Supplier<Wrapper>> wrappers = new HashMap();
static {
wrappers.put(A.class, Wrapper.of(A.class, A::getMessage, A::getCode));
wrappers.put(B.class, Wrapper.of(B.class, B::getMessage, B::getCode));
}
void throwException(Object o) {
Wrapper wrapper = wrappers.get(o.getClass()).apply(o);
throw new CustomException(wrapper.getMessage(), wrapper.getCode());
}
}
You can kill two birds with one stone as this is a classical problem in the clean code design where you can choose to implement Visitor Design Pattern as a workaround to multiple If/else instanceof type of conditioning with a little bit of expansion to cover the problem of excessive throwing of new CustomExeption.
Here is what I can suggest you :
First it's better to change you design for ClassA and ClassB as:
abstract class ClassParent {
// your fields
public ClassParent (//your fields) {
// initializing your fields
}
public abstract void accept(ClassVisitor cv);
}
class ClassA extends ClassParent {
public ClassA(//your fileds) {
super(//your fileds);
}
/// other Implementation
public void accept(ClassVisitor cv) {
cv.visit(this);
}
}
class ClassB extends ClassParent {
public ClassB(//your fileds) {
super(//your fileds);
}
/// other Implementation
public void accept(ClassVisitor cv) {
cv.visit(this);
}
}
Now define your vistors as :
interface ClassVisitor {
abstract void visit(ClassA classA);
abstract void visit(ClassB classB);
}
class Visitor implements ClassVisitor {
public void visit(ClassA classA) {
classA.DoSomthing();
}
public void visit(ClassB classB) {
classB.DoSomthing();
}
}
Now it your ThrowException you can define :
private ClassVisitor visitor = new Visitor();
public void ThrowException(ClassParent classParent){
classParent.accept(visitor);
throw new CustomException(classParent.getMessage(), classParent.getCode);
}
This way you achieve both a cleaner code, more maintainable with
higher readablity by avoiding duplicate codes at the same time.

Java: Instantiate a generic type by returning a Supplier vs returning a new instance

I was reading how to instantiate a generic and after reading and applying this answer; I would like to know what would be the differences between expecting a Supplier<T> vs. expecting a new instance of T.
Example:
abstract class AbstractService<T extends AbstractEntity> {
protected Supplier<T> makeNewThing(); // supplier is expected
public T myMethod(){
T object = makeNewThing().get(); // local object by calling supplier
object.doStuff();
return object;
}
}
class CarService extends AbstractService<Car> {
public Supplier<Car> makeNewThing(){
return Car::new;
}
}
vs.
abstract class AbstractService<T extends SomeAbstractEntity> {
protected T makeNewThing(); // object is expected, newness is assumed
public T myMethod(){
T object = makeNewThing(); // local object by calling constructor
object.doStuff();
return object;
}
}
class CarService extends AbstractService<Car> {
public Car makeNewThing(){
return new Car();
}
}
The only thing I can think of is that expecting a supplier ensures that a new object will be created, but when expecting an object we can only assume that the implementing classes are calling the constructor and not re-using an existing instance.
I'd like to know of other objective differences and possible use cases, if any. Thanks in advance.
Using a Supplier postpones the creation of the instance.
This means that you might avoid a creation of an unnecessary instance.
For example, suppose you pass the output of makeNewThing() to some method.
public void makeNewThingSometimes (T newInstance)
{
if (someCondition) {
this.instance = newInstance;
}
}
public void makeNewThingSometimes (Supplier<T> supplier)
{
if (someCondition) {
this.instance = supplier.get();
}
}
Calling the first variant requires creating an instance of T even if you are not going to use it.
Calling the second variant only creates an instance of T when necessary.
Using a Consumer can save both storage (if the create instance requires a significant amount of memory) and time (if the execution of the constructor is expansive).
The only thing I can think of is that expecting a supplier ensures
that a new object will be created,
Not necessarily.
You implement the Supplier in this way :
return SomeEntityImplementation::new;
But you could have implemented it in this other way :
if (myCachedObject != null){
return (()-> myCachedObject);
}
return SomeEntityImplementation::new;
Both ways may be used to return a cached object or create a new one.
One of Supplier advantages is the case of Supplier creating an object : this one is actually created only as the Supplier.get() method is invoked.
Note that in your example, using Supplier doesn't bring any advantage as in both cases (with or without Supplier) the object creation is already performed in a lazy way : as the factory method is invoked.
To take advantage of it, you should have a method that provides a Supplier<T> as parameter as in the Eran and Dasblinkenlight examples.
Another Supplier advantage is its ability to implement factory that may return multiple of things.
Using Supplier allows to have a shorter and more readable code and besides that doesn't rely on Java Reflection.
Supposing that you want to create the object from an Enum value, you could so write :
public enum MyBaseClassFactory {
ENUM_A (A::new),
ENUM_B (B::new),
ENUM_C (C::new),
ENUM_D (D::new);
private Supplier<BaseClass> supplier;
MyBaseClassFactory (Supplier<BaseClass> supplier){
this.supplier = supplier;
}
public BaseClass createObject(){
return supplier.get();
}
}
You could so use it :
BaseClass base = MyBaseClassFactory.ENUM_A.createObject();
Without Supplier, you will have to use Reflection (that may fail at runtime) or write a verbose and unmaintainable code.
For example with Reflection :
public enum MyEnumFactoryClass {
ENUM_A(A.class), ENUM_B(B.class), ENUM_C(C.class), ENUM_D(D.class);
private Class<BaseClass> clazz;
MyEnumFactoryClass(Class<BaseClass> clazz) {
this.clazz = clazz;
}
public BaseClass createObject() {
return clazz.newInstance();
}
}
For example without reflection but with more verbose code :
public enum MyEnumFactoryClass {
ENUM_A {
#Override
public BaseClass createObject() {
return new A();
}
},
ENUM_B {
#Override
public BaseClass createObject() {
return new B();
}
},
ENUM_C {
#Override
public BaseClass createObject() {
return new C();
}
},
ENUM_D {
#Override
public BaseClass createObject() {
return new D();
}
};
public abstract BaseClass createObject();
}
You could of course take advantage in a close way of Supplier by using it with a Map<String, Supplier<BaseClass>>.
The first solution is more flexible, because an extra level of indirection in object creation lets users of your class library change the source of new items independently of ServiceImpl<SomeEntityImplementation> class.
You can make a new Supplier<T> instance without subclassing or recompiling ServiceImpl, because there is an extra level of indirection. ServiceImpl could be implemented as follows:
class ServiceImpl<SomeEntityImplementation> {
private final Supplier<SomeEntityImplementation> supplier;
public Supplier<T> makeNewThing(){
return supplier;
}
public ServiceImpl(Supplier<SomeEntityImplementation> s) {
supplier = s;
}
}
This makes it possible for users of ServiceImpl to provide their own Supplier<T>, which is not possible using the second approach, in which the source of new items is merged into the implementation of service itself.

How to put all String constants declared in a class and its inner classes in a single keySet

Perhaps the hidden question is which structure to use for keys that have a sort of hierarchy (therefore my attempt in using classes and inner classes, so that a test on specific subsets is possible). I'm looking for a structure where I can add a new key to the appropriate place and having automaticallly this key in the appropriate keySet. Here my actual try:
Now I work with keys as static final String and a corresponding keySet.
I often need to test if a certain key is contained in the set of keys (public static final String) declared in some other class.
Therefore I extend all classes with keys from a class Keys1 which has a method keySet() that gives the set of keys. That works fine.
public class Keys1
{
private TreeSet<String> m_keySet = new TreeSet<String>();
public Keys1()
{
initKeySet();
}
private void initKeySet()
{
Field[] felder = this.getClass().getFields();
for (Field f : felder)
{
if (Modifier.isFinal(f.getModifiers()))
{
try
{
if (f.get(f) instanceof String)
{
m_keySet.add(f.get(f).toString());
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}
public TreeSet<String> keySet()
{
return m_keySet;
}
}
Now I try in vain to code a similar functionality in a class Keys2 where the keySet should also contain keys that are declared in inner classes of type Keys2.
public class Keys2 extends Keys1
{
#Override
protected void initKeySet()
{
super.initKeySet();
Class<?>[] innerClasses = this.getClass().getDeclaredClasses();
for (Class<?> innerClass : innerClasses )
{
if (innerClass.getClass().isInstance(Keys1.class))
{
Keys1 newKeys;
try
{
newKeys = (Keys1) innerClass.newInstance(); // Doesn't work
keySet().addAll(newKeys.keySet());
}
catch (InstantiationException e)
{
e.printStackTrace();
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
}
}
}
}
If I'm not mistaken at first you need to get declared constructor of inner class. Than invoke it with an instance of outer class as an argument.
Since you said, you are looking for public static final String fields only, you are doing unnecessary work. You are not filtering the fields to access static fields only, further, you are querying the field and checking the result’s type instead of checking the field’s type in the first place.
Also, you don’t need an object instance to retrieve a static field. If you write the code in a way that it operates on a Class, it can be used to process inner classes just as discovered, without instantiating them.
Since this procedure doesn’t need an object instance, there is also no reason to repeat that operation for every instance nor to store the result in an instance field. You only need to remember the result on a per-class basis and, thankfully, there is a class named ClassValue which provides this for free.
Putting it together, you can implement it as
public class Keys1 {
static final ClassValue<TreeSet<String>> KEYS = new ClassValue<TreeSet<String>>() {
#Override protected TreeSet<String> computeValue(Class<?> type) {
final int desired=Modifier.PUBLIC|Modifier.STATIC|Modifier.FINAL;
Field[] fields=type.getDeclaredFields();
TreeSet<String> set = new TreeSet<>();
for(Field f: fields) {
if((f.getModifiers()&desired)==desired && f.getType()==String.class) try {
set.add((String)f.get(null));
} catch(IllegalAccessException ex) {
throw new AssertionError(ex);
}
}
for(Class<?> inner: type.getDeclaredClasses()) {
set.addAll(get(inner));
}
type = type.getSuperclass();
if(type != null && type != Object.class) set.addAll(get(type));
return set;
}
};
public TreeSet<String> keySet() {
return KEYS.get(getClass());
}
}
The ClassValue takes care of the caching. When you call get, it checks whether there is already a computed value for the specified class, otherwise, it calls computeValue. The computeValue method in this solution utilizes this itself for processing the super class fields, so if you call it for different subclasses, they will share the result for the common base class instead of repeating the work.
The subclass doesn’t need to do anything here, the inherited keySet() method is sufficient, as it uses getClass(), which returns the actual class.
As shown in this ideone demo.
When you are running in a Java version before Java 7, you may use the following ersatz, which you should replace with the real thing as soon as you migrate to a newer Java version.
/**
* TODO: replace with {#code java.lang.ClassValue<T>} when migrating to >=7.
*/
abstract class ClassValue<T> {
private final ConcurrentHashMap<Class<?>,T> cache=new ConcurrentHashMap<Class<?>,T>();
protected abstract T computeValue(Class<?> type);
public final T get(Class<?> key) {
T previous = cache.get(key);
if(previous != null) return previous;
T computed = computeValue(key);
previous = cache.putIfAbsent(key, computed);
return previous!=null? previous: computed;
}
}
The only change needed by the solution itself, is replacing the diamond operator use
new TreeSet<>() with the explicitly typed new TreeSet<String>(). Then, it should work in Java 6.
Make your inner class static or as already briarheart mentioned create nested instance through the instance of outer class (see Instantiating inner class).
Consider using enums instead of String constants.
You can use something like:
public enum A {
A1,
A2;
public static enum B {
B1,
B2
}
public static enum C {
C1,
C2
}
static Set<Enum> allValues() {
Set<Enum> allValues = new HashSet<>();
allValues.addAll(Arrays.asList(A.values()));
allValues.addAll(Arrays.asList(A.B.values()));
allValues.addAll(Arrays.asList(A.C.values()));
return allValues;
}
}
This solution may be improved depending on your needs.
For example you can implement interface with the method
boolean contains(Enum e);
for each enum to check inclusion of arbitrary value in any enum
and its nested enums.

How to create a static 'Object Holder' class using generics in Java

I am trying to create an object holder util class to be short.
Forexample;
public ResponseAbc bringMeStuff(RequestAbc request){
ResponseAbc response = new ResponseAbc();
/* Setting request here.. */
response = bringMeLotsOfStuff(request);
/* Here I am calling the Util class */
Util.putToObjectHolder("myAbcResponse", response);
return response;
}
public void testMe(){
/* Testing objectHolder */
ResponseAbc newResponse = (ResponseAbc) Util.getFromObjectHolder("response");
}
Here is the Util class
public class Util<T> {
private static Util<?> instance = null;
private Map<String, T> objHolder;
private Util() {
}
/* I strongly think Util class should be singleton if I want to hold the map globally */
public static Util<?> getInstance() {
if (instance == null) {
instance = new Util();
}
return instance;
}
public static <T> void putToObjectHolder(String objectName, T objectType) {
// Map<String, T> holder = (Map<String, T>) getInstance().getObjHolder();
// holder.put(objectName, objectType);
getInstance().getObjHolder().put(objectName, objectType); //-> Argument error
}
public static <T> Object getFromObjectHolder(final String objectName) {
Map<String, T> holder = (Map<String, T>) getInstance().getObjHolder();
T obj = null;
for (Entry<String, T> entry : holder.entrySet()) {
if (entry.getKey().equals(objectName)) {
obj = entry.getValue();
} else {
obj = null;
}
}
return obj;
}
public Map<String, T> getObjHolder() {
if (objHolder == null) {
objHolder = new HashMap<String, T>();
}
return objHolder;
}
public void setObjHolder(Map<String, T> objHolder) {
this.objHolder = objHolder;
}
}
If I uncomment putToObjectHolder method, it works but I am not pretty sure it supposed to work that way. I mean creating an other map and assigning to it should do the trick.
What I intent to do is holding a static Map holder with single instance so I can put whatever object I want with a name and get that object whenever I want if it exist in that 'global holder'.
PS: It is pretty messy with type safety warnings for sure, I would love to improve that aswell though I am not sure how to.
Thanks in advance.
Putting aside the singleton part, are you trying to use generics to get objects (of varying types) into and out of the same Map whilst retaining type safety? That is, if you put into the map (for a given key) say a String then getting this value out will only compile if it is assigned to (or used as) a string. (And, also, there are no casts in the code.)
This can be done but it is a bit involved as you need to define keys that have the type of the corresponding value.
See: Java map with values limited by key's type parameter
Joshua Block also had a good article on this somewhere but I don't seem to be able to find it.
This seems to be what you are trying to achieve with your put method. You won't be able to do it with strings as keys though - you'll need a genericized, typed key.
You are not using generic the way they are meant to be used. Take a look at the ArrayList class to learn the true potential of generics.
Also singleton of this class serves no purpose as you only need a "singleton" of a HashMap.
Maybe I do not see what you are trying to accomplish but this is essentially what you are trying to do. Why don't you just use a HashMap and be done with it?
import java.util.HashMap;
public class Util {
private static HashMap<String, Object> values = new HashMap<String, Object>;
private Util() {
}
public static void put(String key, Object value) {
values.put(key, value);
}
public static Object get(String key) {
return values.get(key);
}
public static void main(String[] args) {
String s = "This is a test.";
Util.put("test", s);
System.out.println(Util.get("test"));
System.out.println(Util.get("another test"));
}
}

Categories