this code doesn't compile. I'm wondering what I am doing wrong:
private static Importable getRightInstance(String s) throws Exception {
Class<Importable> c = Class.forName(s);
Importable i = c.newInstance();
return i;
}
where Importable is an interface and the string s is the name of an implementing class.
The compiler says:
./Importer.java:33: incompatible types
found : java.lang.Class<capture#964 of ?>
required: java.lang.Class<Importable>
Class<Importable> c = Class.forName(format(s));
thanks for any help!
All the solutions
Class<? extends Importable> c = Class.forName(s).asSubclass(Importable.class);
and
Class<? extends Importable> c = (Class<? extends Importable>) Class.forName(s);
and
Class<?> c = Class.forName(format(s));
Importable i = (Importable)c.newInstance();
give this error (that i don't understand):
Exception in thread "main" java.lang.IncompatibleClassChangeError: class C1
has interface Importable as super class
where C1 is actually implementing Importable (so it is theoretically castable to Importable).
Use a runtime conversion:
Class <? extends Importable> c
= Class.forName (s).asSubclass (Importable.class);
This will bark with an exception at runtime if s specifies a class that doesn't implement the interface.
Try:
Class<? extends Importable> klaz = Class.forName(s).asSubclass(Importable.class);
Here are some snippets to illustrate the problems:
Class<CharSequence> klazz = String.class; // doesn't compile!
// "Type mismatch: cannot convert from Class<String> to Class<CharSequence>"
However:
Class<? extends CharSequence> klazz = String.class; // compiles fine!
So for an interface, you definitely need the upper-bounded wildcard. The asSubclass is as suggested by doublep.
API links
<U> Class<? extends U> asSubclass(Class<U> clazz)
Casts this Class object to represent a subclass of the class represented by the specified class object. Checks that that the cast is valid, and throws a ClassCastException if it is not. If this method succeeds, it always returns a reference to this class object.
Related questions
What is the difference between <E extends Number> and <Number>?
See also
Java Tutorials/Generics/Subtyping
More fun with wildcards
Something like this might do the trick:
Class<?> c1 = Class.forName(s);
Class<? extends Importable> c = c1.asSubclass(Importable.class);
return c.newInstance();
Beware of a ClassCastException or NoClassDefFound if you pass in the wrong thing. As #polygenelubricants says, if you can figure out some way to avoid Class.forName then so much the better!
The issue is Class.forName is a static method with the following definition
public static Class forName(String className) throws ClassNotFoundException
Therefore it is not a bound parameter type at all and compiler would definitely throw the cast warning here as it has no way to guarantee the string name of the class would always give you the implementation of the interface.
If you know for sure that the string name passed into the method would be an implementation of the interface you can use SuppressWarnings annotation. But I dont think ther eis any other cleaner way to use forName with generics
where Importable is an interface and the string s is the name of an implementing class.
The compiler can't know that, hence the error.
Use a cast. It is easier to cast the constructed object (because that is a checked cast), than the class object itself.
Class<?> c = Class.forName(s);
Importable i = (Importable) c.newInstance();
return i;
Related
I am trying to write a method where I can convert from a string to an enum object at runtime, for a generic enum. I have a method signature:
public static <T extends Enum<T>> Enum<T> foo(String string, Class<T> clazz)
However, I am calling it from a class whose generic type parameter does not explicitly extend Enum. i.e.
class bar<X> {
private Class<X> clazz;
if (XIsAnEnum()) {
foo(string, clazz)
}
}
This does not compile because even though I know, from the logic of XIsAnEnum, that X extends Enum<X>, I don't explicitly state this in the generic type parameter definition, so it is not a valid argument.
Is there a way to do an unchecked cast from Class<X> to Class<X extends Enum<X>>, or will I have to make a new class bar2<X extends Enum<X>> specifically for when I want to use enums?
You can use Class#asSubclass(Class) to do the cast for you, like
foo("value", clazz.asSubclass(Enum.class));
This involves an actual verification that clazz is referring to a Class that is a subclass of Enum.
You're throwing out all the generic verification here though.
I have the following method:
public Comparator<T> getComparator() throws ReflectiveOperationException {
String className = "some.ClassName";
Class<Comparator<T>> c = Class.forName(className); // (1)
return (Comparator<T>) c. newInstance();
}
In the line (1) I get this error:
Type mismatch: cannot convert from Class <capture#1-of ?> to
Class<Comparator<T>>
What's wrong in this code and how should I make an instance of Comparator<T>?
The best you can get so far is
public <T> Comparator<T> getComparator() throws ReflectiveOperationException {
Class<? extends Comparator> implementation
= Class.forName("some.ClassName").asSubclass(Comparator.class);
#SuppressWarnings("unchecked")
final Comparator<T> c = implementation.newInstance();
return c;
}
Note that there is still an unchecked operation which is unavoidable. The runtime type token Comparator.class produces a Class<Comparator> rather than Class<Comparator<T>> which reflects the type erasure and implies that you can use it via asSubclass to ensure that a Class indeed implements Comparator, but you can’t ensure that it implements Comparator<T> regarding any <T>. (Note that this method doesn’t even know what T is). Therefore there is still an unchecked conversion of Comparator to Comparator<T>.
Simply move the cast:
Class<Comparator<T>> c = (Class<Comparator<T>>) Class.forName(className); // (1)
return c.newInstance();
Try this solution
#SuppressWarnings("unchecked")
public Comparator<T> getComparator() throws Exception {
String className = "some.ClassName";
Class<?> c = Class.forName(className); // (1)
return (Comparator<T>) c. newInstance();
}
This program does not compile:
public class xx {
static class Class1<C> {
void method1(C p) {
}
}
static class Class2<T> extends Class1<Class<? extends T>> {
T object;
void method2() {
this.method1(this.object.getClass());
}
}
}
The error is:
xx.java:10: method1(java.lang.Class<? extends T>) in xx.Class1<java.lang.Class<? extends T>>
cannot be applied to (java.lang.Class<capture#215 of ? extends java.lang.Object>)
this.method1(this.object.getClass());
Why does this happen? Why does the compiler seemingly believe that object.getClass() returns Class<? extends Object> instead of Class<? extends T> ?
There is no upper bound set on T in your code, so ? extends T is really tantamount to ? extends Object. Just yesterday I played with a similar example and hit this barrier. I had
static <T> T newInstance(T o) throws Exception {
final Class<? extends T> c = o.getClass();
return c.newInstance();
}
and it complained with the same error. Consider this: the return type of Object.getClass() is Class<?> and the compiler will want to capture the ? into a concrete type. But instead, we would like not to capture the ?, but to "capture the upper bound" T -- and there is no such thing in Java's generics.
Object.getClass() is defined to return a Class<? extends |T|>, where T is the statically known type of the receiver (the object getClass() is called on). Take special note of the vertical bars, the erasure operator. The erasure of a type variable is the erasure of its leftmost bound. In your case that's the implicit bound Object. So you get back a Class<? extends Object>, not a Class<? extends T>.
Why is that?
Imagine T = List<Integer>, you could suddenly do the following without unchecked warning:
List<String> myStrings = new ArrayList<>();
List<Integer> myInts = new ArrayList<>();
List<Integer> myIntyStrings = myInts.getClass().cast(myStrings);
myIntyStrings.add(-1);
String myString = myStrings.get(0); // BANG!
But thankfully we do get a warning.. ;)
According to the documentation on getClass(), the returned object has type Class< ? extends |X| >, where |X| is the erasure of the type of the instance on which the method is called.
Therefore calling getClass() on an object of type T returns Class< ? extends Object >. We have no bound information about T in this API.
Usually APIs which use reflection on generic classes require that the client pass an additional argument of type Class< T > to the constructor or generic method in question.
I'm trying to create library with a container that releases instances of its contained objects according to descriptors it is passed. I'd like to make it so the descriptor determines the type of the returned object, but the descriptor can specify a bounded type. How do I implement this? For example the closest I can get is:
/*Block 1 - First Attempt. Compiles, but forces user to cast*/
interface ItemDescriptor<I> {
Class<? extends I> getType();
}
interface ArchiveContainer<I, D extends ItemDescriptor<? extends I>> {
Iterable<? extends D> getDescriptors();
I getItem(D descriptor);
}
//Implementations
class ChannelItemDescriptor<I extends ByteChannel> implements ItemDescriptor<I>
{
final Class<? extends I> type;
ChannelItemDescriptor(Class<I> type) {
this.type = type;
}
#Override Class<? extends I> getType() {return type;}
}
class ChannelArchive implements ArchiveContainer<ByteChannel, ChannelItemDescriptor<? extends ByteChannel>> {
#Override ByteChannel getItem(ChannelItemDescriptor<? extends ByteChannel> descriptor) {...}
}
The above code compiles, but the problem is ChannelArchive's getItem can return SeekableByteChannels as well. The user of this library knows this at compile time (because they know the type parameter of the descriptor), so I'm trying to avoid adding a method parameter of type Class for forcing the user to explicitly cast the returned value to SeekableByteChannel when necessary. I can't figure out how to get getItem to return a specific subtype of ByteChannel without forcing the user to cast. I want to do this:
/*Block 2 - Test code*/
ChannelArchive archive = ...;
ChannelItemDescriptor<SeekableByteChannel> desc = ...;
ChannelItemDescriptor<ByteChannel> otherDesc = ...;
SeekableByteChannel sbc = archive.getItem(desc);
SeekableByteChannel sbc = archive.getItem(otherDesc); //Should fail to compile, or compile with warning
ByteChannel bc = archive.getItem(otherDesc);
I could add a Class<? extends I> parameter to each method, but the code for the method would completely ignore Class method parameter! It's only purpose would be to help the compiler infer types. I think it just obfuscates the code so much that it would be easier to just have the user use instanceof checks and casts.
I've tried this:
/*Block 3 - Failed attempt.*/
class ChannelArchive implements ArchiveContainer<ByteChannel, ChannelItemDescriptor<? extends ByteChannel>> {
//Won't compile, getItem doesn't override
#Override <II extends ByteChannel> II getItem(ChannelItemDescriptor<II> descriptor) {...}
}
but that doesn't work: ChannelArchive is not abstract and does not override abstract method getItem(ChannelItemDescriptor<? extends ByteChannel>) in ArchiveContainer. I assume this is because the second type parameter <II extends ByteChannel> has different type erasure than <? extends ByteChannel>?
I've also tried this, which compiles:
/*Block 4 - Almost specific enough*/
interface ArchiveContainer<I, D extends ItemDescriptor<? extends I>> {
Iterable<? extends D> getDescriptors();
<II extends I, DD extends ItemDescriptor<II>> II getItem(DD descriptor);
}
class ChannelArchive implements ArchiveContainer<ByteChannel, ChannelItemDescriptor<? extends ByteChannel>> {
#Override <II extends ByteChannel, DD extends ItemDescriptor<II>> II getItem(DD descriptor) {...}
}
Even though it compiles, it won't really work because I need a ChannelItemDescriptor inside that method, and the resulting cast would defeat the purpose of using the added type-safety of generics.
I don't see why I can't do it, because the right types are known at compile time. What I really need on that ArchiveContainer interface is a parameterized type parameter, like: <II extends I, DD extends D<II>>. What am I doing wrong?
NOTE: I don't actually use ByteChannel and SeekableByteChannel, but what I do use is quite similiar.
That's to ruakh, I settled on the code in block 4. In my case, its highly unlikely the user would send the wrong sublcass of ItemDescriptor in a call to a getItem, especially because the descriptors are all returned from the ArchiveContainer itself via getDescriptors!
I think this code, which is (almost?) the same as your third attempt, is as good as you're going to get:
// in ArchiveContainer:
<II extends I, DD extends ItemDescriptor<II>> II getItem(DD descriptor);
// in ChannelArchive:
public <II extends ByteChannel, DD extends ItemDescriptor<II>>
II getItem(DD descriptor)
{ ... }
Generics do offer a way to declare a type variable with two separate upper bounds:
public <T extends Foo & Bar> Foo fooBar(T t) { ... }
but apparently that's not allowed when one of the upper bounds is a type-parameter rather than a class or interface:
Type variables have an optional bound, T & I1 ... In. The bound consists of either a type variable, or a class or interface type T possibly followed by further interface types I1 , ..., In. […] It is a compile-time error if any of the types I1 ... In is a class type or type variable. [link]
(emphases mine). I don't know why this is.
But I don't think this should be a big problem. Note that, even after Map was genericized to Map<K,V>, its get method still took type Object. Naturally that method will always return null if you pass in a reference to an object that's not of type K (since such an object should never have been inserted into the map), but this doesn't harm type-safety.
I know that this is probably not what you want to hear, but even though Java generics look syntactically like C++ templates, they differ quite a bit in how they work.
Look up java type erasure in your favorite search engine.
Just because a type is known at compile-time does not, unfortunately, mean that the type is recoverable at runtime, or even during later compile phases.
I've always thought the following should work. I get an object which I know is a Class<X> where X extends some class Xyz. In order to make it type-safe I wanted to use Class.asSubclass like in the following method:
private Class<? extends Xyz> castToXyzClass(Object o) {
final Class<?> resultClass = (Class<?>) o;
final Class<? extends Xyz> result = Xyz.class.asSubclass(resultClass);
return result;
}
However, in Eclipse it doesn't work, the only solution I see is an unchecked cast. I'd bet the above code must work, I've used something like this already... no idea what's wrong here.
asSubclass() operates on the object it's called on, not on its parameter - not what one is used to, but it reads quite well. You just have to do this:
final Class<? extends Xyz> result = resultClass.asSubclass(Xyz.class);
The asSubclass is a bit of a confusing name because you're not obtaining a Class object representing the subclass, you're obtaining the same class object that is retyped to reflect that it is a subclass of some parent class.
In fact, this method is fairly single purpose (and I think you've found it)...it's to take a raw or wildcarded class and get a better type parameter with a runtime check. It's not needed when you don't have gaps in your type information:
class Super {}
class Sub extends Super {}
//...
Class<Sub> subClass = Sub.class;
//both work, but the latter introduces a redundant runtime check
Class<? extends Super> subOfSuper1 = subClass;
Class<? extends Super> subOfSuper2 = subClass.asSubclass(Super.class);