Why has my generic method stopped working? - java

In my project I have a factory method that loads an object that implements an interface. You pass in the class you desire and receive an instantiation of it, like so.
public class Factory {
public static <E extends SomeInterface> E load( Class<E> clss ) throws Exception {
return clss.newInstance();
}
}
You could invoke it like this:
MyObject obj = Factory.load( MyObject.class );
This code works just fine in Eclipse 3.4 with Java 6u13, however today I received a new laptop and installed Eclipse 3.5 and java 6u15 and now I am getting type mismatches everywhere.
MyObject obj = Factory.load( MyObject.class );
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Type mismatch: cannot convert from SomeInterface to MyObject
Putting a cast before Factory on that line makes it go away and all runs well, but it makes the line a bit less clean, and I didn't need it before, so what gives?

Did you recently add a type parameter to your factory class? There's a pitfall with generic methods on raw types:
public class FooFactory<UnrelatedArg> {
public <E> E load(Class<E> c) { ... }
}
FooFactory<?> f; f.load(String.class); // returns String
FooFactory f; f.load(String.class); // returns Object

Is that all the code required to get this bug? I've seen something very similar in some code I've been looking at today. There was an additional parameter being passed into the equivalent of your Factory method which had a generic type as well. This was missing it's generic definition and I think was to blame for confusing the compiler.
ie, if your factory method looked something like
public class Factory {
public static <E extends SomeInterface> E load( Class<E> class, Key key ) {
// return an instance of E
}
}
Where there is some Key class defined something like this
public class Key<Datatype> {
....
}
Giving something like this to invoke the method, note no generics on the declaration of key
Key key = new Key()
MyObject obj = Factory.load( MyObject.class, key );
Hope that helps,

I think this is related to the Java compilance level. By default a project has the default level. Which you set in the Eclipse preferences. In your old installation you will have change it.

https://bugs.eclipse.org/bugs/show_bug.cgi?id=277643

Related

How may I create an Generic class Enum<K> which extends EnumMap and call super( K.class )?

G'day, I was aiming to create an abstract (base) class by extend-ing EnumMap. I already have existing prototype code that works great based on an EnumMap sub-class and I want to convert that into a generic base that I can use with different Enum-types (i.e. generic Enum<K>).
The road-block I struck is ...
How to tell the EnumMap constructor the class of the generic Enum<K>?
For comparison the working (non-generic) class look like the following, given the Enum<States>:
public class MyMap extends EnumMap<States, FocusTraversalPolicy>
{
private static States DEFAULT_POLICY;
private static States currentPolicy = DEFAULT_FLOW;
public MyMap (){
this( States.DATA_INPUT );
}
public MyMap ( final ProcessState defaultPolicy ){
super(States.class );
DEFAULT_POLICY = defaultPolicy;
currentPolicy = DEFAULT_FLOW;
}
}
My ability to translate this into a generic version has hit a set of alternative errors which boils down to a difficulty passing the Enum type (K.class) to the EnumMap's parent constructor, viz.
Cannot select from type variable
and (briefly)
No suitable constructor found ...
argument mismatch; Class<CAP#1> cannot be converted to Class<K>)
My declaration so far looks like this:
public abstract class MapBase<K> extends EnumMap<K, FocusTraversalPolicy>{
private K DEFAULT_POLICY;
private K currentPolicy;
private Enum Dummy {
NOTHING
}
private MapBase() { // disable empty constructor
this(Dummy.NOTHING); // Exclude NullPointerException-s
}
public MapBase( final K defaultPolicy ) // Default compulsory
{
super( K.class ); // <-- Cannot select from type variable
// OR
super( defaultPolicy.getClass() ); // <-- No suitable constructor found
DEFAULT_POLICY = defaultPolicy;
currentPolicy = DEFAULT_FLOW;
}
}
This is as far as I got. I attempted a few variations with more or less different ways to tell me the same thing, e.g.
class MapBase<K extends Enum<K>>
extends EnumMap<K, FocusTraversalPolicy>{
:
}
While a generics version for the base class is the Most desirable, it seems that this may not be possible; or that I am not following the right syntax to making the 'kind of' base-class I want.
Even knowing if, "You can't do that." Is helpful and I'll divert my efforts to a different structure. It just seems more OO to inherit versus re-inventing a perfectly good existing prototype wheel. My thanks in advance.
The glaring problem with the code is the apparent inappropriate use of inheritance. You're unlikely to save much memory, and the code becomes a mess.
So the start of the class becomes
public class TraversalPolicies<K extends Enum<K>> {
private final Map<K, FocusTraversalPolicy> policies;
The constructor for EnumMap needs the Class of the enum because it is going to do something funky indexing the ordinal into an array of values.
The straightforward was of doing this is having the Class object passed to your generic class.
public TraversalPolicies(Class<K> clazz) {
this.policies = new EnumMap<>(clazz);
Alternatively, the Class can be taken from an instance of the enum if you have one available.
public TraversalPolicies(K defaultPolicy) {
this.policies = new EnumMap<>(defaultPolicy.getDeclaringClass());

Instantiate generified class after loading from repository

When writing a type handler for a repository (such as a web service or a database), I need to instantiate the type after the value is loaded from the repository.
Let's say I get a String value from the repository and there is a constructor with one String argument that I can use. If the return type has a type parameter, what else can I do besides instantiating the raw type? It seems raw types exist only for compatibility with legacy code so I would prefer not to use them.
Normally ? can be used as type parameter (if you know the type will be correct at runtime), but not in this case because you can't instantiate classes with wildcards as type parameter.
EDIT: some example code:
Let's say I have a PrimaryKey class like this:
public class PrimaryKey<R extends RepositoryObject<R>> {
private String value;
public PrimaryKey(String value) {
this.value = value;
}
}
And a set of classes that extend RepositoryObject, which is defined like this:
public class RepositoryObject<R extends RepositoryObject<R>> {
private PrimaryKey<R> pk;
public RepositoryObject(PrimaryKey<R> pk) {
this.pk = pk;
}
PrimaryKey<R> getPrimaryKey() {
return pk;
}
}
Example of a subclass:
public class User extends RepositoryObject<User> {
public User(PrimaryKey<User> userId) {
super(userId);
}
}
Now the type handling method for class PrimaryKey will look something like this:
public PrimaryKey<?> getValue(String stringValue) {
return new PrimaryKey<>(stringValue);
}
But this results in a compiler error (in the Maven build, not in Eclipse IDE strangely enough) even though I'm using the diamond operator instead of when instantiating. Maybe for some reason type inference doesn't work well because of the recursion in the type parameters.
In Java 7 you can typically use the diamond operator to get around this limitation:
Container<?> c = new Container<>(arg);
Otherwise you can use a helper factory method:
<T> Container<T> makeContainer(String arg) {
return new Container<T>(arg);
}
...
Container<?> c = makeContainer(arg);
EDIT:
Following your update, I can see you're using a recursive type parameter <R extends RepositoryObject<R>>. This compile error is due to limitations of javac when it comes to wildcard capture and recursive type parameters. See this related post for example: Java CRTP and Wildcards: Code compiles in Eclipse but not `javac`
Unfortunately, using a raw type is necessary as a workaround, but it can be hidden as an implementation detail:
public PrimaryKey<?> getValue(String stringValue) {
#SuppressWarnings("rawtypes") //a raw type is necessary to placate javac
final PrimaryKey<?> pk = new PrimaryKey(stringValue);
return pk;
}
class SomeBogusClass extends RepositoryObject<SomeBogusClass> { }
return new PrimaryKey<SomeBogusClass>(stringValue);
seriously, you can put anything there that satisfies the bounds, even some bogus class that has nothing to do with your code.

Instantiating generics type in java

I would like to create an object of Generics Type in java. Please suggest how can I achieve the same.
Note: This may seem a trivial Generics Problem. But I bet.. it isn't. :)
suppose I have the class declaration as:
public class Abc<T> {
public T getInstanceOfT() {
// I want to create an instance of T and return the same.
}
}
public class Abc<T> {
public T getInstanceOfT(Class<T> aClass) {
return aClass.newInstance();
}
}
You'll have to add exception handling.
You have to pass the actual type at runtime, since it is not part of the byte code after compilation, so there is no way to know it without explicitly providing it.
In the code you posted, it's impossible to create an instance of T since you don't know what type that is:
public class Abc<T>
{
public T getInstanceOfT()
{
// There is no way to create an instance of T here
// since we don't know its type
}
}
Of course it is possible if you have a reference to Class<T> and T has a default constructor, just call newInstance() on the Class object.
If you subclass Abc<T> you can even work around the type erasure problem and won't have to pass any Class<T> references around:
import java.lang.reflect.ParameterizedType;
public class Abc<T>
{
T getInstanceOfT()
{
ParameterizedType superClass = (ParameterizedType) getClass().getGenericSuperclass();
Class<T> type = (Class<T>) superClass.getActualTypeArguments()[0];
try
{
return type.newInstance();
}
catch (Exception e)
{
// Oops, no default constructor
throw new RuntimeException(e);
}
}
public static void main(String[] args)
{
String instance = new SubClass().getInstanceOfT();
System.out.println(instance.getClass());
}
}
class SubClass
extends Abc<String>
{
}
What you wrote doesn't make any sense, generics in Java are meant to add the functionality of parametric polymorphism to objects.
What does it mean? It means that you want to keep some type variables of your classes undecided, to be able to use your classes with many different types.
But your type variable T is an attribute that is resolved at run-time, the Java compiler will compile your class proving type safety without trying to know what kind of object is T so it's impossible for it to let your use a type variable in a static method. The type is associated to a run-time instance of the object while public void static main(..) is associated to the class definition and at that scope T doesn't mean anything.
If you want to use a type variable inside a static method you have to declare the method as generic (this because, as explained type variables of a template class are related to its run-time instance), not the class:
class SandBox
{
public static <T> void myMethod()
{
T foobar;
}
}
this works, but of course not with main method since there's no way to call it in a generic way.
EDIT: The problem is that because of type erasure just one generic class is compiled and passed to JVM. Type checker just checks if code is safe, then since it proved it every kind of generic information is discarded.
To instantiate T you need to know the type of T, but it can be many types at the same time, so one solution with requires just the minimum amount of reflection is to use Class<T> to instantiate new objects:
public class SandBox<T>
{
Class<T> reference;
SandBox(Class<T> classRef)
{
reference = classRef;
}
public T getNewInstance()
{
try
{
return reference.newInstance();
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
public static void main(String[] args)
{
SandBox<String> t = new SandBox<String>(String.class);
System.out.println(t.getNewInstance().getClass().getName());
}
}
Of course this implies that the type you want to instantiate:
is not a primitive type
it has a default constructor
To operate with different kind of constructors you have to dig deeper into reflection.
You need to get the type information statically. Try this:
public class Abc<T> {
private Class<T> clazz;
public Abc(Class<T> clazz) {
this.clazz = clazz;
}
public T getInstanceOfT()
throws throws InstantiationException,
IllegalAccessException,
IllegalArgumentException,
InvocationTargetException,
NoSuchMethodException,
SecurityException {
return clazz.getDeclaredConstructor().newInstance();
}
}
Use it as such:
Abc<String> abc = new Abc<String>(String.class);
abc.getInstanceOfT();
Depending on your needs, you may want to use Class<? extends T> instead.
The only way to get it to work is to use Reified Generics. And this is not supported in Java (yet? it was planned for Java 7, but has been postponed). In C# for example it is supported assuming that T has a default constructor. You can even get the runtime type by typeof(T) and get the constructors by Type.GetConstructor(). I don't do C# so the syntax may be invalid, but it roughly look like this:
public class Foo<T> where T:new() {
public void foo() {
T t = new T();
}
}
The best "workaround" for this in Java is to pass a Class<T> as method argument instead as several answers already pointed out.
First of all, you can't access the type parameter T in the static main method, only on non-static class members (in this case).
Second, you can't instantiate T because Java implements generics with Type Erasure. Almost all the generic information is erased at compile time.
Basically, you can't do this:
T member = new T();
Here's a nice tutorial on generics.
You don't seem to understand how Generics work.
You may want to look at http://java.sun.com/j2se/1.5.0/docs/guide/language/generics.html
Basically what you could do is something like
public class Abc<T>
{
T someGenericThing;
public Abc(){}
public T getSomeGenericThing()
{
return someGenericThing;
}
public static void main(String[] args)
{
// create an instance of "Abc of String"
Abc<String> stringAbc = new Abc<String>();
String test = stringAbc.getSomeGenericThing();
}
}
I was implementing the same using the following approach.
public class Abc<T>
{
T myvar;
public T getInstance(Class<T> clazz) throws InstantiationException, IllegalAccessException
{
return clazz.newInstance();
}
}
I was trying to find a better way to achieve the same.
Isn't it possible?
Type Erasure Workaround
Inspired by #martin's answer, I wrote a helper class that allows me to workaround the type erasure problem. Using this class (and a little ugly trick) I'm able to create a new instance out of a template type:
public abstract class C_TestClass<T > {
T createTemplateInstance() {
return C_GenericsHelper.createTemplateInstance( this, 0 );
}
public static void main( String[] args ) {
ArrayList<String > list =
new C_TestClass<ArrayList<String > >(){}.createTemplateInstance();
}
}
The ugly trick here is to make the class abstract so the user of the class is forced to subtype it. Here I'm subclassing it by appending {} after the call to the constructor. This defines a new anonymous class and creates an instance of it.
Once the generic class is subtyped with concrete template types, I'm able to retrieve the template types.
public class C_GenericsHelper {
/**
* #param object instance of a class that is a subclass of a generic class
* #param index index of the generic type that should be instantiated
* #return new instance of T (created by calling the default constructor)
* #throws RuntimeException if T has no accessible default constructor
*/
#SuppressWarnings( "unchecked" )
public static <T> T createTemplateInstance( Object object, int index ) {
ParameterizedType superClass =
(ParameterizedType )object.getClass().getGenericSuperclass();
Type type = superClass.getActualTypeArguments()[ index ];
Class<T > instanceType;
if( type instanceof ParameterizedType ) {
instanceType = (Class<T > )( (ParameterizedType )type ).getRawType();
}
else {
instanceType = (Class<T > )type;
}
try {
return instanceType.newInstance();
}
catch( Exception e ) {
throw new RuntimeException( e );
}
}
}
There are hacky ways around this when you really have to do it.
Here's an example of a transform method that I find very useful; and provides one way to determine the concrete class of a generic.
This method accepts a collection of objects as input, and returns an array where each element is the result of calling a field getter on each object in the input collection. For example, say you have a List<People> and you want a String[] containing everyone's last name.
The type of the field value returned by the getter is specified by the generic E, and I need to instantiate an array of type E[] to store the return value.
The method itself is a bit ugly, but the code you write that uses it can be so much cleaner.
Note that this technique only works when somewhere in the input arguments there is an object whose type matches the return type, and you can deterministically figure it out. If the concrete classes of your input parameters (or their sub-objects) can tell you nothing about the generics, then this technique won't work.
public <E> E[] array (Collection c) {
if (c == null) return null;
if (c.isEmpty()) return (E[]) EMPTY_OBJECT_ARRAY;
final List<E> collect = (List<E>) CollectionUtils.collect(c, this);
final Class<E> elementType = (Class<E>) ReflectionUtil.getterType(c.iterator().next(), field);
return collect.toArray((E[]) Array.newInstance(elementType, collect.size()));
}
Full code is here: https://github.com/cobbzilla/cobbzilla-utils/blob/master/src/main/java/org/cobbzilla/util/collection/FieldTransformer.java#L28
It looks like you are trying to create the class that serves as the entry point to your application as a generic, and that won't work... The JVM won't know what type it is supposed to be using when it's instantiated as you start the application.
However, if this were the more general case, then something like would be what you're looking for:
public MyGeneric<MyChoiceOfType> getMeAGenericObject(){
return new MyGeneric<MyChoiceOfType>();
}
or perhaps:
MyGeneric<String> objMyObject = new MyGeneric<String>();
Abc<String> abcInstance = new Abc<String> ();
..for example

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.

Higher-kinded generics in Java

Suppose I have the following class:
public class FixExpr {
Expr<FixExpr> in;
}
Now I want to introduce a generic argument, abstracting over the use of Expr:
public class Fix<F> {
F<Fix<F>> in;
}
But Eclipse doesn't like this:
The type F is not generic; it cannot be parametrized with arguments <Fix<F>>
Is this possible at all or have I overlooked something that causes this specific instance to break?
Some background information: in Haskell this is a common way to write generic functions; I'm trying to port this to Java. The type argument F in the example above has kind * -> * instead of the usual kind *. In Haskell it looks like this:
newtype Fix f = In { out :: f (Fix f) }
I think what you're trying to do is simply not supported by Java generics. The simpler case of
public class Foo<T> {
public T<String> bar() { return null; }
}
also does not compile using javac.
Since Java does not know at compile-time what T is, it can't guarantee that T<String> is at all meaningful. For example if you created a Foo<BufferedImage>, bar would have the signature
public BufferedImage<String> bar()
which is nonsensical. Since there is no mechanism to force you to only instantiate Foos with generic Ts, it refuses to compile.
Maybe you can try Scala, which is a functional language running on JVM, that supports higher-kinded generics.
[ EDIT by Rahul G ]
Here's how your particular example roughly translates to Scala:
trait Expr[+A]
trait FixExpr {
val in: Expr[FixExpr]
}
trait Fix[F[_]] {
val in: F[Fix[F]]
}
In order to pass a type parameter, the type definition has to declare that it accepts one (it has to be generic). Apparently, your F is not a generic type.
UPDATE: The line
F<Fix<F>> in;
declares a variable of type F which accepts a type parameter, the value of which is Fix, which itself accepts a type parameter, the value of which is F. F isn't even defined in your example. I think you may want
Fix<F> in;
That will give you a variable of type Fix (the type you did define in your example) to which you are passing a type parameter with value F. Since Fix is defined to accept a type parameter, this works.
UPDATE 2: Reread your title, and now I think you might be trying to do something similar to the approach presented in "Towards Equal Rights for Higher-Kinded Types" (PDF alert). If so, Java doesn't support that, but you might try Scala.
Still, there are ways to encode higer-kinded generics in Java. Please, have a look at higher-kinded-java project.
Using this as a library, you can modify your code like this:
public class Fix<F extends Type.Constructor> {
Type.App<F, Fix<F>> in;
}
You should probably add an #GenerateTypeConstructor annotation to your Expr class
#GenerateTypeConstructor
public class Expr<S> {
// ...
}
This annotation generates ExprTypeConstructor class.
Now you can process your Fix of Expr like this:
class Main {
void run() {
runWithTyConstr(ExprTypeConstructor.get);
}
<E extends Type.Constructor> void runWithTyConstr(ExprTypeConstructor.Is<E> tyConstrKnowledge) {
Expr<Fix<E>> one = Expr.lit(1);
Expr<Fix<E>> two = Expr.lit(2);
// convertToTypeApp method is generated by annotation processor
Type.App<E, Fix<E>> oneAsTyApp = tyConstrKnowledge.convertToTypeApp(one);
Type.App<E, Fix<E>> twoAsTyApp = tyConstrKnowledge.convertToTypeApp(two);
Fix<E> oneFix = new Fix<>(oneAsTyApp);
Fix<E> twoFix = new Fix<>(twoAsTyApp);
Expr<Fix<E>> addition = Expr.add(oneFix, twoFix);
process(addition, tyConstrKnowledge);
}
<E extends Type.Constructor> void process(
Fix<E> fixedPoint,
ExprTypeConstructor.Is<E> tyConstrKnowledge) {
Type.App<E, Fix<E>> inTyApp = fixedPoint.getIn();
// convertToExpr method is generated by annotation processor
Expr<Fix<E>> in = tyConstrKnowledge.convertToExpr(inTyApp);
for (Fix<E> subExpr: in.getSubExpressions()) {
process(subExpr, tyConstrKnowledge);
}
}
}
It looks as if you may want something like:
public class Fix<F extends Fix<F>> {
private F in;
}
(See the Enum class, and questions about its generics.)
There is a roundabout way to encode higher kinded types in Java as pointed out by Victor. The gist of it is to introduce a type H<F, T> to encode F<T>. This can then be used to encode fixed point of functors (i.e. Haskell's Fix type):
public interface Functor<F, T> {
<R> H<F, R> map(Function<T, R> f);
}
public static record Fix<F extends H<F, T> & Functor<F, T>, T>(F f) {
public Functor<F, Fix<F, T>> unfix() {
return (Functor<F, Fix<F, T>>) f;
}
}
From here you can go on and implement catamorphisms over initial algebras:
public interface Algebra<F, T> extends Function<H<F, T>, T> {}
public static <F extends H<F, T> & Functor<F, T>, T> Function<Fix<F, T>, T> cata(Algebra<F, T> alg) {
return fix -> alg.apply(fix.unfix().map(cata(alg)));
}
See my GitHub repo for working code including some example algebras. (Note, IDE's like IntelliJ struggle with the code although it compiles and runs just fine with Java 15).

Categories