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.
source to share
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);
}
}
source to share
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.
source to share
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(){...}
}
source to share
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.
source to share
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 returnVoid
. - As a placeholder type argument when fields and variables of that type are not intended to be used.
source to share
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() {...}
}
source to share