Cannot instantiate the type LinqMap - java

I've been a Java developer since 2011 and usually have no problem in getting the hang of the errors since I've seen them tons of times already. Even this one I've seen a lot and I usually know how to solve it.
However, today I ran into an odd problem which judging by what it means, I can't get my head around what the problem really is.
So I'm a modder, specificly for Minecraft and in this case Bukkit. However that is completly irrelevant for the problem since this is rather something to do with the language itself and not any library made with it.
So the error.
Cannot instantiate the type LinqMap<Integer, ? extends ItemStack>
Usually when I see this, I think it's because the type I'm trying to use, either is an interface, is abstract, or the specified constructors are either private or not defined however some of these do have their own errors, but that's what I usually check.
I also noticed there's a lot of copies of this error over Stack Overflow, however most of them seem to point in the direction of instancing List which is an interface, or some custom class which is abstract. This would be the same, if it wasn't for the fact that I already checked this, and it's not the problem it turns out.
So the piece of code I originally tried to use, looks as follows
HashMap<Integer,? extends ItemStack> stackmap = new LinqMap<Integer,? extends ItemStack>(player.getInventory().all(prototype.getType()));
Now, this was a bit hard to spot, so I tried narrowing it down. I took note of the constructor of LinqMap which takes either no parameters, or a Map<K,V>.
Also want to point out that all returns HashMap<Integer, ? extends ItemStack> in case you wonder what it returns. Anyway, So I tried again with the following code
Map<Integer,? extends ItemStack> map = player.getInventory().all(prototype.getType());
HashMap<Integer,? extends ItemStack> stackmap = new LinqMap<Integer,? extends ItemStack>(map);
This still didn't work, so I tried using the empty constructor which ends up like this
HashMap<Integer,? extends ItemStack> stackmap = new LinqMap<Integer,? extends ItemStack>();
This still ended up in the error, which really surprised me, since the object is a class, it has no modifiers except being public, and both the constructors including the parameter-less one is empty.
So what's the problem here? Why can't I create an instance of a LinqMap when the code clearly allows for it?
Also, here's a small snippet of the class for reference, it's custom made by me and is a port of Linq from C# (not released)
import java.util.HashMap;
import java.util.Map;
public class LinqMap<K,V> extends HashMap<K,V> {
/**
*
*/
private static final long serialVersionUID = 1796259800183459223L;
public LinqMap(final Map<K,V> other) {
for (Map.Entry<K, V> item : other.entrySet()) {
this.put(item.getKey(), item.getValue());
}
}
public LinqMap() {
}
/* ... */
}

In Java, you're not allowed to instantiate wildcard types ? directly. If you're compiling with at least Java 7, then I recommend you simply take advantage of diamond inference:
Map<Integer, ? extends ItemStack> map = player.getInventory().all(prototype.getType());
HashMap<Integer, ? extends ItemStack> stackmap = new LinqMap<>(map);

Related

Type Parameter Class with generic java

I am trying to use the generic class in java 15 with the below code
#Singleton
public class GenericRepository<T> implements IGenericRepository<T>{
private final MongoClient mongoClient;
public GenericRepository(MongoClient mongoClient) {
this.mongoClient = mongoClient;
}
public MongoCollection<T> getCollection(String collectionName) {
return mongoClient
.getDatabase("main")
.getCollection(collectionName, T.class);
}
}
I can't use T.class, how can I solve this
Solution I found
#Singleton
public class GenericRepository<T> implements IGenericRepository<T>{
private final MongoClient mongoClient;
private final Class<T> typeParameterClass;
public GenericRepository(MongoClient mongoClient, Class<T> typeParameterClass) {
this.mongoClient = mongoClient;
this.typeParameterClass = typeParameterClass;
}
public MongoCollection<T> getCollection(String collectionName) {
return mongoClient
.getDatabase("main")
.getCollection(collectionName, this.typeParameterClass);
}
}
Since using this solution is quite extra code, is there any better way to do this ?
A singleton class, whose only constructor takes parameters, and is parameterized?
Your code makes no sense. The problem you're running into is significant in other contexts, but not this one. There is no direct solution to this problem (the problem being: Generics are erased), but there are different code styles that avoid it.
The problem is, because the problem doesn't even apply to this situation, it's hard to explain how one would rewrite this code so the problem goes away as a general principle.
Here, you'd just... remove the type param, get rid of that interface (in general if you have IFoo hanging around, something's not right), simple as that.
If you want to generalize this concept, so that you can make a lot of these (Let's say you have one of these classes to retrieve the Foos, and another to retrieve the Bars), you CAN fetch the <X> in specifically public class FooFetcher implements GenericFetcher<X>, though it's a bit tricky (you'd use getGenericSuper from your own java.lang.Class and take it from there. There's a ton of caveats in this situation, so I won't expand any further on this, just know that's how you could do it.
If, in a different situation, you do need to convey generics in a runtime-queryable way, the problem with your style is that a class object and a generics param overlap but aren't the same. int has a class object (int.class), but List<int> is not valid java code. List<String> is valid generics (List<List<String>> x; is valid java), but List<String>.class isn't a thing and never will be, only List.class can be. Same goes for ?, ? extends Map<?, List<? extends Number>> & Serializable, which is valid generics, but rather obviously not at all something you can represent with a java.lang.Class type. Therefore, if you do want generics as a runtime queryable concept, search the web for 'super type tokens' - but note that they require MORE code than what you have here, not less. They're just actually capable of representing exactly what generics can represent.
As a general rule of thumb if you're relying on the generics of java.lang.Class to glue your code together you've done something wrong, and you probably want factories.

Out-of-nowhere ClassCastException in android

This morning I woke up on this strange exception:
java.lang.ClassCastException:
org.apache.harmony.luni.lang.reflect.ImplForVariable cannot be cast to
java.lang.Class
It happens when I try to get a Type argument Class.
Example:
public static Class getTypeParameterClass(Object o, int index) {
return (Class)
((ParameterizedType)o.getClass()
.getGenericSuperclass())
.getActualTypeArguments()[index];
}
As you can see, this method gets one of the type parameter for a given object's class.
It's been working for months now but today, it stopped.
Usage example:
Collection<Object> foo = new ArrayList<Object>();
Class<?> fooClass = Utils.getTypeParameterClass(foo, 0);
And it crashes.
Is there a curse on me for blaming java too many times;) ?
Thanks !
As you can see, this method gets one of the type parameter for a given object's class.
So what you are doing is specifically not allowed because of the generic type erasure. You are trying to investigate the generic parameter of your ArrayList but when the code is running, the specific generic type is no longer visible.
Your superclass hack (and it is a hack) would work if you were dealing with a superclass. It would work if you defined your ArrayList like:
Collection<Object> foo = new ArrayList<Object>() {
private static final long serialVersionUID = -594043150300376049L;
};
In this case foo is a class which extends ArraryList. For some reason with the superclass the generic type parameter is available.
So, first of all, let me address a huge "thank you" to Gray for his patience.
I finally figured what was wrong.
I was focusing on the wrong field.
So, as Gray points out, because of type erasure you can't get a type parameter that is not explicitly given at compile time.
I was so persuaded that the error was on a Collection field that I totally forgot about other fields.
So, because my data come from webservices, and because the JSON mapper can't directly get a list as root, I had to define models containing a Collection of objects, a date (for caching) and few other things related to paging.
So, because writing all these similar classes was a nonsense, I tried to generalize the process, like so:
public abstract class ModelList<T> {
[ paging and caching stuffs ]
#ForeignCollectionField
Collection<T> collection;
[ constructor, getters, setters ]
}
and then only have subclasses like:
#DatabaseTable(tableName = "category_list")
public class CategoryList extends ModelList<Category> {
}
So I could have less verbose classes, and so I could generalize the caching process using ObjectPersister from Robospice.
What I couldn't understand (because of a lack of knowledge), is that the parameter would not be found at run time !
What confused me even more is that the tests I ran to try to reproduce the bug, WERE producing the bug ! but they were wrong too.
So, note to self (and others that may face complete nonsense like I did):
don't lose faith in the language (it's not buggy, it's not buggy, it's not buggy ...)
don't blame the language (not too much)
always attach sources to jars and set breakpoints
At the end the solution was quite simple, just move the collection from the ModelList to the sublasses, and keep the getters and setters as abstract methods in ModelList (for the generic ObjectPersisters).
I think it all got a little too complicated, if someone knows a better solution for this case using ormlite/jackson/robospice I'd be glad to hear it.

Is there any way I can create/get and return a Class<T<?, ?>> object?

I seem to have painted myself in to a bit of a generics coloured corner. Basically I have a generic Interface X<T1, T2 extends Y<?, ?>> with a bunch of methods, including a T1 getFirstClass(), and a T2 getSecondClass(). This works fine for most things, but one of the things I need to do with this is find instances of this Class that are super classes of what I'm looking up, and I need a "catch-all" object for those that can't be found. This means I end up with a Class that looks like:
public class A implements X<Object, Y<?, ?>> {
...
public Class<Y<?, ?>> getSecondClass() {
return ????
}
}
I tried dealing with this by ignoring the <?, ?> bit and using #SuppressWarnings("rawtypes"), which works in Eclipse, but when built by ant, gives the error message type parameter Y is not within its bound. The JDK should be the same - I'm only aware of one being installed on my system, namely 1.6.0_23 (I unfortunately can't update this due to factors beyond my control).
Is there any way I can get around this or am I going to have to go back to the drawing board and redesign my classes?
Obviously -- due to erasure -- there's only one Class object Y.class per class declaration Y<F1, ..., FN>. The type of this object is Class<Y>, Y being a raw type. To pass it of as a Class<Y<A1, ..., AN> you need to upcast and then downcast:
return (Class<Y<?, ?>>)(Object) Y.class;
The relevant JLS references you can find in a previous answer to a similar question.

java generics - parameters cannot be applied to method

I can't seem to figure out why a method call I'm trying to make doesn't work.
I've looked much around SO before asking this, and while there are (many) threads about similar problems, I couldn't find one that quite fits my problem..
I have the following code:
(in file Processor.java:)
public interface Processor
{
Runner<? extends Processor> getRunner();
}
(in file Runner.java:)
public interface Runner<P extends Processor>
{
int runProcessors(Collection<P> processors);
}
(in some other file, in some method:)
Collection<? extends Processor> processorsCollection = ...;
Runner<? extends Processor> runner = ...;
runner.runProcessors(processorsCollection);
IntelliJ marks the last line as an error:
"RunProcessors (java.util.Collection>) in Runner cannot be applied to (java.util.Collection>)".
I can't figure out whats wrong with what I did, especially since the error message is not quite clear..
any suggestions?
thanks.
Both your collection and your runner allow for anything that extend processor. But, you can't guarantee they're the same.
Collection might be Collection<Processor1> and Runner be Runner<Processor2>.
Whatever method you have that in needs to be typed (I forget the exact syntax, but I'm sure you can find it!)
void <T extends Processor<T>> foo() {
Collection<T> procColl = ...
Runner<T> runner = ...
runner.runProc(procColl);
}
Edit:
#newAcct makes an excellent point: you need to genericize (is that a word?) your Processor. I've updated my code snippet above as to reflect this important change.
public interface Processor<P extends Processor>
{
Runner<P> getRunner();
}
public interface Runner<P extends Processor<P>>
{
int runProcessors(Collection<P> processors);
}
You have not made your situation clear and you're not showing us any of the code of the methods or of how you get the objects, so we don't really know what you're trying to do.
Your code is not type-safe. As #glowcoder mentioned, there is no way of knowing that the parameter of Collection is the same as the parameter of Runner. If you believe they are indeed the same, then that is based on code that you're not showing us (i.e. what happens in "..."?)
You have written Processor's getRunner() method with a return type that has a wildcard parameter. This says when run it will return a Runner with a mysterious parameter that it determines and we don't know. This doesn't make much sense and is probably not what you wanted.
Also depending on what you are doing, the runProcessors method could possibly take a less strict bound. For example, perhaps <? extends P> or even <? extends Processor> if you don't need to modify the collection.

Subclassing a generic type, returning instances of the subclass from a method in another class

It was such a simple, brilliant idea. Use the power of Java 5.0 enumerated types to encode details of a data dictionary (attribute name, type, range, units, etc.) and create a type-safe system for setting and reading attribute values (i,.e., attribute AAH is short, ACC is enumerated and should only accept the values ACC001, ACC002, ACC003, etc.).
The hitch is that different attributes have different types (integer, float, text, enumerated), and the behaviors for each type are different. So I create a base class with a type parameter and some abstract methods:
public abstract class GsAttributeValueBase<T extends Comparable<T>> {
protected T m_value;
...
public GsAttributeValueBase(...) {..}
...
public abstract void SetValue(T value) throws IllegalArgumentException;
public T GetValue() { return m_value; }
// etc., etc., etc
}
I then subclass this for each type (basically, I'm trying to fake partial specialization):
public class GsAttributeValueShort extends GsAttributeValueBase<Short> {...}
public class GsAttributeValueLong extends GsAttributeValueBase<Long> {...}
public class GsAttributeValueEncoded extends GsAttributeValueBase<GsAttributeEncodedValueEnum> {...}
...
So far so good. Now I want to basically create a factory method in the attribute enumeration type to return an instance of one of the above subtypes (since each attribute knows its type and range), something like
public GsAttributeValueBase<? extends Comparable<?>> CreateInstance()
{
switch(m_format)
{
case SHORT: return new GsAttributeValueShort(...);
case LONG: return new GsAttributeValueLong(...);
case ENCODED: return new GsAttributeValueEncoded(...);
...
}
}
and call the method as:
GsAttributeValueShort = GsAttributeEnum.AAH.CreateInstance();
This is where I hit a brick wall; I get an incompatible types error on the order of
found : GsAttributeValueBase<capture of ? extends java.lang.Comparable<?>>
required: GsAttributeValueShort
I've tried roughly a dozen permutations on the declaration of CreateInstance() so far (it can't be static, since it relies on information specific to the enumeration instance). I'm about to tear my hair out at this point; I've wasted several days going down this rabbit hole, and need to either get this working today or punt altogether.
I really want to make this work; I think it would be valuable to not just this project but other projects going forward. But Java generics don't behave like C++ templates (something that's been driven home with a vengeance over the past week), and I know I'm missing something vital here, but I can't see what it is.
EDIT
I can't make this work the way I'm envisioning in my head and I've burned too much time on it. Thanks for the suggestions, but I'm going to go ahead and close this down.
EDIT 2
Oh. I can't close my own question. Oh well.
What about:
public <T extends Comparable<T>> GsAttributeValueBase<? super T> CreateInstance() {
...
}
Just use a map and my TypeSafeMap pattern.
Some thoughts on Generics: Generics are meant to make collections type safe. They aren't really intended for complex things like building type-safe classes at runtime. So be mindful and use your tools so that they don't become a burden. If a cast works and you don't understand how the generic construct works (even if you just wrote it), use the cast. Just imagine coming back to this code in half a year and having to fix it.

Categories