0

I wonder what is missing to get the following overloading functions to work?

e.g.

List<?> list = ...;
for (Object element : list)
  Fun(element);

public void Fun(Integer element) { ... }
public void Fun(String element) { ... }
public void Fun(MyClass element) { ... }
Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
user1589188
  • 5,316
  • 17
  • 67
  • 130

5 Answers5

2

Java uses double-dispatch -- the compiler chooses among overloaded methods based on parameter types, and later, at runtime, the JVM chooses among implementations (overridings) of a method based on the runtime type of this.

You're supplying multiple overloadings, but Java will not automatically switch between them. It looks for an overloading that can accept (Object element) and finds none so the compiler rejects your program.

One way to fix this is to have a runtime dispatch method:

public void Fun(Object element) {
  if (element instanceof Integer) { Fun((Integer) element); }
  ...
}

This works because its static type is very general, and it calls Fun with a parameter type whose type is more specific so is dispatched to a different overloading.

Frequent use of instanceof is often considered an anti-pattern.

Community
  • 1
  • 1
Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
  • Yes thank you, I see where this is going. I was just hoping those instanceof can be done implicitly by jvm at runtime based on the actual instance of the Object element, instead of doing it explicitly using that dispatch method. – user1589188 Feb 04 '14 at 04:23
2

Fun(x) where x is of type Object will try to find a function with the signature Fun(Object), and you've never declared one. I think you want something like this instead.

public void fun(Object obj) {
    if (obj instanceof Integer)
        ((Integer) obj).someMethod(); // line 3
    else if (obj instanceof String)
        ...
}

Note cast in line 3. I would also recommend you to follow Java naming conventions: someMethodName for functions, and SomeClassName for classes.

Christian Tapia
  • 33,620
  • 7
  • 56
  • 73
  • Yes, thank you, I fully understand this can be done. Actually thats my original code. I was only thinking if those instanceof can be removed because obviously jvm knows the actual instance of Object obj and would be nice to call appropriate overloading functions for me automatically. – user1589188 Feb 04 '14 at 04:26
2

Add the logic in for identifying the type of object and typecast it. Then the code will work as you expected.

List<?> list = ...;
for (Object element : list)
// Type cast element to one of the type (Integer, String or MyClass) using Instance of  
  Fun(element);

public void Fun(Integer element) { ... }
public void Fun(String element) { ... }
public void Fun(MyClass element) { ... }
2

you can do something like that

public void SuperFun(Object o){
     if(o instanceof Integer)
          Fun((Integer)o);
     if(o instanceof String)
          Fun((String)o);
     if(o instanceof MyClass)
          Fun((MyClass)o);

}
stinepike
  • 54,068
  • 14
  • 92
  • 112
1

The Java Language Specification says the following about overloading

When a method is invoked (§15.12), the number of actual arguments (and any explicit type arguments) and the compile-time types of the arguments are used, at compile time, to determine the signature of the method that will be invoked (§15.12.2).

The reference you are trying to use as a method argument is declared as type Object, but you don't have an overloaded method that accepts an Object argument.

You will have to rethink your design.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724