How to create a static 'Object Holder' class using generics in Java - 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"));
}
}

Related

Multiple generic type for a class java

is there a way to use a class, with generic types, without setting the maximum number?
I have this class
public class Repository<V> {
private Map<String, HashSet<V>> repo = new HashMap<>();
private static Repository instance = null;
private Repository() {}
public static synchronized Repository getInstance() {
if(instance == null) {
instance = new Repository();
}
return instance;
}
public void addRepository(String key) throws ClassNotFoundException, IOException {
repo.put(key, new HashSet<>());
}
.....
}
this is a "general repository", the HashMap contains an identifier as a key while as a value have HashSet<V> with the data.
I would like each HashSet in the HashMap to contain different class types. More precisely, I would like the generic type V to be different for each HashSet within the HashMap
how can i fix the code to be able to achieve this result?
You can't add a class parameter such as Repository<V> and expect V to be different for each type of entry in the map.
However, you may do something like this:
Remove the generic type from Repository:
public class Repository {
}
Generify the repository map so that it takes a Class<?> as key (instead of a String) and a Set<?> as value):
private final Map<Class<?>, Set<?>> repo = new HashMap<>();
Then, create one method to add a new repository and a method to get an existing repository as such:
public <T> void addRepository(Class<T> key) {
Set<?> existing = repo.putIfAbsent(key, new HashSet<>());
if (existing != null) {
throw new IllegalArgumentException("Key " + key + " is already associated to a repository");
}
}
public <T> Set<T> getRepository(Class<T> key) {
Set<?> subRepo = repo.get(key);
if (subRepo == null) {
throw new IllegalArgumentException("No repository found for key " + key);
}
return (Set<T>) subRepo; //unchecked cast
}
Note: the getRepository() will perform an unchecked cast, but it is a "safe" unchecked cast since the only way to add a new entry into your map is passing through <T> void addRepository(Class<T> key) and you won't be able to insert values that are not T inside the returned Set<T>.
Sample usage:
Repository repository = Repository.getInstance();
repository.addRepository(String.class);
repository.addRepository(Integer.class);
Set<String> stringRepo = repository.getRepository(String.class);
stringRepo.add("Hey");
stringRepo.add("Jude");
Set<Integer> intRepo = repository.getRepository(Integer.class);
intRepo.add(1);
intRepo.add(4);
However, I think you should have one repository per type, it would be cleaner because with the above solution, you're basically not leveraging at all on Java generics (except for the method <T> used in the getRepository method, for which you need to perform an unchecked cast anyway).
There's no way to achieve that cleanly. You can create a repository for each type you have, but you can not unite them into one repository with this setup.

Singleton Factory - Implementation using Java 8

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);
}
}

Use Java HashMap multiple Type

I'm using a Hashmap as my in-memory cache. So basically, this is what I have:
private static final Map<String, Object> lookup = new HashMap<String, Object>();
public static Object get(CacheHelper key) {
return lookup.get(key.getId());
}
public static void store(CacheHelper key, Object value) {
lookup.put(key.getId(), value);
}
That's fine. But for every Object I "get" from the Map, I have to cast, which is very ugly.
I want to put ArrayList and many other different things into it.
Does anybody know an other solution to be typesafe ?
(For sure, I can create for every type a getter and setter, but is that the only solution ?
So, is there a better way to create an in-memory cache or does somebody have an idea how to wrap the hashmap to be more safe ?
One solution to this problem is to make your CacheHelper type generic, with CacheHelper<T>. Then create a wrapper for your map:
class MyCache {
private final Map<CacheHelper<?>, Object> backingMap = new HashMap<>();
public <T> void put(CacheHelper<T> key, T value) {
backingMap.put(key, value);
}
#SuppressWarnings("unchecked")
// as long as all entries are put in via put, the cast is safe
public <T> T get(CacheHelper<T> key) {
return (T) backingMap.get(key);
}
}
The Java compiler actually uses this approach internally; see e.g. here. You don't have to pass around explicit Class objects, but you do have to know what type is actually associated with each key, which is as it should be in well-behaved applications.
You could store the type of the elements ass well, pass the type you expect to the get() method and check there. AFAIK there's no built-in way to make storing different types typesafe without some common superclass or interface.
Basically you'd do this:
private static final Map<String, Object> lookup = new HashMap<>();
private static final Map<String, Class<?>> types= new HashMap<>();
public static <T> T get(CacheHelper key, Class<T> expectedType ) {
Class<?> type = types.get(key.getId());
if( type == null || expectedType == null || expectedType.isAssignableFrom( type ) ) {
throw new IllegalArgumentException("wrong type");
}
return (T)lookup.get(key.getId());
}
//if null values should be allowed, you'd need to change the signature to use generics
//and pass the expected type as well, e.g. <T> void store(CacheHelper key, T value, Class<T> type)
public static void store(CacheHelper key, Object value ) {
lookup.put(key.getId(), value);
types.put( key.getId(), value.getClass() );
}
Note that this still wouldn't catch any compile time errors since you're basically disabling generics inside your cache. Without a common superclass/interface or a generic type on cache itself there's no compile time way to catch those errors - at least no easy one.
If you just don't want to do the casts yourself you can hide them inside get() and live with the possible class cast exception. In that case you can let the compiler infer the type of T from the call (by assignment, explicitly set or type of the parameter).
However, passing the expected class easily provides additional information that you can use to create better error messages etc. which you'd not get from a ClassCastException.
You can pass a Class object as a parameter and use the Class.cast method :
public static <T> T get(CacheHelper key, Class<T> clazz){
return clazz.cast(lookup.get(key.getId());
}
You can use generics feature if java version is 7 (or upper)
public static <T> T get(CacheHelper key){
return (T)(lookup.get(key.getId());
}
And you can then call it as follows :
Myclass.<String>get(key);
In the above example I supposed the Myclass be a class containing the get() method
The get needs a Class<T>, as because of type erasure a cast (T) is a senseless no-op.
Either incorporate the Class all the way; IDs per class:
private final Map<Class<?>, Map<String, Object>> lookup = new HashMap<>();
public <T> T get(Class<T> klass, String id) {
Map<String, Object> mapById = lookup.get(klass);
if (mapById == null) {
return null;
}
Object value = mapById.get(id);
return klass.cast(value);
}
public <T> void store(Class<T> klass, String id, T value) {
Map<String, Object> mapById = lookup.get(klass);
if (mapById == null) {
mapById = new HashMap<>();
lookup.put(klass, mapById);
}
mapById.put(id, value);
}
The store not using value.getClass() to allow a get by interface or base class:
store(Number.class, "x", 3.14);
store(Number.class, "x", 3);
store(Number.class, "x", new BigDecimal("3.14"));
Or do only
public static <T> T get(Class<T> klass, String id) {
Object value = lookup.get(id);
return klass.cast(value);
}
(I simplified the original code a bit, for the readers.)

Converting a List<String> to a List<Integer> (or any class that extends Number)

I want to create a very generic utility method to take any Collection and convert it into a Collection of a user selectable class that extends from Number (Long, Double, Float, Integer, etc.)
I came up with this code that uses Google Collections to transform the Collection and to return an Immutable List.
import java.util.List;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
/**
* Takes a {#code List<String>} and transforms it into a list of the
* specified {#code clazz}.
*
* #param <T>
* #param stringValues
* the list of Strings to be used to create the list of the
* specified type
* #param clazz
* must be a subclass of Number. Defines the type of the new List
* #return
*/
public static <T extends Number> List<T> toNumberList(List<String> stringValues, final Class<T> clazz) {
List<T> ids = Lists.transform(stringValues, new Function<String, T>() {
#SuppressWarnings("unchecked")
#Override
public T apply(String from) {
T retVal = null;
if (clazz.equals(Integer.class)) {
retVal = (T) Integer.valueOf(from);
} else if (clazz.equals(Long.class)) {
retVal = (T) Long.valueOf(from);
} else if (clazz.equals(Float.class)) {
retVal = (T) Float.valueOf(from);
} else if (clazz.equals(Double.class)) {
retVal = (T) Double.valueOf(from);
} else {
throw new RuntimeException(String.format("Type %s is not supported (yet)", clazz.getName()));
}
return retVal;
}
});
return ImmutableList.copyOf(ids);
}
It can be used like this:
// Convert List<String> to List<Long>
List<Long> ids = MiscUtils.toNumberList(productIds, Long.class);
Is my code overkill or how would you simplify it and at the same time keep it generic enough?
I think the most important aspect of this code is the Function as opposed to the method itself. I also don't think it makes sense to switch over the subclasses you allow in the Function body, as you already know what type of Number you want to return at the time the Function is created. It's also slightly problematic that your method fails if given, say, BigInteger.class.
Given this, what I would do is create a utility class (let's call it Numbers) and provide methods on it that each return a Function (which can be an enum singleton) for parsing a String as a specific type of Number. That is:
public class Numbers {
public static Function<String, Integer> parseIntegerFunction() { ... }
public static Function<String, Long> parseLongFunction() { ... }
...
}
They could each be implemented something like this:
public static Function<String, Integer> parseIntegerFunction() {
return ParseIntegerFunction.INSTANCE;
}
private enum ParseIntegerFunction implements Function<String, Integer> {
INSTANCE;
public Integer apply(String input) {
return Integer.valueOf(input);
}
#Override public String toString() {
return "ParseIntegerFunction";
}
}
This can then be used however users want:
List<String> strings = ...
List<Integer> integers = Lists.transform(strings, Numbers.parseIntegerFunction());
This approach has quite a few advantages over yours:
Doesn't require any switching in the Function... we know what type of number we're creating and just do that. Faster.
Is more flexible, in that each Function can be used wherever... users aren't forced to use it the way your method does (copying the transformed values into an ImmutableList.
You only create the Functions you actually want to allow. If there's no BigInteger parsing function, users just can't call that, as opposed to having it be completely legal to do that at compile time and then fail at runtime like in your example.
As a side note, I'd recommend making the return type of any method that returns an ImmutableList be ImmutableList rather than List... it provides information that is useful to clients of the method.
Edit:
If you really need something more dynamic (i.e. you want classes that have an instance of some Class<T extends Number> to be able to transform Strings to that Number type) you could also add a lookup method like:
public static <T extends Number> Function<String, T> parseFunctionFor(Class<T> type) {
// lookup the function for the type in an ImmutableMap and return it
}
This has the same problems as your original method, though, if there's a Number subclass that you don't provide a Function for. It also doesn't seem like there would be many situations where this would be useful.
Why don't you implement several transformer functions and pass them to Lists.transform() call?
public class IntegerTransformer extends Function<String, Integer>() {
public Integer apply(String from) {
return Integer.valueOf(from);
}
}
So, you could write:
Lists.transform(stringValues, new IntegerTransformer());
If you want to handle types automatically, you can add a transformer factory or a map:
static Map<Class,Function<String,?>> transformers = new HashMap<String,?>();
static {
transformers.put(Integer.class, new IntegerTransformer());
transformers.put(Integer.class, new LongTransformer());
...
}
public static Function<String,?> get(Class c) {
Function<String,?> transformer = transformers.get(c);
if(transformer==null) {
throw new RuntimeException(String.format("Type %s is not supported (yet)", clazz.getName()));
}
return transformer;
}
Looks good to me.
Since you have the Class token, why not avoid the unchecked cast and thus suppress warnings?
retVal = clazz.cast(Double.valueOf(from));
You could use reflection, and do something like this:
Method m = clazz.getDeclaredMethod("valueOf", String.class);
T str = (T) m.invoke(null, from);
return str;
Untested and possible slow.

Proper way to declare and set a private final member variable from the constructor in Java?

There are different ways to set a member variable from the constructor. I am actually debating how to properly set a final member variable, specifically a map which is loaded with entries by a helper class.
public class Base {
private final Map<String, Command> availableCommands;
public Base() {
availableCommands = Helper.loadCommands();
}
}
In the above example the helper class looks like this:
public class Helper {
public static Map<String, Command> loadCommands() {
Map<String, Command> commands = new HashMap<String, Command>();
commands.put("A", new CommandA());
commands.put("B", new CommandB());
commands.put("C", new CommandC());
return commands;
}
}
My thought is, that is better practice to use a method to set such a variable in the constructor. So Base class would look something like this:
public class Base {
private final Map<String, Command> availableCommands;
public Base() {
this.setCommands();
}
private void setCommands() {
this.availableCommands = Helper.loadCommands();
}
}
But now I cannot maintain the final modifier and get a compiler error (Final variable cannot be set)
Another way to do this would be:
public class Base {
private final Map<String, Command> availableCommands = new HashMap<String, Command>();
public Base() {
this.setCommands();
}
private void setCommands() {
Helper.loadCommands(availableCommands);
}
}
But in this case the method in the Helper class would change to:
public static void loadCommands(Map<String, Command> commands) {
commands.put("A", new CommandA());
commands.put("B", new CommandB());
commands.put("C", new CommandC());
}
So the difference is where do I create a new map with new HashMap<String, Command>();? My main question is if there is a recommended way to do this, given that part of the functionality comes from this Helper's static method, as a way to load the actual map with entries?
Do I create the new map in my Base class or the Helper class? In both cases Helper will do the actual loading and Base's reference to the map holding the concrete commands will be private and final.
Are there perhaps other more elegant ways to do this besides the options I am considering?
It seems entirely reasonable to me for the helper class to create the map, as per your first code snippet. You are setting the variable in the constructor - I can't see the problem.
As yawn says, making the map immutable would be a nice touch here, but other than that I'd just use the code from the first snippet.
(I assume in real life this really needs to be an instance variable, rather than a static one, by the way?)
If you want it inmutable you do not need to use 3rd party APIs, you can use: java.util.Collections.unmodifiableMap(Map m)
The most common way to do this would be:
public class Base {
private final Map availableCommands;
public Base(){
availableCommands=new HashMap(); // or any other kind of map that you wish to load
availableCommands = Helper.loadCommands(availableCommands);
}
}
If you want such maps to be immutable have a look at the Google Collection API. To quote the linked documentation:
static final ImmutableMap<String, Integer> WORD_TO_INT =
new ImmutableMap.Builder<String, Integer>()
.put("one", 1)
.put("two", 2)
.put("three", 3)
.build();
Have you considered using a Builder pattern like the one in Effective Java 2nd ed.?
You could capture all the map construction logic in one place (thus you wouldn't have 2 separate classes to maintain). Base would look like this:
public class Base {
private final Map<String, Command> commands;
private Base(Builder b) {
commands = b.commands;
}
public static class Builder() {
private final Map<String, Command> commands;
public Builder() {
commands = new HashMap<String, Command>();
}
public Builder addCommand(String name, Command c) {
commands.put(name, c);
return this;
}
public Base build() {
return new Base(this);
}
}
}
Clients of Base would now work like this:
Base b = new Base.Builder().addCommand("c1", c1).addCommand("c2", c2).build();
Upshot is that the client class doesn't need to know that they need to build a Map and you could essentially build it all with 1 line. Downside is that Base cannot be extended because the constructor is private now (maybe you want that, maybe you don't).
EDIT: Had a goof in build() where I passed commands instead of this as I originally intended
EDIT2: Mistakenly called add instead of put in Base.Builder.addCommand
Why don't you just do
private final Map<String, Command> availableCommands = Helper.loadCommands();
?
I personally would rename the Helper class to something like CommandHolder:
public class CommandHolder {
private static Map<String, Command> availableCommands;
private static CommandHolder instance;
private CommandHolder{}
public static synchronized Map<String, Command> getCommandMap() {
if (instance == null) {
instance = new CommandHolder();
instance.load();
}
return availableCommands
}
private void load() {
...
}
}
synchronized to make sure the loading takes place only once. No getCommand because
that one must then also be synchronized, and each lookup would be more expensive.
I assume the map is read-only, otherwise you'd need a synchronizedMap anyway in a multi-threaded environment.
You can also use double-brace initialization, although whether or not you think it's cleaner is probably a matter of taste, but at least has the benefit of having all the initialization code in one place:
public class Base {
public final Map< String, Command > availableCommands;
public Base() {
availableCommands = Collections.unmodifiableMap( new HashMap() {
{
put( "A", new CommandA() );
put( "B", new CommandB() );
}
} );
}
}

Categories