Ответ 1
Два подхода, которым вы должны следовать.
Измените имена методов.
Используйте для этого интерфейс.
то либо поместите код foo в сами объекты, либо используйте двойная отправка (в зависимости от вашей парадигмы дизайна и вкуса).
С кодом в объектах, которые были бы:
public interface FooInterface{
void foo();
}
public class Foo
{
public <T extends FooInterface> void abc(Collection<T> objects)
{
for(T object: objects)
{
object.foo();
}
}
}
public class FooString implements FooInterface {
public void foo(){
// do foo for String
}
}
public class FooInteger implements FooInterface {
public void foo(){
// do foo for Integer
}
}
Если домен содержит вашу логику.
С двойной отправкой вы передадите "FooInterface" в метод foo, а на обработчике вызовите соответствующий метод в зависимости от типа.