Java compares generic type to Void

I have a problem comparing java type if it is Void type or not. In other words, I am trying to enforce if my generic type T is invalid or not. My example implementation:

public abstract class Request<T>{

     private T member;

     protected void comparing(){
         if(T instanceof Void) // this make error "Expression expected"
             runAnotherMethod();

         //if I type
         if(member instanceof Void) //Incovertible types; cannot cast T to java.lang.Void
             runAnotherMethod();
     }

     protected void runAnotherMethod(){...}
}

public class ParticularRequest extends Request<Void>{
}

      

I tried to compare id with instanceof

, Class<T>

and Class<Void>

, T.class

and Void.class

. But AndroidStudio shows me an error in every checked case :(

Can you help me how to compare it? thank.

+3


source to share


6 answers


When using java generics, you often need to query the generic type class in the constructor so that you can actually work with the class. I think this is a confusing proposal, so just see the example below:

public abstract class Request<T> {

    private Class<T> clazz;

    // constructor that asks for the class of the generic type
    public Request(Class<T> clazz) {
        this.clazz = clazz;
    }

    // helper function involving the class of the generic type.
    // in this case we check if the generic type is of class java.lang.Void
    protected boolean isVoidRequest(){
        return clazz.equals(Void.class);
    }

    // functionality that depends on the generic type
    protected void comparing() {
        if (isVoidRequest()) {
            runAnotherMethod();
        }
    }

    // ...
}

      



When subclassing, you must pass the generic type class to the super constructor.

public class LongRequest extends Request<Long> {
    public LongRequest() {
        super(Long.class);
    }
}

public class VoidRequest extends Request<Void> {
    public VoidRequest() {
        super(Void.class);
    }
}

      

+2


source


You can keep a member private

that is of the generic class type.

public abstract class Request<T> {

     private T memberOfGenericType;

     protected void comparing() {
         if (memberOfGenericType instanceof Sometype)
             runAnotherMethod();
     }

     protected void runAnotherMethod() { ... }

     public T getMemberOfGenericType() {
        return memberOfGenericType;
     }

     public void setMemberOfGenericType(T value) {
        this.memberOfGenericType = value;
     }
}

      



This way, in Runtime, it memberOfGenericType

will have a type Sometype

and you can compile the statement if

. You can also check what memberOfGenericType

is equal Sometype

in Runtime using the added getter.

Anyway, as a side note , I would say that there is no need for a generic type unless you use it as a type for a member, method, or method parameter, and then you have to rethink your design. Also, in particular, the type is Void

not real, so you won't be able to pass a valid instance for a class member, which more or less makes the assertion if

useless.

+1


source


You cannot use T. For comparison, you need an example. For example, some member or parameter:

public abstract class Request<T> {
    T member;

     protected void comparing(T param){
         if(member instanceof Void)
             runAnotherMethod();

         if(param instanceof Void)
             runAnotherMethod();

     }

     protected void runAnotherMethod(){...}
}

      

0


source


The best approach to accessing the parameter class used by Guice is that while the generic class cannot access its own class arguments, its do subclasses have access to those arguments: see fooobar.com/questions/2182093/ .. ...

If you need it, use Guice ' TypeLiterals

or repeat their logic.

0


source


Since there are no objects in Java that are instances of a type Void

, you cannot use here instanceof

.

null

is the only value that is a member of the type Void

. So maybe you want to do this ?:

 if (memberOfGenericType == null)
     runAnotherMethod();

      

About type Void

Objects of the type Void

cannot be instantiated because the class only has a private constructor and is never called from the class. Void

commonly used in the following situations:

  • To get an object Class

    that represents the return type of the methods declared to return Void

    .
  • As a placeholder type argument when fields and variables of that type are not intended to be used.
0


source


At runtime, it will T

compile as Object

, and the actual class is unknown. As others have said, you must maintain an instance of your parameterized type, but this is not automatic: you need to instantiate it, and the constructor T()

cannot be used.

It is also not possible to instantiate java.lang.Void

, so you have to use another class like a homemade class Void

.

Try something like this:

public final class Void {}; // cannot use java.lang.Void, so create another class...

public abstract class Request<T> {
  protected abstract T member(); // A member would need to be initialized...

  protected void comparing(T param){
    if(member() instanceof Void) // Use our Void not java.lang.Void
      runAnotherMethod();

  }

  protected void runAnotherMethod(){...}
}

public class ParticularRequest extends Request<Void>{
  @Override
  protected Void member() { return new Void(); } // Could be optimized...
}

      


Edit:

I don't see why you need this. If you have different children for different types, then you may also have different implementations.

Something like this (types and methods for example only):

public abstract class Request<T> {
  protected abstract T method();
}

public class RequestInt extends Request<Integer> {
  @Override
  protected Integer method() {...}
}

public class RequestText extends Request<String> {
  @Override
  protected String method() {...}
}

      

0


source







All Articles