passing arguments to method with generics in java - java

I have the following structure of classes and methods :
public class NavigationTree<T extends BaseListItem<? extends BaseData>> {
public boolean insert(final T parent, final T child){
}
}
public class Screen extends BaseData {
}
public class DrawerListItem<T> extends BaseListItem<T>{
}
This is what I am calling from one of my other classes :
mCurItems.insert(new DrawerListItem<Screen>(null, null),
new DrawerListItem<Screen>(screen.name, screen));
The compilers throws the following error :
Error: incompatible types: DrawerListItem cannot be converted to CAP#1 where CAP#1 is a fresh type-variable:CAP#1 extends BaseListItem from capture of ? extends BaseListItem
I do not understand why this should be wrong. DrawerListItem extends BaseListItem and Screen extends BaseData. I have tried reading the other posts around generic types and type params but none of them seem to address this issue.

Try this:
public class Test {
public static void main(String[] args) throws java.lang.Exception {
NavigationTree<DrawerListItem<Screen>> nt = new NavigationTree<>();
nt.insert(new DrawerListItem<Screen>(), new DrawerListItem<Screen>());
}
private static class NavigationTree<T extends BaseListItem<? extends BaseData>> {
public boolean insert(final T parent, final T child) {
return true;
}
}
private static class DrawerListItem<T> extends BaseListItem<T> {}
private static class BaseListItem<T> {}
private static class Screen extends BaseData {}
private static class BaseData {}
}

I figured out the solution. In my DrawerListItem declaration I had declared it as
public class DrawerListItem<T> extends BaseListItem<T>{
}
Whereas the NavigationTree was expecting:
<T extends BaseListItem<? extends BaseData>>
Which essentially means :
<DrawerListItem<? extends BaseData>>
in this case.
And hence the error was basically saying that the template type declared vs template type required are different and hence the error.
Hope this helps someone else.
Thanks everyone for the help!

Related

Exact match in type but Java compiler won't compile for List<type>?

private ResourceAssembler<? extends BasedEntity> resourceAssembler;
List<? extends BasedEntity> bases = userRepository.findAll();
return resourceAssembler.toResources(bases, User.class); //<-----compile error
Compile error
Wrong 1st argument type. Found: 'java.util.List<? extends BasedEntity>', required: 'java.util.List<? extends BasedEntity>'
Method signature
public class ResourceAssembler<T extends BasedEntity> {
public Resources<Resource<T>> toResources(List<T> list, Class entityClass) {}
}
What's going on?
Minimal code example which can be copied and pasted into an empty project.
class Main {
ResourceAssembler<? extends BasedEntity> resourceAssembler;
List<? extends BasedEntity> bases;
void test() {
resourceAssembler.toResources(bases);
// the error is here: ^~~~~
}
}
class BasedEntity {}
class ResourceAssembler<T extends BasedEntity> {
void toResources(List<T> list) {}
}

Java Generics - Compile time validation of type and implementing object

I have a method to add implementing class' objects against interface class and I want to make this as a generic one.
The implementing class also extends a class X
public abstract class X<T>{...}
public interface InterfaceA{...}
public class A extends X implements InterfaceA{...}
now, currently my method is:
public <S, <T extends X<S>> void add(Class<S> clazz, T object){...}
But I have no use of type parameter on X, it is just for the above method. Is there a way I could have X without type parameter and still have compile-time validation in method 'add' please?
Thanks
EDIT:
I think my question is not clear. Please look at the below example code:
public interface I {}
public abstract class X {}
public class A extends X implements I {}
public class B implements I {}
public class C extends X {}
public class Main {
public static void main(String[] args) {
add(I.class, new A()); // uses first method
add(I.class, new B()); // uses second method
add(I.class, new C()); // uses first method
}
public static <P, T extends P> void add(Class<P> c, T object) {} //No
public static <P, T extends X> void add(Class<P> c, T object) {} //No
}
I need an 'add' method that just accepts A's instance and not B's not C's.
Both the above method signature don't fulfill my requirement
If you don't care about the type parameter of X, just make it Object:
public class A extends X<Object> implements InterfaceA{...}
So the method will work with anything.
I believe you can remove the type on X and still get a compile-time error for add in the following manner. Now, of course, a little more context will be more helpful if this doesn't meet your requirement.
public abstract class X {
}
public class A<T> extends X implements InterfaceA {
public <S, M extends X> void add(Class<S> clazz, M object){
}
public void abc() {
Class<String> clazz = String.class;
this.add(clazz, new B());//This should throw compilation error
}
}
public class B implements InterfaceA {
}

Proper way to extend ParseObject and have a generic query factory

I need a way to query different parse classes based on choices made by a user. I approached the problem as follows. Please advise how to fix the problem I have or suggest alternative/better approach.
I have classes A, B, C, ... that correspond to Parse classes. They are very similar. So, I created abstract class Q:
public abstract class Q extends ParseObject {
// some shared methods
public abstract ParseQuery<? extends Q> getQuery();
}
Each of A, B, C, ... is defined as:
#ParseClassName("A")
public class A extends Q {
private static final A INSTANCE = new A();
#Override
public ParseQuery<A> getQuery() {
return ParseQuery.getQuery(A.class);
}
public static A getInstance(){
return INSTANCE;
}
}
Than I have the following recycle adapter for my recycle view:
public class QAdapter extends ParseRecyclerQueryAdapter<Q,QAdapter.MyViewHolder>{ ... }
The error I am getting happens on the following line in my activty:
mRecyclerAdapter = new QAdapter(this, factory, true);
The error message is:
Error:(58, 70) error: incompatible types: QueryFactory<CAP#1> cannot be converted to QueryFactory<Q>
where CAP#1 is a fresh type-variable:
CAP#1 extends Q from capture of ? extends Q
I tried to make the definition of adapter class generic as public class QAdapter<T extends Q> extends ParseRecyclerQueryAdapter<T, QAdapter.MyViewHolder> {... }, yet this introduced another error saying that QAdapter did not implement onBindViewHolder even though it is implemented.
This may not work, but I would try replacing
public class QAdapter extends ParseRecyclerQueryAdapter<Q,QAdapter.MyViewHolder>{ ... }
with
public class QAdapter extends ParseRecyclerQueryAdapter<? extends Q,QAdapter.MyViewHolder>{ ... }
Try to replace
extends ParseRecyclerQueryAdapter<T, QAdapter.MyViewHolder> {... }
with
extends ParseRecyclerQueryAdapter<T extends ParseObject, QAdapter.MyViewHolder> {... }
This is how to make my ParseRecyclerQueryAdapter work
Well, as the old saying goes, "make sure everything is contiguous" or something like that. You've got a great idea for a abstract and you're doing it right, but maybe you've just got an inheritance issue by not having the same call issued by the same parameters as met by the processor. like <? extends Q,...> So in that case you've got to make sure it's all redundant. Good luck!
You should make your base class Q generic:
public abstract class Q<T extends Q<T>> extends ParseObject {
// some shared methods
public abstract ParseQuery<T> getQuery();
}
Then your class A becomes
#ParseClassName("A")
public class A extends Q<A> {
private static final A INSTANCE = new A();
#Override
public ParseQuery<A> getQuery() {
return ParseQuery.getQuery(A.class);
}
public static A getInstance(){
return INSTANCE;
}
}
and ParseQuery is:
public class ParseQuery<T> {
public static <T> ParseQuery<T> getQuery(Class<T> clazz) {
return null;
}
}

Bound mismatch: type is not a valid substitute for the bounded parameter

I am getting the following error Bound mismatch: The type FFTWTask is not a valid substitute for the bounded parameter <T extends AbsTask<T>> of the type AbsStage<T,U>
I am representing an abstract stage:
public abstract class AbsStage<T extends AbsTask<T>, U extends AbsTask<U>> { }
Where an AbsTask is:
public abstract class AbsTask <T> { }
Then I create an AbsTask called FFTWTask:
public class FFTWTask extends AbsTask<Double>{ }
Finally, I create an AbsStage called FFTWStage:
public class FFTWStage extends AbsStage<FFTWTask, FFTWTask>{ } // Error occurs here
What am I missing with my understanding of generics. I have found numerous posts that feature the same error message, but I cant seem to decipher them.
Here is a simple class that achieves the error:
public class Test {
public abstract class AbsTask <T> { }
public class FFTWTask extends AbsTask<Double>{ }
public abstract class AbsStage<T extends AbsTask<T>, U extends AbsTask<U>> { }
public class FFTWStage extends AbsStage<FFTWTask, FFTWTask>{ } // Error here <-
}
If the type parameter T in AbsStage must extend AbsTask<T>, then FFTWTask must extend AbsTask<FFTWTask> in order to be used in FFTWStage:
public class FFTWTask extends AbsTask<FFTWTask>{ }

Get actual enum class of the Parameterized class T extends Enum<?>

I have a class:
public class MultipleSorting<T extends Enum<?>> {
private T criteriaType;
public Class<T> getCriteriaClass() {
Field field = ReflectionUtils.getField(getClass(),"criteriaType");
ReflectionUtils.makeAccessible(field);
return (Class<T>)field.getType();
}
}
This class is get instantiated as:
public abstract class MultiSortPageableController<T extends MultiSortPageableController<?,?>, U extends Enum<?>> {
private MultipleSorting<U> multipleSorting;
public MultiSortPageableController() {
super();
multipleSorting = new MultipleSorting<U>();
}
}
The actual value of U is passed from the child class of MultiSortPageableController which is:
public abstract class AbstractArticleSearchController<T extends AbstractArticleSearchController<T>> extends MultiSortPageableController<T,ArticleSortField> {
}
The ArticleSortField is an Enum.
I was expecting the method getCriteriaClass of MultipleSorting would return ArticleSortField from a method of MultiSortPageableController. But it is returning java.lang.Enum.
I am unable to figure it out why it is not returning the actual enum and how can I make it so. Any pointer would be very helpful to me. I need to get ArticleSortField.
Purpose:
I two requirement:
To get the actual class of enum type (say ArticleSortField.class)
To list enum value. If I have the enum class, then I could invoke class..getEnumConstants().
Java compiler removes information about generics, therefore when you use reflection you get no information about the declared type, other than Enum. This process is called type erasure.
How about passing the type down, via the constructor, like this:
public class MultipleSorting<T extends Enum<?>> {
private Class<T> criteriaType;
MultipleSorting(Class<T> criteriaType) {
this.criteriaType = criteriaType;
}
public Class<T> getCriteriaClass() {
return criteriaType;
}
}
public abstract class MultiSortPageableController<T extends MultiSortPageableController<?, ?>, U extends Enum<?>> {
private MultipleSorting<U> multipleSorting;
public MultiSortPageableController(Class<U> criteriaType) {
super();
multipleSorting = new MultipleSorting<U>(criteriaType);
}
}
public abstract class AbstractArticleSearchController<T extends AbstractArticleSearchController<T>> extends MultiSortPageableController<T, ArticleSortField> {
public AbstractArticleSearchController() {
super(ArticleSortField.class);
}
}

Categories

Resources