Matching function name but different arguments - java

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?

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

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.)

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.

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)

Related

Array Containing Methods/Functions for Argument Passing

I have a method that selects between the arguments of an array and returns a specific one. For instance, here is that method:
private <T> T selectOnType(T[] selection, T defaultOp){
switch(this.type){
case Resources.TEXT:
return selection[Resources.TEXT];
case Resources.LISTEN:
return selection[Resources.LISTEN];
default:
return defaultOp;
}
}
How can I construct an array full of method references (i.e. function pointers) in order to be able to pass that array into this method above?
I tried doing such things as:
java.util.function.Function<Void, Void>[] array = {ClassA::method1, ClassA::method2};
(where method1 and method1 take no arguments and return void)
But that throws a compiler error saying:
incompatible types: invalid method reference but expected no arguments. found: java.lang.Void reason: actual and formal argument lists differ in length
I have been playing around with lambdas such as:
() -> ClassA.method1()
But I haven't been able to get it to work. Does anyone know what I am doing wrong and know a solution to this problem?
EDIT:
I have seen this on Stack Overflow, but this is for C# and I haven't figured out how to mimic it in Java.
Example:
Let's say I have a Word class:
public class Word{
private final String text;
private int listenCorrect = 0, textCorrect = 0;
public Word(final String test){
this.text = text;
}
public void incListenCorrect(){
listenCorrect++;
}
public void incTextCorrect(){
textCorrect--;
}
}
And finally I have a Main class. Inside the action method (in the Main class) I want to have an array with these two methods in it in order to select between them if the type (shown below) is either listen or text:
public class Main{
int type = 0;
public void action(){
Word word = new Word("Hello");
// 'Functions' is used to represent something I tried above (just for demonstration)
Function[] array = {word::incListenCorrect, word::incTextCorrect};
Function picked = selectOnType(array, word::incTextCorrect);
picked.call();
}
/*
* Resources is another class that contains the following values:
* public static final int TEXT = 0;
* public static final int LISTEN = 1;
*/
private <T> T selectOnType(T[] selection, T defaultOp){
switch(this.type){
case Resources.TEXT:
return selection[Resources.TEXT];
case Resources.LISTEN:
return selection[Resources.LISTEN];
default:
return defaultOp;
}
}
}
A Function is a method that takes one argument and returns a result. You're using methods that take no arguments and do not return results. You can't use Function for this (using Void isn't a way to get around this), but the java.util.function package contains a number of classes for different common combinations (methods that take no arguments but return a result, methods that take one or two arguments and don't return a result, methods that take primitive arguments or return primitive results that won't work in a Function because the types aren't class types, etc.).
There isn't a class in java.util.function for a functional interface with no arguments and no result, but Runnable can be used for that.
You need to make sure you use the correct interface.
Note: I was assuming method1 and method2 are static methods, so that they don't take any arguments, even a hidden "instance" argument that instance methods take. If they're instance methods, then things have to be done differently.
Now that you've clarified that they're instance methods, things are different--but it depends on how you get the method. If you say
Word::incListenCorrect
since you're using the class name, you need to provide the instance as an argument. Therefore, Word::incListenCorrect returns a functional interface for a method that takes one argument, such as Consumer<Word>, and you have to pass the Word as the argument when you call the method with .accept(). But:
word::incListenCorrect
is very different. Now, the word instance becomes "baked into" the method reference, so it doesn't need to be passed as an argument. In this case, therefore, you'll still need the interface that takes no arguments and does not return a value, which is Runnable. When you say
Runnable r = word::incListenCorrect;
r.run();
where r is a Runnable, it will automatically use word as the instance for the instance method, since word became part of r when you assigned the method reference to it.

Differences in type inference JDK8 javac/Eclipse Luna?

I'm trying to switch a project to Java8, and encounter odd differences between Eclipse Luna and javac's type inference. With JDK 1.7.0_65 javac this code compiles just fine. JDK 1.8.0_11 complains that both toString(char[]) and toString(Throwable) match for the "toString(getKey(code, null));" line. Eclipse Luna 4.4 (I20140606-1215) compiles it happily with either JDK:
public class TypeInferenceTest {
public static String toString(Object obj) {
return "";
}
public static String toString(char[] ca) {
return "";
}
public static String toString(Throwable t) {
return "";
}
public static <U> U getKey(Object code, U defaultValue) {
return defaultValue;
}
public static void test() {
Object code = "test";
toString(getKey(code, null));
}
}
I think the only signature that could possibly match is toString(Object).
Of course I could simply add a cast to Object, but I wonder why javac can't infere the type by itself (while eclipse does), and why the heck javac considers Throwable and char[] suitable matches, but not Object.
Is this a bug in Eclipse or javac? (I mean only one compiler can be right here, either it compiles or it doesn't)
Edit: Error message from javac (JDK8):
C:\XXXX\Workspace\XXXX\src>javac -cp . TypeInferenceTest.java
TypeInferenceTest.java:22: error: reference to toString is ambiguous
toString(getKey(code, null));
^
both method toString(char[]) in TypeInferenceTest and method toString(Throwable) in TypeInferenceTest match
1 error
Compilers can only inspect the method signatures, not the method body, so that part is irrelevant.
This "reduces" your code to (psuedocode):
public class TypeInferenceTest {
public static String toString(Object obj);
public static String toString(char[] ca);
public static String toString(Throwable t);
public static <U> U getKey(Object code, U defaultValue);
public static void test() {
Object code = "test";
toString(getKey(code, null));
}
}
Also note that the <U> U getKey(...) really is: <U extends Object> U getKey(...).
All it knows that getKey(code, null) returns is: ? extends Object, so it returns a subtype of Object, or an Object itself.
There are three signatures that match, namely Object, char[] and Throwable, where both char[] and Throwable match equally and better than Object, because you asked for an ? extends Object.
So it cannot choose which is the correct one, because all three match the signature.
When you change it to:
public static Object getKey(Object code, Object defaultValue);
then only public static String toString(Object obj); matches, because it matches better as any other ? extends Object that is not equal to Object.
Edit, I looked over the original intent of the question: Why does it compile in Java 7, but not in Java 8?
In Java 8 type inference got greatly improved.
Whereas in Java 7 it could for example only infer that getKey returned an Object, it now in Java 8 infers that it returns an ? extends Object.
When using Java 7 there was only one match, namely Object.
To have the change visualized even better, consider this piece of code:
public class TypeInferenceTest {
public static String toString(Object obj) { return "1"; }
public static String toString(Throwable t) { return "2"; }
public static <U> U getKey(Object code, U defaultValue) { return defaultValue; }
public static void test() {
Object code = "test";
String result = toString(getKey(code, null));
System.out.println(result);
}
public static void main(String[] args) {
test();
}
}
On Java 7 it prints 1, on Java 8 it prints 2, exactly because of the reasons I have outlined above.
javac may actually be correct. The spec writes:
The null type has one value, the null reference, represented by the null literal null, which is formed from ASCII characters.
Therefore, the type of null is the null type.
The expression getKey(code, null) is a method invocation expression of a generic method. The spec defines its type as follows:
If the chosen method is generic and the method invocation does not provide explicit type arguments, the invocation type is inferred as specified in §18.5.2.
The actual description of the type inference algorithm is rather involved, but the type inferred for U must be assignable from the null type. Alas, this is true for all reference types, so which one to choose? The most logical one is the most specific such type, which is the null type. Therefore, the type of the method invocation expression probably is the null type.
Now, which method does the method invocation expression toString(getKey(code, null)) refer to? The spec writes:
The second step searches the type determined in the previous step for member methods. This step uses the name of the method and the argument expressions to locate methods that are both accessible and applicable, that is, declarations that can be correctly invoked on the given arguments.
There may be more than one such method, in which case the most specific one is chosen. The descriptor (signature plus return type) of the most specific method is the one used at run time to perform the method dispatch.
Since the type of the argument is the null type, all three toString methods are applicable. The spec writes:
A method is said to be maximally specific for a method invocation if it is accessible and applicable and there is no other method that is applicable and accessible that is strictly more specific.
If there is exactly one maximally specific method, then that method is in fact the most specific method; it is necessarily more specific than any other accessible method that is applicable. It is then subjected to some further compile-time checks as specified in §15.12.3.
It is possible that no method is the most specific, because there are two or more methods that are maximally specific. In this case:
If all the maximally specific methods have override-equivalent signatures (§8.4.2), then:
If exactly one of the maximally specific methods is concrete (that is, non-abstract or default), it is the most specific method.
Otherwise, if all the maximally specific methods are abstract or default, and the signatures of all of the maximally specific methods have the same erasure (§4.6), then the most specific method is chosen arbitrarily among the subset of the maximally specific methods that have the most specific return type.
In this case, the most specific method is considered to be abstract. Also, the most specific method is considered to throw a checked exception if and only if that exception or its erasure is declared in the throws clauses of each of the maximally specific methods.
Otherwise, the method invocation is ambiguous, and a compile-time error occurs.
Both toString(char[]) and toString(Throwable) are more specific that toString(Object), but neither is more specific than the other, nor are their signatures override-equivalent.
Therefore, the method invocation is ambiguous, and rejected by the compiler.

How to specify function types for void (not Void) methods in Java8?

I'm playing around with Java 8 to find out how functions as first class citizens. I have the following snippet:
package test;
import java.util.*;
import java.util.function.*;
public class Test {
public static void myForEach(List<Integer> list, Function<Integer, Void> myFunction) {
list.forEach(functionToBlock(myFunction));
}
public static void displayInt(Integer i) {
System.out.println(i);
}
public static void main(String[] args) {
List<Integer> theList = new ArrayList<>();
theList.add(1);
theList.add(2);
theList.add(3);
theList.add(4);
theList.add(5);
theList.add(6);
myForEach(theList, Test::displayInt);
}
}
What I'm trying to do is pass method displayInt to method myForEach using a method reference. To compiler produces the following error:
src/test/Test.java:9: error: cannot find symbol
list.forEach(functionToBlock(myFunction));
^
symbol: method functionToBlock(Function<Integer,Void>)
location: class Test
src/test/Test.java:25: error: method myForEach in class Test cannot be applied to given ty
pes;
myForEach(theList, Test::displayInt);
^
required: List<Integer>,Function<Integer,Void>
found: List<Integer>,Test::displayInt
reason: argument mismatch; bad return type in method reference
void cannot be converted to Void
The compiler complains that void cannot be converted to Void. I don't know how to specify the type of the function interface in the signature of myForEach such that the code compiles. I know I could simply change the return type of displayInt to Void and then return null. However, there may be situations where it's not possible to alter the method I want to pass somewhere else. Is there an easy way to reuse displayInt as it is?
You are trying to use the wrong interface type. The type Function is not appropriate in this case because it receives a parameter and has a return value. Instead you should use Consumer (formerly known as Block)
The Function type is declared as
interface Function<T,R> {
R apply(T t);
}
However, the Consumer type is compatible with that you are looking for:
interface Consumer<T> {
void accept(T t);
}
As such, Consumer is compatible with methods that receive a T and return nothing (void). And this is what you want.
For instance, if I wanted to display all element in a list I could simply create a consumer for that with a lambda expression:
List<String> allJedi = asList("Luke","Obiwan","Quigon");
allJedi.forEach( jedi -> System.out.println(jedi) );
You can see above that in this case, the lambda expression receives a parameter and has no return value.
Now, if I wanted to use a method reference instead of a lambda expression to create a consume of this type, then I need a method that receives a String and returns void, right?.
I could use different types of method references, but in this case let's take advantage of an object method reference by using the println method in the System.out object, like this:
Consumer<String> block = System.out::println
Or I could simply do
allJedi.forEach(System.out::println);
The println method is appropriate because it receives a value and has a return type void, just like the accept method in Consumer.
So, in your code, you need to change your method signature to somewhat like:
public static void myForEach(List<Integer> list, Consumer<Integer> myBlock) {
list.forEach(myBlock);
}
And then you should be able to create a consumer, using a static method reference, in your case by doing:
myForEach(theList, Test::displayInt);
Ultimately, you could even get rid of your myForEach method altogether and simply do:
theList.forEach(Test::displayInt);
About Functions as First Class Citizens
All been said, the truth is that Java 8 will not have functions as first-class citizens since a structural function type will not be added to the language. Java will simply offer an alternative way to create implementations of functional interfaces out of lambda expressions and method references. Ultimately lambda expressions and method references will be bound to object references, therefore all we have is objects as first-class citizens. The important thing is the functionality is there since we can pass objects as parameters, bound them to variable references and return them as values from other methods, then they pretty much serve a similar purpose.
When you need to accept a function as argument which takes no arguments and returns no result (void), in my opinion it is still best to have something like
public interface Thunk { void apply(); }
somewhere in your code. In my functional programming courses the word 'thunk' was used to describe such functions. Why it isn't in java.util.function is beyond my comprehension.
In other cases I find that even when java.util.function does have something that matches the signature I want - it still doesn't always feel right when the naming of the interface doesn't match the use of the function in my code. I guess it's a similar point that is made elsewhere here regarding 'Runnable' - which is a term associated with the Thread class - so while it may have he signature I need, it is still likely to confuse the reader.
Set return type to Void instead of void and return null
// Modify existing method
public static Void displayInt(Integer i) {
System.out.println(i);
return null;
}
OR
// Or use Lambda
myForEach(theList, i -> {System.out.println(i);return null;});

When I pass a null, which overloaded function will java run

So i can pass nulls into functions in java. I can also overload functions in java. But consider the following
public static void main(String ... args){
doStuff(null);
}
public static void doStuff(String s){
solveWorldHunger();
}
public static void doStuff(Integer i){
nukeCanada();
}
public static void nukeCanada(){
System.out.println("NO!");
}
public static void solveWorldHunger(){
System.out.println("YAY!");
}
The previous program will always print out YAY no matter what the order of the sorce code...
Can anyone shed some light onto why the jvm consitently decides to run the solveWorldHunger function over the nukeCanada function`?
It's quite clear to the compiler that you can't store null in a primitive int. So, it decides to go with the method which has String as argument.
However, when you change your 2nd method to take Integer as argument, then you will get compiler error. Because both of them are eligible to be invoked with null argument. So, there will be ambiguity.
So, try changing your 2nd method: -
public static void doStuff(String s){
solveWorldHunger();
}
public static void doStuff(Integer i){ // Integer instead of `int`
nukeCanada();
}
And invoke it on null. You will see the compiler error.
So, in that case, you can invoke the appropriate method using typecasting like this: -
doStuff((Integer)null); // Calls Integer version
doStuff((String)null); // Calls String version
Also, note that, if you have your 2nd method take a parameter that is a super type of String, like Object, then there would be no ambiguity, because compiler will now choose the most specific one, i.e., String argument.
So, ambiguity only occurs, when you have two methods with types that are not in the same inheritance hierarchy.
Only your doStuff(String) method can take a NULL argument... the primitive int can never be null. If you had a second method overload that passed an object, you would no longer be able to pass null as a parameter for that method.

Polymorphism and method overloading

I have a quick and straighforward question:
I have this simple class:
public class A
{
public void m(Object o)
{
System.out.println("m with Object called");
}
public void m(Number n)
{
System.out.println("m with Number called");
}
public static void main(String[] args)
{
A a = new A();
// why will m(Number) be called?
a.m(null);
}
}
UPDATE: actually is method with Number actually being called. Sorry about the confusion.
If I call a.m(null) it calls method with Number parameter.
My question is: why is this? where in the java language specification is this specified?
First of all, it actually calls m(Number).
It happens because both methods are applicable, but m(Number) is the most specific method, since any argument of m(Number) can be passed to m(Object), but not vice versa.
If you replace m(Object) by m(String) (or add another method such as m(Date)), compiler would report ambiguity, since the most specific method can't be identified.
See the section Choosing the Most Specific Method in the Java Specification.
This is not polymorphism or overriding. This is method overloading.
I tested this and specific method is being called (not the m(Object)) and according to the spec the specific method is always called. Which overload will get selected for null in Java?
another related question for you to think about:
public static void main(String[] args)
{
A a = new A();
Object n = new Integer(1);
a.m(n); // which method will be called?
}
My 2 cents. Method with Number argument is the one that is called, Because Number extends Object. I had a similar situation in the past, I did override a method and put Component instead of JComponent (by mistake). It took me one week to find out the reason why my method was never called. I figure it out, that if there are some inheritance relationship between the overloaded methods, the JVM matches first the deeper one in the class hierarchy.
Object is the default type in Java. If you refactor your m(Object o) method to m(String o) you'll have a compile time error saying that the call m(null) is ambiguous because Java cannot determine which class between String and Number defaults to null
Other than that, between m(Object o) and m(Number o), calling m(null) will call m(Number o) because it's the most specialized method. You would need to cast null into an Object (or anything not an instance of Number) otherwise.
a.m((String) null);

Categories