views:

28

answers:

3

How can I pass a generic type to a method, when I don't know the type?

public static class ExecContext<E> {

    public void doSomething(E e) {

        System.out.println(e);
    }
}

public static void exec(ExecContext<?> ctx) {

    String s = new String("saoj");

    ctx.doSomething(s); // <============== COMPILE ERROR
}
+3  A: 
public static <T> void exec(ExecContext<T> ctx)

should do it.

Edit:

This should do it... a slight change to how you are doing it though:

public class Main
{
    public static void main(String[] args)
    {
        final ExecContext<String>  stringCtx;
        final ExecContext<Integer> integerCtx;

        stringCtx  = new ExecContext<String>();
        integerCtx = new ExecContext<Integer>();
        exec(stringCtx, "Hello, World");
        exec(integerCtx, 42);
    }

    public static class ExecContext<T>
    {
        public void doSomething(final T e)
        {
            System.out.println(e);
        }
    }

    public static <T> void exec(final ExecContext<T> ctx,
                                final T              value)
    {
        ctx.doSomething(value);
    }
}
TofuBeer
Got you, thanks!
Sergio Oliveira Jr.
A: 

That is a bad thing to be trying to do. If you don't know what the generic type is going to be, how do you know if passing a String is type-safe?

If you really want to do this, you have to add the appropriate annotation to the exec method to tell it to suppress the unsafe/unchecked type conversion error. But that is just turning the compilation into a potential ClassCastException at runtime that might be thrown unexpectedly by some subtype of ExecContext that does something different in the doSomething method.

EDIT I don't think that the following is correct either:

    public static <T> void exec(ExecContext<T> ctx) {
        String s = new String("saoj");
        ctx.doSomething(s);
    }

because the compiler cannot tell that the actual type used for T will be String or a (hypothetical) subtype of String. Suppose for instance that exec was called as follows:

    ExecContext<Integer> ctx = ...;
    exec(ctx);

Now when exec calls the doSomething method, it will pass a String instance as an argument, where the generic signature of the doSomething method says it should be passing an instance of E; i.e. an Integer.

Stephen C
A: 

This will not work because the you are passing the ExecContext (of type unknown) so you don't know at compile what type the ExecutionContext holds.

You will have to do this:

public class Test {

     public static class ExecContext<E> {

         public void doSomething(E e) {

             System.out.println(e);
         }
     }

     public static void exec(ExecContext<Object> ctx) {

         String s = new String("saoj");

         ctx.doSomething(s); // <============== NO COMPILE ERROR
     }
  }

Any way whats the point of generics if you are passing the execution context of unknown or object?

naikus