I found a method like the one below.
public void simpleTest(Class <? extends ParentClass> myClass){
}
I didn't understand the expression : Class <? extends ParentClass> myClass here.
Can anyone explain it?
Class <? extends ParentClass> myClass is a method argument whose type is a Class that is parameterized to ensure that what's passed is a Class that represents some type that is a subtype of ParentClass.
i.e. given:
class ParentParentClass {}
class ParentClass extends ParentParentClass {}
class ChildClass extends ParentClass {}
class ChildChildClass extends ChildClass {}
public void simpleTest(Class <? extends ParentClass> myClass) {}
These are valid:
simpleTest(ParentClass.class);
simpleTest(ChildClass.class);
simpleTest(ChildChildClass.class);
These aren't valid because the argument doesn't "fit" inside the required type:
simpleTest(ParentParentClass.class);
simpleTest(String.class);
simpleTest(Date.class);
simpleTest(Object.class);
Class myClass - means that myClass should be a a sub type of ParentClass.
class MyClass extends ParentClass {
}
simpleTest(ParentClass.class); // this is ok
simpleTest(MyClass.class); // this is ok
class SomeOtherClass {
}
simpleTest(SomeOtherClass.class); // will result in compiler error
From the javadoc of java.lang.Class<T>:
T - the type of the class modeled by this Class object. For example, the type of String.class is Class<String>. Use Class<?> if the class being modeled is unknown.
Now replace String with your class: it's a Class of a type which is a ParentClass or a subclass of ParentClass.
It's a generic method taking a parametrized class.
It might be helpful to first consider a simpler generics example: List<? extends ParentClass> means it's a List that only takes objects that fulfill the is-a relationship with ParentClass. I.e. the parameter of the List implementation is-a ParentClass, but the type of the whole thing List<? extends ParentClass> is List.
In your example, just substitute "Class" instead of "List". myClass is a Class, i.e. you can call the method with something like "MyClassName.class". Further, the parameter of the Class of my Class is-a ParentClass. This basically means that you can only pass the Class of ParentClass or its subclasses to the method.
See also: http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html
Related
I am looking for a small help with my piece of code trying to return list of classes which share the same parent abstract class / interface. Here is the code snippet:
public <T extends Animal> List<Class<T>> getAnimalTypes() {
return Arrays.<T>asList(Dog.class, Cat.class, Bear.class);
}
Dog, Cat and Bear are classes that extends abstract class Animal. What am I missing ? Thanks, Ondrej,
To define a method that returns a list of Class objects with the same parent abstract class/interface, specify the return type List<Class<? extends Animal>> to that method:
public List<Class<? extends Animal>> getAnimalTypes() {
return Arrays.asList(Dog.class, Cat.class, Bear.class);
}
That says to the compiler to require a type of class that extends the class Animal. There is no need to specify the generic type T.
In Java Generics, given a generic class/interface Foo<T>,
What's the difference between declaring a new generic class:
Foobar<T extends Foo<T>> or simply Foobar<T extends Foo>, also why can I instantiate a generic class Foo<T> without instantiating the type parameter T?, i.e. why can i write the following:
Foo var = new Foo();, does this mean that the class is instantiated with an object, through which i can only use the non-generic method?
please forgive me if the question is not so clear, the example i was working on is the following:
MyClass<T extends Comparable<T>>
class Foo<T> {}
is your class.
Foo yourVariable = new Foo();
equals Foo<Object> yourFoo = new Foo<Object>();
class Foobar<T> extends Foo {}
equals class Foobar<T> extends Foo<Object> {}
the answer to your question
class YourClass<T extends Comparable<T>> {}
means YourClass's type T is able to compare itself to objects of T (its class), whereas
class YourClass<T extends Comparable> {}
's type T is able to compare itself to objects of class Object, which is not what you want
I have an interface:
public MyInterface {};
And few enums which implement MyInterface as:
public enum MyFirstEnums implements MyInterface{};
In some another class, I need a method to return Class object such that
the Class should be like MyFirstEnums, which extends enum and implements MyInterface.
The return type of method should be: <E extends Enum<?> & MyInterface>, which should allow returning MyFirstEnums.class and like enums
I tried doing it like:
public <E extends Enum<?> & MyInterface> Class<E> getClazz(){
return MyFirstEnums.class;
}
but this give me error as:
Type mismatch: cannot convert from Class<MyFirstEnums> to Class<E>
What am I missing here?
At other place, I tried a method which takes such type of class as an argument and that worked fine:
public <E extends Enum<?> MyInterface> void doSomething(Class<E> myClazz){};
//it rightly checks the type of myClazz while calling this method
You can't just return the class object of MyFirstEnum. Your method is declared to return a class object that corresponds to an enum and implements MyInterface but it could be an enum other than MyFirstEnum that also meets this criteria. Imagine you have another enum:
public enum MySecondEnum implements MyInterface { }
You could also do:
Class<MySecondEnum> clazz = getClazz();
The compiler infers the type argument from the target return type of clazz (E is inferred as MySecondEnum). In this case, clearly a runtime exception is likely to occur. For example, when you try to instantiate an object from the returned class, you would get a java.lang.InstantiationException.
Note that your method does not actually use the type argument, so why have it generic in the first place?
If you want a "generic" way to return class objects for each enum implementing the interface, you can do something like:
abstract class EnumProvider<E extends Enum<?> & MyInterface> {
...
public abstract Class<E> getClazz();
}
class MyFirstEnumProvider extends EnumProvider<MyFirstEnums> {
...
#Override
public Class<MyFirstEnums> getClazz() {
return MyFirstEnums.class;
}
}
I would try some response:
You want to define a method which return some class type which is not fully defined, but which respects: extends Enum & MyInterface.
And your Class is not passed to the method.
I have a doubt it is not possible or safe.
I would :
1 pass a Class I want as an argument
2 inverse the test: I test inside if Class< E> extends Enum & MyInterface and MyFirstEnum.class and if MyFirstEnum.class extends class< E>
3 of course Class result=MyFirstEnum.class; can be more sophisticated and not known before...
This compiles (because tests are made at runtime) but I dont know if it can help you.
public <E> Class<E> getClazz(Class< E> _return_class) throws Exception
{
Class result=MyFirstEnum.class;
if (MyInterface.class.isAssignableFrom(_return_class) )
if (Enum.class.isAssignableFrom(_return_class))
if (_return_class.isAssignableFrom(result))
return (Class<E>) result;
throw new Exception("Bad Class");
}
I have the following interface and class definitions...
abstract interface I{}
class Foo implements I{}
abstract class A<T extends I> {
List<T> list;
}
class B extends A<Foo> {}
All the definitions work fine. I then want to do the following:
A b = new B();
List<? extends I> iList = b.list;
The compiler will indeed give me an Unchecked Assignment warning... but why? Won't all of A's lists be of type <? extends I>? b.list always has elements that extend I, so I am having trouble seeing why there would be an error
The variable A b is of a raw type. Perhaps you meant to use A<Foo> b instead.
I am trying to return an object which should be an implementation of IClass with a generic type that is an implementation of IType.
public IClass<IType> createClass()
{
return new ActualClass();
}
The actual class I want to return extends Class (abstract), with a generic type of ActualType:
public class ActualClass extends Class<ActualType>
The abstract Class object implements the IClass interface, and can have any type that extends IType
public abstract class Class<T extends IType> implements IClass<T>
The ActualType simply implements the IType interface
public final class ActualType implements IType
I get a "Type mismatch: cannot convert from ActualClass to IClass" error on compilation. I can't understand why, since ActualClass implements IClass (indirectly via Class) and ActualType implements IType.
How can I rearrange this so it works? What have I done wrong or misunderstood?
Ideally I still want to have an interface IClass and IType, an abstract implementation Class, and then an ActualClass which extends the abstract Class and has a specific type which has implemented IType.
The hierarchy of ActualClass is like this:
IClass<ActualType>
^
|
Class<ActualType>
^
|
ActualClass
So, IClass<ActualType> is super type of ActualClass. But the return type of your method is IClass<IType>. Even though IType is super type of ActualType, IClass<IType> is not a super type of IClass<ActualType>, and thus it is also not super type of ActualClass.
So, either change the return type of method to IClass<ActualType>, or IClass<? extends IType>. The following should work:
public IClass<? extends IType> createClass() {
return new ActualClass();
}
Change the method signature of createClass to:
public IClass<? extends IType> createClass() {
return new ActualClass();
}
The reason it doesn't compile is that Generics in Java are not implicitly polymorphic, so you have to explicitly denote that the method would be able to return IClass parameterized by an unknown subset of IType