I am trying to add the class object of a children class to a set of parent class object :
public class Main {
public static void main(String[] args) {
Set<Class<? extends A<?>>> set = new HashSet<>();
set.add(C.class); //this does not work
}
public abstract class A<T> {
}
public abstract class B<T, V> extends A<T> {
}
// Set<T> could be any other class, it is for demonstration purpose.
public class C<T> extends B<Set<T>, Set<T>> {
}
}
I get the following error :
The method add(Class<? extends Main.A<?>>) in the type Set<Class<? extends Main.A<?>>> is not applicable for the arguments (Class<Main.C>)
If I remove the '?' from the A, the code compiles, but I don't understand why. Can someone explain me why the "add" is not working ?
class is a 'class literal' which only looks like a static field.
As per definition, the type of C.class is Class<C>, where C is the name of a class.
So you cannot add it to a Set of Class<C<?>> (or in your case Set<Class<? extends A<?>>>)
For further information read 15.8.2 Class Literals in the Java specs:
http://docs.oracle.com/javase/specs/jls/se8/jls8.pdf
Related
public interface Fruits {}
public interface SweetFruitsInterface extends Fruits{}
public class FruitParty <T extends Fruits> {
public void getFruits(ArrayList<? super SweetFruitsInterface> fruitList) {
System.out.println("Lets get Fruit List");
}
}
Now to call this method as per my understanding I can pass an arrayList of SweetFruitsInterface type but other than that we can pass super classes of implementation class of SweetFruitsInterface and so I try to create one implementation of SweeFruitsInterface as below:
public class SweetProducts {}
public class SweetFruits extends SweetProducts implements SweetFruitsInterface{}
now I call the method
ArrayList<SweetProducts> sweetProductsArrayList1 = new ArrayList<>();
fruitsFruitParty.getFruits(sweetProductsArrayList1);
But its giving compiler error?
May I know if this SweetProducts is not the super class of implementation class of SweetFruitsInterface , and if it is then why its not working..
I tested this with class scenario where T is super , but i wanna understand how this works for interface
I have following class:
public class AClass<T extends XYZClass> extends BFunction<DTOClass, T>{
#Override
public <T extends XYZClass> T apply(DTOClass input) {
return null;
}
}
where T is generic Type, BFunction is function that implements com.google.common.base.Function with apply method. The problem is that this class declaration construction is invalid, because it corresponds following apply method:
#Override
public T apply(DTOClass input) {
return null;
}
I also tried:
public class AClass extends BFunction<DTOClass, <T extends XYZClass> T>{
#Override
public <T extends XYZClass> T apply(DTOClass input) {
return null;
}
}
but this syntax is invalid.
Could you advise me how to correct my class declaration?
Remove the type variable declared on the method:
public class AClass<T extends XYZClass> extends BFunction<DTOClass, T>{
#Override
public /* remove this */ T apply(DTOClass input) {
return null;
}
}
You're trying to declare another type variable called T which hides the type variable declared on the class.
You are declaring a generic method in your parent class, where the <T extends XYZClass> clause has nothing to do with the <T extends XYZClass> in your class declaration.
What you likely want to do is remove <T extends XYZClass> from your method declaration and overrides altogether.
Say I have a class
abstract class A {
ArrayList<?> l;
public void setList(ArrayList<?> l) //set the list
}
Is it possible to do something like
class B extends A {
public void setList(ArrayList<? extends Foo> l) //Set the list }
I basically would like to specify an abstract class with a parameterised field, where a class inheriting from the first class can specify the type of the field more specifically so that it must extend some other type.
Can a subclass in Java override a set method and make the argument type more specific?
No. When overriding a method the signatures (name and argument types) have to be the same after type erasure. See JLS 8.4.2 for more information.
I basically would like to specify an abstract class with a parameterised field, where a class inheriting from the first class can specify the type of the field more specifically so that it must extend some other type.
abstract class A<T> {
public abstract void setList(ArrayList<? extends T> l);
}
class B extends A<Integer> {
#Override
public void setList(ArrayList<? extends Integer> l) {
//...
};
}
Here the compiler will perform type erasure and the signatures will be identical.
You would need to make A generic:
abstract class A<T> {
abstract void setList(List<? extends T> list);
}
And then make B something like:
class B extends A<Foo> {
#Override void setList(List<? extends Foo> list) { ...}
}
It will work if you generify the base class:
abstract class A<T> {
ArrayList<T> l;
public void setList(ArrayList<T> l) {//set the list
}
}
class B<T extends Foo> extends A<T> {
#Override
public void setList(ArrayList<T> l) {//Set the list
}
}
In a Java application, I'd like to use a generic type parameter which implements an interface which uses a generic parameter itself.
public interface SuperInterface<T> { ... }
public interface MyInterface extends SuperInterface<MyClass> { ... }
public class Worker<T extends SuperInterface<U>> extends SuperWorker<String, Boolean> {
}
However, the class declaration won't work like that. T should be of type MyInterface (or any other interface which implements the SuperInterface) and U should be of type MyClass (or any other class according to the interface).
You have to declare all of the type parameters at the top level. It's annoying, but that's how it is.
public class Worker<U extends MyClass, T extends SuperInterface<U>> { ...
The order of the parameters doesn't matter; you can also do Worker<T extends..., U extends...>. All that matters is that each is declared at the top level of the nested generics.
Here's a complete class:
public class MyClass {
public interface SuperInterface<T>{}
public interface MyInterface extends SuperInterface<MyClass> {}
public class Worker<U extends MyClass, T extends SuperInterface<U>> {}
public void compileTest() {
// just to make sure the declaration compiles
Worker<MyClass, MyInterface> worker = null;
}
}
Within my code a have the following abstract superclass
public abstract class AbstractClass<Type extends A> {...}
and some child classes like
public class ChildClassA extends AbstractClass<GenericTypeA> {...}
public class ChildClassB extends AbstractClass<GenericTypeB> {...}
I'm searching for an elegant way how I can use the generic type of the child classes (GenericTypeA, GenericTypeB, ...) inside the abstract class in a generic way.
To solve this problem I currently defined the method
protected abstract Class<Type> getGenericTypeClass();
in my abstract class and implemented the method
#Override
protected Class<GenericType> getGenericTypeClass() {
return GenericType.class;
}
in every child class.
Is it possible to get the generic type of the child classes in my abstract class without implementing this helper method?
BR,
Markus
I think its possible. I saw this was being used in the DAO patterns along with generics. e.g.
Consider classes:
public class A {}
public class B extends A {}
And your generic class:
import java.lang.reflect.ParameterizedType;
public abstract class Test<T extends A> {
private Class<T> theType;
public Test() {
theType = (Class<T>) (
(ParameterizedType) getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
}
// this method will always return the type that extends class "A"
public Class<T> getTheType() {
return theType;
}
public void printType() {
Class<T> clazz = getTheType();
System.out.println(clazz);
}
}
You can have a class Test1 that extends Test with class B (it extends A)
public class Test1 extends Test<B> {
public static void main(String[] args) {
Test1 t = new Test1();
Class<B> clazz = t.getTheType();
System.out.println(clazz); // will print 'class B'
System.out.println(printType()); // will print 'class B'
}
}
I'm not sure I fully understand your question - <Type> is the generic type of the subclass, even when it's being expressed in the abstract class. For example, if your abstract superclass defines a method:
public void augment(Type entity) {
...
}
and you instantiate a ChildClassA, you'll only be able to call augment with an instance of GenericTypeA.
Now if you want a class literal, then you'll need to provide the method as you indicated. But if you just want the generic parameter, you don't need to do anything special.