-1

I have a generic class which has a method getOutput. I want to make decision based on the type of T (the class type). I tried the below but it does not work.

class Test<T> implements Interface1<T> {

public T getOutput(String input) {
    
     if (T instanceof Class1) {
       //do something
     } else {
       //do something else
     }
}

}
Zack
  • 2,078
  • 10
  • 33
  • 58
  • That `T` is the type of *something* inside your class, isn't it? That's what you should check, not `T` itself. – Federico klez Culloca Jul 09 '20 at 07:26
  • T can be say String or Integer. If T is a String, I will do action-1. If T is an Integer, I will do action-2. – Zack Jul 09 '20 at 07:28
  • And `getOutput` itself returns something of type `T`. What were you going to return? – Federico klez Culloca Jul 09 '20 at 07:28
  • If T is a String, I will return a String object. If T is an Integer, I will return an Integer object. – Zack Jul 09 '20 at 07:29
  • 1
    You have to pass `Class` as a constructor (or method) parameter if you want to know what it is. That said, it's _usually_ not the Right Thing to do, since the whole point of object-oriented programming is that you should be able to call `input.getWhatever` (either that, or you're really looking for the Strategy design pattern). – chrylis -cautiouslyoptimistic- Jul 09 '20 at 07:32
  • is it possible to do this without setting the instance variable ? – Zack Jul 09 '20 at 07:34
  • I want to generate different return type based on the object type created of Test class. – Zack Jul 09 '20 at 07:35
  • You want to do some more research regarding generics in java. Remember: they are just a "glorified" way of you writing T, and the compiler inserting "Object" as type. Java generics are not C++ templates. At runtime, your T is ... Object. And there is no (easily available way) to know whether it was meant to be String, or Integer. – GhostCat Jul 09 '20 at 07:56

2 Answers2

0

Java does not provide a run-time mechanism allowing a function to determine the type of the expected return value or how its is going to be immediately used. Type parameters of generic methods are being erased after compilation.

See: https://docs.oracle.com/javase/tutorial/java/generics/genMethods.html

You will have to use a method parameter to pass expected type:

interface Value {
    <T> T get(Class<T> tag);
}

class TheValue implements Value {
    @Override
    public <T> T get(final Class<T> tag) {
        if (tag.isAssignableFrom(String.class)) {
            return (T) "something";
        } else {
            return null;
        }
    }
}
andreoss
  • 1,570
  • 1
  • 10
  • 25
0

I tried the below. What do you guys think? Let me know if you have a better solution. We can also discuss solutions using design pattern like strategy pattern. I need this class to give answers in different formats. say. String or Integer...Or Class1 or Class2 (for example)

class Test<T> implements Interface1<T> {

public T getOutput(String input, Class<T> type) {
    
     if (type.isAssignableFrom(String.class)) {
       //do something
       String answer = "10"; // example answer
       return type.cast(answer); 
     } else {
       //do something else
     }
}

}
Zack
  • 2,078
  • 10
  • 33
  • 58
  • What if in a place I want a `List` and in another place a `List`? – rascio Jul 09 '20 at 08:06
  • That's a different question. Lets solve this first. My return type is not a collection. – Zack Jul 09 '20 at 08:07
  • This response is correct, it is the only way to do it in Java, but if the output type is a generic type there is a change that you have to do. Instead of `Class` you should use a `TypeToken` like this: https://guava.dev/releases/21.0/api/docs/com/google/common/reflect/TypeToken.html – rascio Jul 09 '20 at 08:08
  • My only worry is that whether using isAssignableFrom will cause any performance impact? – Zack Jul 09 '20 at 08:10
  • @rascio I don't have the option of using guava library as of now. – Zack Jul 09 '20 at 08:11
  • It doesn't do anything special, so you have to study a little bit (https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getTypeParameters--) if you want generics support. Let me ask a question, do you know all the possible output of your method? – rascio Jul 09 '20 at 08:12
  • Yes. Since I am writing this class and function and its caller as well, I am supporting limited types. Lets say two types Class1, Class2. If there is anything else, I throw exception. – Zack Jul 09 '20 at 08:13
  • so you are worried about the `isAssignableFrom` performance, but not of the `if`. If you know them all, it is better to have a class with a method for each `if` branch, and call the right method in the right place. – rascio Jul 09 '20 at 08:16
  • I was thinking about that as well. Let me re-evaluate the approach. – Zack Jul 09 '20 at 08:26