java generics - "extends" keyword -> not supporting add elements - java

I am stuck with a strange problem due to java generics "extend" keyword. I have developed a generic method to get the elements from a method as generic as possible.
When I use <? extends X>, I am not able to add any elements to it.
In my case I am using the generic template to restrict the arguments provided by the user and providing the return type ac.
class Root{
}
class Sub_1 extends Root{
}
class Sub_2 extends Root{
}
public static <T extends Root> List<T> getSubElements(Class<T> targetClass){
List<T> ls=new ArrayList<>();
if(targetClass.getSimpleName().equals("Sub_1")){
Sub_1 sub_1 = new Sub_1();
ls.add(sub_1);
}else if(targetClass.getSimpleName().equals("Sub_2")){
Sub_2 sub_2=new Sub_2();
ls.add(sub_2);
}
return ls;
}
In the above case, I am getting compilation error when I add elements to the list.
ls.add(sub_1);
ls.add(sub_2);
It looks quite challenging now to solve this issue.. I will be happy if someone can provide some hints here.
Thanks!!

You can do this in a type-safe way, without using reflection, by having the caller pass in a Supplier of the desired type instead of the Class of that type. The getSubElement code then simply calls the supplier to get the right instance:
static <T extends Root> List<T> getSubElements(Supplier<T> s) {
List<T> ls = new ArrayList<>();
ls.add(s.get());
return ls;
}
The caller needs to provide a way to create an instance of its desired subclass. This might be using a constructor reference, or it could be a reference to a static factory method. If the class hierarchy is like so:
public class Root { }
public class Sub1 extends Root {
public Sub1() { ... }
}
public class Sub2 extends Root {
public static Sub2 instance() { ... }
}
Then callers could write code like the following:
List<Sub1> list1 = getSubElements(Sub1::new);
List<Sub2> list2 = getSubElements(Sub2::instance);

If you can accept any class derived from Root, and all have a default constructor...
public static <T extends Root> List<T> getSubElements(Class<T> targetClass) throws ReflectiveOperationException {
List<T> ls = new ArrayList<>();
T t = targetClass.getDeclaredConstructor().newInstance();
ls.add(t);
return ls;
}
... or try/catch exception locally.

To sum things up, here is a verified working implementation, checked using an online java compiler:
import java.util.*;
class Root{
}
class Sub_1 extends Root{
}
class Sub_2 extends Root{
}
public class Bla {
public static <T extends Root> T factoryMethod(Class<T> targetClass) throws Exception{
if (Sub_1.class ==(targetClass)) {
return (T) (new Sub_1());
}
else if (Sub_2.class == (targetClass)) {
return (T) (new Sub_2());
}
else {
throw new Exception("Unsupported class type");
}
}
public static List<Root> getSubElements() throws Exception{
List<Root> ls=new ArrayList<>();
ls.add(factoryMethod(Sub_1.class));
ls.add(factoryMethod(Sub_2.class));
return ls;
}
public static void main(String[] args) {
try {
List<Root> root = getSubElements();
System.out.println(root);
} catch (Exception e) {
e.printStackTrace();
}
}
}

I would rather say the answer depends on boundary conditions. we can write code to get the necessary functionality but they may/may not adhere to various boundaries conditions like performance, security, integrity ,.. etc
e.g:
The following code
**T newInstance = targetClass.newInstance();**
**list.add(newInstance);**
can also achieve necessary functionality but may/may not adhere to performance boundary, coz any call to reflective methods checks for security access.
The solution with Supplier posted above also achieves a similar functionality , but it may not adhere to security boundary as a malicious supplier can supply values which can lead to buffer overflow or DOS attacks.
(if you really want to to try it out you can create a static supplier and initialize with self.. you will get an stack overflow. java generics book also provide a similar security related example which you can refer). The problem i see lies in the java open sub-typing in the current scenario .
There are other solutions also to achieve required functionality ( with slight modification to way of subtyping created) which may/may not adhere to these boundary conditions. The problem i see is due to open sub-typing system and makes it verbose and difficult for developers to write code adhering to all boundary conditions.
The solution also depends completely up on your model structure whether you have created a sub-typing coz of your data or or based on behavior , which might not reflect in this short example.
you can refer Java Generics Book by Philiph Wadler for more details on working with generics which i would recommend. it also gives an important aspect of writing code in a secure way. On an interesting note you can refer to project amber (java 11 or later) regarding Data Classes for java which tries to address some of these problems.

Related

Java generics in List return type on a method inherited from multiple interfaces

I'm currently working at a company that has a diverse set of modules. In that company if you want to provide module internals you provide it via a java interface, that hides the actual implementing type and gives an interface for the requesting module. Now I want to have one provider to be able to provide data for multiple modules that expose different fields or methods of the actual internal data.
Therefore I have an internal Object, which has some data and I have an interface for each module that needs access to some but not strictly all fields. Finally I have an external object that implements all those interfaces and holds an instance of the internal object to delegate the method calls:
public class InternalObject {
public int getA() { return 0; }
public int getB() { return 0; }
}
public interface ModuleXObject {
int getA();
}
public interface ModuleYObject {
int getA();
int getB();
}
public class ExternalObject implements ModuleXObject, ModuleYObject {
private InternalObject _internal;
public int getA() { return _internal.getA(); }
public int getB() { return _internal.getB(); }
}
Now that is all fine and dandy, but if I want to provide - lets say - repository methods for finding a list of said objects typed for the correct module, I run into problems with how I can achieve that. I would wish for something like the following:
public interface ModuleXObjectRepository {
List<ModuleXObject> loadAllObjects();
}
public interface ModuleYObjectRepository {
List<ModuleYObject> loadAllObjects();
}
public class ExternalObjectRepository implements ModuleXObjectRepository, ModuleYObjectRepository {
public List<ExternalObject> loadAllObjects() {
// ...
}
}
This doesn't compile saying the return type is incompatible.
So my question is, if it is possible to achieve something like that and if, how?
I should note that I tried some different approaches which I want to include for completeness and to portray their downsides (in my eyes).
Approach 1:
public interface ModuleXObjectRepository {
List<? extends ModuleXObject> loadAllObjects();
}
public interface ModuleYObjectRepository {
List<? extends ModuleYObject> loadAllObjects();
}
public class ExternalObjectRepository implements ModuleXObjectRepository, ModuleYObjectRepository {
public List<ExternalObject> loadAllObjects() {
// ...
}
}
This approach is quite close to the solution I would prefer, but results in code like this:
List<? extends ModuleXObject> objects = repository.loadAllObjects();
Therefore requiring the user to include the "? extends" into each List-Declaration regarding to an invocation of loadAllObjects().
Approach 2:
public interface ModuleXObjectRepository {
List<ModuleXObject> loadAllObjects();
}
public interface ModuleYObjectRepository {
List<ModuleYObject> loadAllObjects();
}
public class ExternalObjectRepository implements ModuleXObjectRepository, ModuleYObjectRepository {
public List loadAllObjects() {
// ...
}
}
This approach just omits the generic in the ExternalObjectRepository and therefore reduces the type safety too much in my opinion. Also I haven't tested if this actually works.
Just to reharse, is there any possible way to define the loadAllObjects-method in a way that enables users to get lists that are typed with the objects for their respective module without
requiring "? extends" in the users code
degrading type safety in the repository implementation
using class/interface level generics
The challenge with allowing it to be typed as List<ModuleXObject> is that other code may hold is as a List<ExternalObject>.
All ExternalObject instances are ModuleXObject instances but the inverse is not true.
Consider the following additional class:
public class MonkeyWrench implements ModuleXObject{
//STUFF
}
MonkeyWrench instances are NOT ExternalObject instances but if one could cast a List<ExternalObject> to a List<ModuleXObject> one could add MonkeyWrench instances to this collection, and this causes a risk of run time class cast exceptions and ruins type safety.
Other code could very easily have:
for(ExternalObject externalObject:externalObjectRepository.loadAllObjects())
If one of those instances is a MonkeyWrench instance, run time class cast, which is what generics are meant to avoid.
The implication of ? extends ModuleXObject is that you can read any object from the collection as a ModuleXObject but you can't add anything to the collection as other code may have additional constraints on the collection that are not obvious/available at compile time.
I'd suggest in your case to use ? extends ModuleXObject as its semantics seem to align with what you want, namely pulling out ModuleXObject instances, e.g.
ModuleXObjectRepository repo = //get repo however
for(ModuleXObject obj : repo.loadAllObjects()){
//do stuff with obj
}

Varying enums in Java being accessed by common method

Essentially what I'm trying to do is create a generic method that can take many different kinds of enums. I'm looking for a way to do it how I'm going to describe, or any other way a person might think of.
I've got a base class, and many other classes extend off that. In each of those classes, I want to have an enum called Includes like this:
public enum Includes {
VENDOR ("Vendor"),
OFFERS_CODES ("OffersCodes"),
REMAINING_REDEMPTIONS ("RemainingRedemptions");
private String urlParam;
Includes(String urlParam) {
this.urlParam = urlParam;
}
public String getUrlParam() {
return urlParam;
}
}
I've got a method that takes in a generic class that extends from BaseClass, and I want to be able to also pass any of the includes on that class to the method, and be able to access the methods on the enum, like this:
ApiHelper.Response<Offer> offer = apiHelper.post(new Offer(), Offer.Includes.VENDOR);
public <T extends BaseClass> Response<T> post(T inputObject, Includes... includes) {
ArrayList<String> urlParams = new ArrayList<String>();
for (Include include : includes){
urlParams.add(include.getUrlParam());
}
return null;
}
Is there a way to be able to pass in all the different kinds of enums, or is there a better way to do this?
---EDIT---
I've added an interface to my enum, but how can I generify my method? I've got this:
public <T extends BaseClass> Response<T> post(Offer inputObject, BaseClass.Includes includes) {
for (Enum include : includes){
if (include instanceof Offer.Includes){
((Offer.Includes) include).getUrlParam();
}
}
return null;
}
But I get an error on apiHelper.post(new Offer(), Offer.Includes.VENDOR); saying the second param must be BaseClass.Includes.
Enums can implement interfaces, so you can create an interface with these methods that you'd like to be able to call:
interface SomeBaseClass {
String getUrlParam();
void setUrlParam(String urlParam);
}
and then your enum can implement this interface:
public enum Includes implements SomeBaseClass {
VENDOR ("Vendor"),
OFFERS_CODES ("OffersCodes"),
REMAINING_REDEMPTIONS ("RemainingRedemptions");
private String urlParam;
Includes(String urlParam) {
this.urlParam = urlParam;
}
#Override
public String getUrlParam() {
return urlParam;
}
#Override
public void setUrlParam(String urlParam) {
this.urlParam = urlParam;
}
}
If you want to get really fancy, it's possible to restrict subtypes of the interface to enums, but the generic type declaration will be pretty ugly (thus hard to understand and maintain) and probably won't provide any "real" benefits.
Unrelated note regarding this design: it's a pretty strong code smell that the enum instances are mutable. Reconsider why you need that setUrlParam() method in the first place.

.Net equivalent for Java typed Class<>?

I'm a .NET guy, so let me first assert my understanding of a few Java concepts - correct me if I'm wrong.
Java Generics support the concept of bounded wildcards:
class GenericClass< ? extends IInterface> { ... }
...which is similar to the .NET where restriction:
class GenericClass<T> where T: IInterface { ... }
Java's Class class describes a type, and is roughly equivalent to .NET Type class
So far, so good. But I can't find a close enough equivalence to the Java genericly typed Class<T> where T is a bounded wildcard. This basically imposes a restriction on the types that the Class represents.
Let me give an example in Java.
String custSortclassName = GetClassName(); //only known at runtime,
// e.g. it can come from a config file
Class<? extends IExternalSort> customClass
= Class.forName("MyExternalSort")
.asSubclass(IExternalSort.class); //this checks for correctness
IExternalSort impl = customClass.newInstance(); //look ma', no casting!
The closest I could get in .NET is something like this:
String custSortclassName = GetClassName(); //only known at runtime,
// e.g. it can come from a config file
Assembly assy = GetAssembly(); //unimportant
Type customClass = assy.GetType(custSortclassName);
if(!customClass.IsSubclassOf(typeof(IExternalSort))){
throw new InvalidOperationException(...);
}
IExternalSort impl = (IExternalSort)Activator.CreateInstance(customClass);
The Java version looks cleaner to me.
Is there a way to improve the .NET counterpart ?
Using extension methods & a custom wrapper class for System.Type, you can get pretty close to the Java syntax.
NOTE: Type.IsSubclassOf cannot be used to test if a type implements an interface - see the linked documentation on MSDN. One can use Type.IsAssignableFrom instead - see the code below.
using System;
class Type<T>
{
readonly Type type;
public Type(Type type)
{
// Check for the subtyping relation
if (!typeof(T).IsAssignableFrom(type))
throw new ArgumentException("The passed type must be a subtype of " + typeof(T).Name, "type");
this.type = type;
}
public Type UnderlyingType
{
get { return this.type; }
}
}
static class TypeExtensions
{
public static Type<T> AsSubclass<T>(this System.Type type)
{
return new Type<T>(type);
}
}
// This class can be expanded if needed
static class TypeWrapperExtensions
{
public static T CreateInstance<T>(this Type<T> type)
{
return (T)Activator.CreateInstance(type.UnderlyingType);
}
}
Further improvements using interface variance
(Should only be used in production code after the performance has been evaluated. Could be improved by using a (concurrent!) cache dictionary ConcurrentDictionary<System.Type, IType<object>)
Using Covariant type parameters, a feature introduced with C# 4.0, and an additional type interface IType<out T>, which Type<T> implements, one could make things like the following possible:
// IExternalSortExtended is a fictional interface derived from IExternalSort
IType<IExternalSortExtended> extendedSort = ...
IType<IExternalSort> externalSort = extendedSort; // No casting here, too.
One could even do:
using System;
interface IType<out T>
{
Type UnderlyingType { get; }
}
static class TypeExtensions
{
private class Type<T> : IType<T>
{
public Type UnderlyingType
{
get { return typeof(T); }
}
}
public static IType<T> AsSubclass<T>(this System.Type type)
{
return (IType<T>)Activator.CreateInstance(
typeof(Type<>).MakeGenericType(type)
);
}
}
static class TypeWrapperExtensions
{
public static T CreateInstance<T>(this IType<T> type)
{
return (T)Activator.CreateInstance(type.UnderlyingType);
}
}
So that one can (explicitly) cast between unrelated interfaces InterfaceA and InterfaceB like:
var x = typeof(ConcreteAB).AsSubclass<InterfaceA>();
var y = (IType<InterfaceB>)x;
but that kinda defeats the purpose of the exercise.
C# generics is declaration-site variance, the variance of a type parameter is fixed.
Java is use-site variance, so once we have a declaration List<E>, we can use it 3 ways
List<Number> // invariant, read/write
List<+Number> // covariant, read only
List<-NUmber> // contravariant, write only
There are pros and cons to both approaches. The use-site approach is apparently more powerful, though it gained the reputation as being too difficult to programmers. I think it is actually pretty easy to grasp
List<Integer> integers = ...;
List<+Number> numbers = integers; // covariant
Unfortunately, Java invented an absolutely hideous syntax,
List<? extends Number> // i.e. List<+Number>
once your code has several of these it becomes really ugly. You have to learn to get over it.
Now, in the declaration-site camp, how do we achieve 3 variances on the same class? By having more types - a ReadOnlyList<out E>, a WriteOnlyList<in E>, and a List<E> extending both. This is not too bad, and one might say it's a better design. But it may become ugly if there are more type parameters. And if the designer of a class did not anticipate it being used variantly, the users of the class have no way to use it variantly.
You can get a slightly prettier version using the "as" operator:
String custSortclassName = GetClassName();
Assembly assy = GetAssembly();
Type customClass = assy.GetType(custSortclassName);
IExternalSort impl = Activator.CreateInstance(customClass) as IExternalSort;
if(impl==null) throw new InvalidOperationException(...);
But here I'm creating the instance before checking its type, which may be an issue for you.
You can try writing an extension method like the following:
static class TypeExtension
{
public static I NewInstanceOf<I>(this Type t)
where I: class
{
I instance = Activator.CreateInstance(t) as I;
if (instance == null)
throw new InvalidOperationException();
return instance;
}
}
Which can then be used in the following manner:
String custSortclassName = GetClassName(); //only known at runtime,
// e.g. it can come from a config file
Assembly assy = GetAssembly();
Type customClass = assy.GetType(custSortclassName);
IExternalSort impl = customClass.NewInstanceOf<IExternalSort>();

Is there a way to refer to the current type with a type variable?

Suppose I'm trying to write a function to return an instance of the current type. Is there a way to make T refer to the exact subtype (so T should refer to B in class B)?
class A {
<T extends A> foo();
}
class B extends A {
#Override
T foo();
}
To build on StriplingWarrior's answer, I think the following pattern would be necessary (this is a recipe for a hierarchical fluent builder API).
SOLUTION
First, a base abstract class (or interface) that lays out the contract for returning the runtime type of an instance extending the class:
/**
* #param <SELF> The runtime type of the implementor.
*/
abstract class SelfTyped<SELF extends SelfTyped<SELF>> {
/**
* #return This instance.
*/
abstract SELF self();
}
All intermediate extending classes must be abstract and maintain the recursive type parameter SELF:
public abstract class MyBaseClass<SELF extends MyBaseClass<SELF>>
extends SelfTyped<SELF> {
MyBaseClass() { }
public SELF baseMethod() {
//logic
return self();
}
}
Further derived classes can follow in the same manner. But, none of these classes can be used directly as types of variables without resorting to rawtypes or wildcards (which defeats the purpose of the pattern). For example (if MyClass wasn't abstract):
//wrong: raw type warning
MyBaseClass mbc = new MyBaseClass().baseMethod();
//wrong: type argument is not within the bounds of SELF
MyBaseClass<MyBaseClass> mbc2 = new MyBaseClass<MyBaseClass>().baseMethod();
//wrong: no way to correctly declare the type, as its parameter is recursive!
MyBaseClass<MyBaseClass<MyBaseClass>> mbc3 =
new MyBaseClass<MyBaseClass<MyBaseClass>>().baseMethod();
This is the reason I refer to these classes as "intermediate", and it's why they should all be marked abstract. In order to close the loop and make use of the pattern, "leaf" classes are necessary, which resolve the inherited type parameter SELF with its own type and implement self(). They should also be marked final to avoid breaking the contract:
public final class MyLeafClass extends MyBaseClass<MyLeafClass> {
#Override
MyLeafClass self() {
return this;
}
public MyLeafClass leafMethod() {
//logic
return self(); //could also just return this
}
}
Such classes make the pattern usable:
MyLeafClass mlc = new MyLeafClass().baseMethod().leafMethod();
AnotherLeafClass alc = new AnotherLeafClass().baseMethod().anotherLeafMethod();
The value here being that method calls can be chained up and down the class hierarchy while keeping the same specific return type.
DISCLAIMER
The above is an implementation of the curiously recurring template pattern in Java. This pattern is not inherently safe and should be reserved for the inner workings of one's internal API only. The reason is that there is no guarantee the type parameter SELF in the above examples will actually be resolved to the correct runtime type. For example:
public final class EvilLeafClass extends MyBaseClass<AnotherLeafClass> {
#Override
AnotherLeafClass self() {
return getSomeOtherInstanceFromWhoKnowsWhere();
}
}
This example exposes two holes in the pattern:
EvilLeafClass can "lie" and substitute any other type extending MyBaseClass for SELF.
Independent of that, there's no guarantee self() will actually return this, which may or may not be an issue, depending on the use of state in the base logic.
For these reasons, this pattern has great potential to be misused or abused. To prevent that, allow none of the classes involved to be publicly extended - notice my use of the package-private constructor in MyBaseClass, which replaces the implicit public constructor:
MyBaseClass() { }
If possible, keep self() package-private too, so it doesn't add noise and confusion to the public API. Unfortunately this is only possible if SelfTyped is an abstract class, since interface methods are implicitly public.
As zhong.j.yu points out in the comments, the bound on SELF might simply be removed, since it ultimately fails to ensure the "self type":
abstract class SelfTyped<SELF> {
abstract SELF self();
}
Yu advises to rely only on the contract, and avoid any confusion or false sense of security that comes from the unintuitive recursive bound. Personally, I prefer to leave the bound since SELF extends SelfTyped<SELF> represents the closest possible expression of the self type in Java. But Yu's opinion definitely lines up with the precedent set by Comparable.
CONCLUSION
This is a worthy pattern that allows for fluent and expressive calls to your builder API. I've used it a handful of times in serious work, most notably to write a custom query builder framework, which allowed call sites like this:
List<Foo> foos = QueryBuilder.make(context, Foo.class)
.where()
.equals(DBPaths.from_Foo().to_FooParent().endAt_FooParentId(), parentId)
.or()
.lessThanOrEqual(DBPaths.from_Foo().endAt_StartDate(), now)
.isNull(DBPaths.from_Foo().endAt_PublishedDate())
.or()
.greaterThan(DBPaths.from_Foo().endAt_EndDate(), now)
.endOr()
.or()
.isNull(DBPaths.from_Foo().endAt_EndDate())
.endOr()
.endOr()
.or()
.lessThanOrEqual(DBPaths.from_Foo().endAt_EndDate(), now)
.isNull(DBPaths.from_Foo().endAt_ExpiredDate())
.endOr()
.endWhere()
.havingEvery()
.equals(DBPaths.from_Foo().to_FooChild().endAt_FooChildId(), childId)
.endHaving()
.orderBy(DBPaths.from_Foo().endAt_ExpiredDate(), true)
.limit(50)
.offset(5)
.getResults();
The key point being that QueryBuilder wasn't just a flat implementation, but the "leaf" extending from a complex hierarchy of builder classes. The same pattern was used for the helpers like Where, Having, Or, etc. all of which needed to share significant code.
However, you shouldn't lose sight of the fact that all this only amounts to syntactic sugar in the end. Some experienced programmers take a hard stance against the CRT pattern, or at least are skeptical of the its benefits weighed against the added complexity. Their concerns are legitimate.
Bottom-line, take a hard look at whether it's really necessary before implementing it - and if you do, don't make it publicly extendable.
You should be able to do this using the recursive generic definition style that Java uses for enums:
class A<T extends A<T>> {
T foo();
}
class B extends A<B> {
#Override
B foo();
}
I may not fully understood the question, but isn't it enough to just do this (notice casting to T):
private static class BodyBuilder<T extends BodyBuilder> {
private final int height;
private final String skinColor;
//default fields
private float bodyFat = 15;
private int weight = 60;
public BodyBuilder(int height, String color) {
this.height = height;
this.skinColor = color;
}
public T setBodyFat(float bodyFat) {
this.bodyFat = bodyFat;
return (T) this;
}
public T setWeight(int weight) {
this.weight = weight;
return (T) this;
}
public Body build() {
Body body = new Body();
body.height = height;
body.skinColor = skinColor;
body.bodyFat = bodyFat;
body.weight = weight;
return body;
}
}
then subclasses won't have to use overriding or covariance of types to make mother class methods return reference to them...
public class PersonBodyBuilder extends BodyBuilder<PersonBodyBuilder> {
public PersonBodyBuilder(int height, String color) {
super(height, color);
}
}
Just write:
class A {
A foo() { ... }
}
class B extends A {
#Override
B foo() { ... }
}
assuming you're using Java 1.5+ (covariant return types).
If you want something akin to Scala's
trait T {
def foo() : this.type
}
then no, this is not possible in Java. You should also note that there is not much you can return from a similarly typed function in Scala, apart from this.
I found a way do this, it's sort of silly but it works:
In the top level class (A):
protected final <T> T a(T type) {
return type
}
Assuming C extends B and B extends A.
Invoking:
C c = new C();
//Any order is fine and you have compile time safety and IDE assistance.
c.setA("a").a(c).setB("b").a(c).setC("c");

Generic Map of Generic key/values with related types

I'm trying to create a generic type that keeps a map of the versions of itself that have been created for later use. Effectively, it's an singleton pattern where there's one instance per type. The code I have so far is:
public class FieldBinder<T> {
static final Map<Class<? extends Object>,FieldBinder<? extends Object>> instanceMap =
new HashMap<Class<? extends Object>,FieldBinder<? extends Object>>();
private FieldBinder() {}
synchronized public static <V extends Object> FieldBinder<V> getInstance(Class<V> klass) {
if(!instanceMap.containsKey(klass)) {
instanceMap.put(klass, new FieldBinder<V>());
}
return (FieldBinder<V>)instanceMap.get(klass);
}
}
However, I'm still unsure that I'm "doing it right". It feels like I should be able to specify that the collection is (Class -> FieldBinder). The fact that the IDE is warning about the return statement only reinforces this thought.
Is there a better way to handle this?
Note: This question seems very closely related, but just far enough away that I can't figure out how to apply the information in it to my own problem.
Your implementation is correct. There's no "better" way of doing it (if there is such a thing is "better" in code, which is another issue..)
Minor fixes:
<V extends Object> is equivalent to V which is less verbose
Class<? extends Object> is equivalent to Class<?> which is less verbose
You can use the #SuppressWarnings("unchecked") annotation to tell your compiler that the cast is safe
I don't think it can be done without having an unchecked cast somewhere. You would need something similar to Haskell's existential types, which Java does not have.
You could make the client perform the unchecked cast instead...
synchronized public static <V> FieldBinder<V>
getInstance(Class<V> klass, Class<FieldBinder<V>> binderKlass) {
if(!instanceMap.containsKey(klass)) {
instanceMap.put(klass, new FieldBinder<V>());
}
return binderKlass.cast(instanceMap.get(klass));
}
Now if the client passes a Class<FieldBinder<V>> to the getInstance() method you can avoid the unchecked cast within getInstance().
Unfortunately creating a Class<FieldBinder<V>> itself requires an unchecked cast.
Class<FieldBinder<Integer>> binderKlass =
(Class<FieldBinder<Integer>>) (Class<?>) FieldBinder.class;
BinderAssociator.getInstance(Integer.class, binderKlass);
RHSeeger, I got your original question. I found no solution for the problem. What you can try to play with is a MyMap class, which makes the binding as you request. However with this map two problems arise:
As it is declared as MyMap<?>, one cannot add something with a given type to it. That's dummy and I refer you to Java Generics FAQs (see case study 3) for more details.
As map has connection between key and value, one cannot add two independent objects of any type (two <?> refer to different types) because these two types may be not connected.
While playing I have seen some errors, which I could not explain myself. I think, everything goes into the fact (as I mentioned before) that we try to deal with 2-nd level parametrization.
class FieldBinder<T> {
static class MyMap<M> extends HashMap<Class<M>, FieldBinder<M>> {
}
static final MyMap<?> instanceMap1 = new MyMap<Object>();
static final Map<Class<?>, FieldBinder<?>> instanceMap2 = new HashMap<Class<?>, FieldBinder<?>>();
public static <V> void test() {
Class<V> c1 = null;
FieldBinder<V> f1 = null;
Class<?> c2 = null;
FieldBinder<?> f2 = null;
instanceMap1.put(c1, f1); // error (see 1)
instanceMap1.put(c2, f2); // error (see 2)
instanceMap2.put(c1, f1); // ok
instanceMap2.put(c2, f2); // ok
instanceMap2.put(c1, f2); // wish to be an error, but ok
instanceMap2.put(c2, f1); // wish to be an error, but ok
}
}
The example you refer tells, how to recover the type (class) of object, while you need to recover the type (class) of parametrization. That is not possible.

Categories