4

I have this class :

public class Bird extends AbstractEntity<Long> implements IHasWings {
}

And some other classes that extends AbstractEntity but they don't implement IHasWings, for example :

public class Cat extends AbstractEntity<Long>{
}

I pass these classes as a type argument in their DAO classe, like this :

public class BirdDAO extends AbstractDAO<Bird, Long> { ... }

and

public class CatDAO extends AbstractDAO<Cat, Long> { ... }

So all the DAO classes are extending the AbstractDAO class.

In AbstractDAO class I have this :

public abstract class AbstractDAO<T extends AbstractEntity<ID>, ID extends Serializable> { 
    public List<T> findAll(){ 
        AbstractEntity entity = ...
        if (entity instanceof IHasWings) {
            IHasWings entityWithWings = (IHasWings) entity;
            //Do something with entityWithWings.getWingSize();
        }else{
            //Do something else
        }
    }
}

I want to test if the passed type argument is implementing IHasWings as you can see above, but I couldn't find a way to do it.

I tried the following :

Class<T> entity = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass())
    .getActualTypeArguments()[0];
if (entity instanceof IHasWings) {...}

Which threw this error : Incompatible conditional operand types Class<T> and IHasWings

How can I solve this ?

Zabuzard
  • 25,064
  • 8
  • 58
  • 82
Renaud is Not Bill Gates
  • 1,684
  • 34
  • 105
  • 191
  • https://stackoverflow.com/questions/22467362/in-java-why-is-there-no-generic-type-info-at-run-time – PeterMmm Jun 14 '18 at 10:28
  • 1
    Your `if (entity instanceof IHasWings)` at the bottom is equivalent to `class instanceof class`. A class is, by definition, not an instance of anything. – Michael Jun 14 '18 at 10:35

1 Answers1

4

Your check is incorrect in that it's verifying that an instance of Class<?> is an instance of IHasWings. The compiler prevents instanceof checks using objects and types that have no relationship (java.lang.Class objects can never be instances of your IHasWings interface).

What you're looking for is a way to find out whether IHasWings is compatible with the class object in entity. For that, what you need is:

IHasWings.class.isAssignableFrom(entity)

From the javadocs (java.lang.Class.isAssignableFrom(Class<?> cls)):

Determines if the class or interface represented by this Class object is either the same as, or is a superclass or superinterface of, the class or interface represented by the specified Class parameter.

Zabuzard
  • 25,064
  • 8
  • 58
  • 82
ernest_k
  • 44,416
  • 5
  • 53
  • 99
  • Thanks for your help, but then how can I cast `entity` so I can do `entity.getWingSize()` ? – Renaud is Not Bill Gates Jun 14 '18 at 10:47
  • @IchigoKurosaki You mean inside `findAll`? There are two variables named `entity` in your question, one being a `Class`, the other being an `AbstractEntity`. I believe the way you have it in `AbstractDAO` will work, assuming the actual creation of `AbstractEntity entity` instance uses the correct class to create the object. [But why are you using the raw type `AbstractEntity`? Is this a sign of a problem? Or is this because you're using reflection to instantiate objects?] – ernest_k Jun 14 '18 at 11:01
  • Well I wrote `AbstractEntity entity = ...` because I didn't know how to instantiate `entity`, that's not the final code. – Renaud is Not Bill Gates Jun 14 '18 at 11:05
  • @IchigoKurosaki Right. Then I'm sure `if (entity instanceof IHasWings)` will work if the correct `AbstractEntity` subclass is used at runtime. – ernest_k Jun 14 '18 at 11:07
  • Emm, actually I get this compilation error : `Incompatible conditional operand types Class and IHasWin` when I do that. – Renaud is Not Bill Gates Jun 14 '18 at 11:10
  • @IchigoKurosaki That's why I said you have two variables named `entity` in the question. The second one would give that compiler error (and that's the one my answer was about), but the first one (in your `AbstractDAO.findAll` method) wouldn't. – ernest_k Jun 14 '18 at 11:12