John Kang
John Kang

Reputation: 65

Matching function name but different arguments

Studying "cracking the coding interview" in Java, on page 51 I came across:

void permutation(String str){
   permutation(str,"");
}
void permutation(String str, String prefix){
  if(str.length()==0){
    System.out.println(prefix);
  } else{
    for(int i=0;i<str.length();i++){
        String rem=str.substring(0,i)+str.substring(i+1);
         permutation(rem,prefix+str.charAt(i));
    }
  }
}

I get that the first permutation function takes a string and calls the second permutation function which does all the work. However, isn't the second permutation a redeclaration of the first permutation function? How will Java recognize and use the first permutation function and not overwrite it?

Upvotes: 0

Views: 1139

Answers (4)

Turing85
Turing85

Reputation: 20195

To explain what the semantics are, we need to take a look at how Java methods are differentiated.

In Java, a method is identified by its signature. JLS §8.4.2 specifies that

Two methods have the same signature if they have the same name and argument types.

Important to note is that the return type of a method is not part of a method's signature. Thus if one would write:

public class Foo {
    void bar(String baz) {
    }

    String bar(String baz) {
    }
}

Both methods would have the same signature. In Java, this would lead to a compilation error since it is not allowed to have two methods with the same signature in the same class.

The behaviour changes if we take inheritance into the picture:

public class Foo {
    void bar(String baz);
}

public class Zoo extends Foo {
    @Override
    void bar(String baz);
}

In this case, class Zoo overrides method bar(...) of class Foo. Note that the annotation is not responsible for the behaviour and merely a compile-time check to ensure that there is a method void bar(String baz) in at least one parent-class.

The code presented has two method with same name, but different signatures. This is called Overloading in Java. Thus, the method are treated as not "equal". You could rename one of those method and they would not be more or less "equal".

To make things even weirder, if methods are overloaded, the signature for the method to call is made at compile-time. That means that only the static types of parameters can be considered. Let us look at the following code and figure out what the result is:

public class Test {
    public static void main(final String... args) {
        final String s = "foo";
        final Object o = s;
        print(s);
        print(o);
    }

    private static void print(final String s) {
        System.out.println("Called with String parameter");
    }

    private static void print(final Object o) {
        System.out.println("Called with Object parameter");
    }
}

Ideon demo

Now what is the static type of s? It is the type to the left, where s was declared, thus print(final String s) is called and "Called with String parameter" is printed. What is the static type of o? Again, it is the type to the left, where o was declard, and thus print(final Object o) is called and "Called with Object parameter" is printed out. One could argue that in this trivial example, the compiler could figure out that the type of o can only be String, but basing this behaviour on the ability of the compiler to recognize types at compile-time makes it only more confusing.

Upvotes: 0

dan1st
dan1st

Reputation: 16447

In java, the whole class is loaded before a method is executed.

This means that the second method is loaded/ready before the first method is executed and the first method is loaded/ready before the second method is executed.

This allows to call a method recursively, and to call a method that will be declared later.

Also, the method is overloaded.

In java, it's possible to create multiple methods with the same name in the same class if the parameters are different. The methods will be treated as different, deoending of the argument that are passed to the method.

In other words, the name alone does not define which method is called but the signature, including the parameters(not the return value)

Upvotes: -1

jacobm
jacobm

Reputation: 14035

Unlike in Python, in Java these two declarations live side-by-side -- the second doesn't replace the first. In Java, the rule is roughly that when you call a method with multiple definitions (aka an "overloaded" method), Java will look for the one that best matches the arguments you called it with and run that method. So permutation("hi") invokes the first version, and permutation("hi", "") calls the second.

The fundamental difference here is that in Python you can imagine the interpreter reading the definitions one at a time and replacing its overall definition of permutation every time it gets a new definition. In Java, you have to think of it as reading all the definitions of permutation at once, and calling the most appropriate one for any given invocation.

(A consequence of this is that Java also checks at compile-time that every overloaded version of a method is callable: for instance, if you wrote two versions of permutation that both took just a string as their argument, the compiler would give you an error and wouldn't compile your program at all. In python you'd just get the second definition.)

Upvotes: 0

rhowell
rhowell

Reputation: 1187

How will java recognize and use the first permutation function?

When you call the method, Java will see what you're trying pass into it. Based on the arguments you pass, it will decide which 'version' of the method you are trying to use.

Like others have said - this is method overloading

Upvotes: 2

Related Questions