tags:

views:

245

answers:

4

Somebody help me with these generics!

If you have an overloaded method with different types which can be an argument, can one write a generic method which at runtime call the right one? (Sorry if my java-nology is poor, if so)

Example:

public interface CoolInterface {
   setOverloadedValue(String o);
   setOverloadedValue(Integer o);
   setOverloadedValue(Date o);
}

public interface ClazzProvider {
   Class getClazz();
}

public class SomeUncoolClass {

   @AutowiredMagic CoolInterface coolGuy;
   @AutowiredMagic ClazzProvider clazzyProvider;

   public void helpMeMethod() {
      coolGuy.setOverloadedValue(getValue(clazzyProvider.getClazz()));
   }

   private ??? getValue(???) {
      return ???;
   }
}

What is the method signature of getValue()? And how can i implement it?

+6  A: 

No - the overload is selected at compile time, and the compiler can't tell which overload you want to use.

You might want to have a look at at the Visitor Pattern as a workaround for the case where the types you want to accept are under your control - it doesn't help much when you want to accept String/Date/Object though :(

Jon Skeet
How is that a workaround?
ChloeRadshaw
@ChloeRadshaw: It's a slightly different approach to the same kind of problem. It wouldn't help with String/Integer/Date as the targets, but for others in a similar situation it's an alternative. Will edit to make that clearer.
Jon Skeet
+1  A: 

You can accomplish something similar with what Joshua Bloch call a typesafe heterogenous container (THC) in Effective Java 2nd Edition.

import java.util.*;

class TypesafeHeterogenousContainer {
    Map<Class<?>, Object> map = new HashMap<Class<?>, Object>();

    public <T> T get(Class<T> klass) {
        return klass.cast(map.get(klass));
    }

    public <T> void put(Class<T> klass, T thing) {
        map.put(klass, thing);
    }
}

public class Main {
    public static void main(String args[]) {
        TypesafeHeterogenousContainer thc = new TypesafeHeterogenousContainer();
        thc.put(String.class, "a string");
        thc.put(Integer.class, 5);
        System.out.println(thc.get(String.class)); // prints "a string"

        thc.put(String.class, 5); // compile-time error
    }
}

This is not exactly done by overloading, because that's impossible since Java generics uses type-erasure. So instead you have to pass Class<?> objects around at run-time.

You can read more about this in the book, or in some other pages online.

If you don't have the book, you can read it from his 2006 presentation at Java One PDF.

polygenelubricants
Thanks for the links. They were a great read!
JavaRocky
You are more than welcome =)
polygenelubricants
+1  A: 

As Jon Skeet said, generics will not help in this case.

You could look at the Visitor pattern, that helps in some situations where polimorphic paramenters need diferent method executions. But WATCH OUT: it only helps if the type hierarchy is stable.

If you want a generic processing, with an unstable list of types, or you don't like the visitor pattern complexity, I should recommend a Map<Class, ValueProcessor>:

private [static?] Map<Class, ValueProcessor> processors = new HashMap<Class, ValueProcessor>();

// initialization
processors.put(Integer.class, new ValueProcessor() {
   public void process(Object value) {
      doStuffWith( (Integer) value);
   }
});

processors.put(Date.class, new ValueProcessor() {
   public void process(Object value) {
      doStuffWith( (Date) value);
   }
});

// and so on...

public interface ValueProcessor {
   public void process(Object value);
}
helios
+2  A: 

I'm not sure what the intension of this code is, but maybe you want something like this:

public interface CoolInterface<T> {
   void setOverloadedValue(T o);
}

public interface ValueProvider<T> {
   T getValue();
}

public class SomeUncoolClass<T> {

   private CoolInterface<? super T> coolGuy;
   private ValueProvider<? extends T> valueProvider;

   public void helpMeMethod() {
      coolGuy.setOverloadedValue(valueProvider.getValue());
   }
}
Arne Burmeister