Method overloading with both static and non-static methods - java

As I've learned, in Java method overloading, we use same name for all overloaded methods. And also, their return type is not a matter. But what happens if we use same method as static and non-static form, as in the below example? Can we consider this method overloading?
class Adder {
static int add(int a, int b) {
return a + b;
}
int add(int a, int b, int c) {
return a + b + c;
}
}
class Test {
public static void main(String[] args) {
Adder a1 = new Adder();
System.out.println(Adder.add(11, 11));
System.out.println(a1.add(11, 11, 51));
}
}
I read some articles, but they didn't clarify my question.

Use of keyword static doesn't make a difference in method overloading.
Your code compiles because the method signature of both add() methods are different (2 params vs 3 params).
However, if you were to write something like this, then it would result in a compilation error.
class Adder {
static int add(int a, int b) {
return a + b;
}
int add(int a, int b) {
return a + b;
}
}

Yes they can overload each other. See this JLS :
If two methods of a class (whether both declared in the same class, or
both inherited by a class, or one declared and one inherited) have the
same name but signatures that are not override-equivalent, then the
method name is said to be overloaded.
See this Thread .

U have two methods one is static and another is non static.. so this is not overloading... Because both methods get stored in memory saperately...

Related

Does method overloading implicitly typecasts to larger type even though compatible type is available [duplicate]

This question already has answers here:
Inheritance and Overloading methods with different argument data types in Java
(2 answers)
Closed 3 years ago.
When I execute below program since child class has compatible methods call should have gone to child class but instead parent class methods are called. Is there any rule in overloading which is causing this behaviour ?
public class OverrideTest {
public static void main(String[] args) {
Parent d=new Child();
d.test(10);
d.add(1,2,3);
}
}
class Parent{
void test(double d) {
System.out.println("Value of D:"+ d);
}
public void add(double a, double b, double c){
double sum = a+b+c;
System.out.println("sum Double:"+ sum);
}
}
class Child extends Parent{
void test(int i) {
System.out.println("i:"+ i);
}
public void add(int a, int b, int c){
int sum = a+b+c;
System.out.println("sum Int:"+ sum);
}
}
The method to invoke is chosen at compile time. The compiler only considers methods which exist on the type of the variable, i.e. Parent, because all it knows is that d is a Parent.
Since it only knows about test(double) and add(double,double,double), these are the methods which will be invoked. Because they are not overridden in the child class (only overloaded), the methods from the parent class are invoked.
The compiler automatically widens the int parameters to double to make them compatible with the method's formal parameter types.
The fact that d is more specifically a Child at runtime is not used.

type checking and method lookup

I'm confused about the functionality of type checking and method lookup in Java.
From what I understand, type checking is done at the compile time and method lookup is done at the run time.
Type checking is based on the declared type of the reference object whereas method lookup is based on the actual type of the reference.
So suppose the class MyInt is a superclass of the class GaussianInt as follows:
class MyInt
{
private int n;
public myInt(int n)
{
this.n = n;
}
public int getval()
{
return n;
}
public void increment(int n)
{
this.n += n;
}
public myInt add(myInt N)
{
return new myInt(this.n + N.getval());
}
public void show()
{
System.out.println(n);
}
}
class GaussInt extends MyInt
{
private int m; //represents the imaginary part
public GaussInt(int x, int y)
{
super(x);
this.m = y;
}
public void show()
{
System.out.println( "realpart is: " + this.getval() +" imagpart is: " + m);
}
public int realpart()
{
return getval();
}
public int imagpart()
{
return m;
}
public GaussInt add(GaussInt z)
{
return new GaussInt(z.realpart() + realpart(), z.imagpart() + imagpart());
}
And suppose in the main method we have the following:
GaussInt z = new GaussInt(3,4);
MyInt b = z;
MyInt d = b.add(b)
System.out.println("the value of d is:"+ d.show());
Which add method would be used in the show statement inside the print statement in the end?
From what I understand, b is declared to be MyInt, but it is, in fact, GuaussInt. The type checker only sees that b is of MyInt type and that it has add(MyInt) so the code makes sense and compiles.
But then in run time, the method lookup sees that b is of type GaussInt and it has two add() methods, so it will use add(GaussInt) method by looking at method signature and it produces a GaussInt. But d is of type MyInt and method lookup will think it won't work, then will it go back to add(Myint)?
How does the mechanism behind compiling and running of a program work?
From what I understand, b is declared to be MyInt, but it is, in fact,
GaussInt
You are CORRECT. b's reference type is MyInt but it is pointing to an object of GaussInt type.
But then in run time, the method lookup sees that b is of type
GaussInt and it has two add() methods, so it will use add(GaussInt)
method by looking at method signature and it produces a GaussInt. But
d is of type GaussInt and method lookup will think it won't work, then
will it go back to add(Myint)?
As the add method in GaussInt takes a reference of GaussInt type and not of MyInt type. So b.add(b) will call add method of MyInt type. Since the gaussInt has two add methods one take the argument of type MyInt and other takes the argument GaussInt type. So it will call add method of myInt(superclass).
The thing you are trying to achieve is method overriding. For it to work the method signatures should be same. That is, the parent and child class methods should match in every respect, except that the return type of child class method can be subtype of the return type of parent class method
SO in order to achieve what you have mentioned, that is b.add(b) should call add method of gaussInt, make the argument type of add method in both classes same.
Also what you should learn about is dynamic polynorphism(run time check) and static polymorphism(compile time type check).

Avoid code duplication over classes

I am writing some classes and all of them implement a certain method they inherit from an interface. This method is close to the same for all the classes beside one call to a certain other function.
For example:
public void doSomething(){
int a = 6;
int b = 7;
int c = anOtherMethod(a,b);
while(c < 50){
c++;
}
}
What if multiple classes have the function doSomething() but the implementation of the method anOtherMethod() is different?
How do I avoid code duplication in this situation? (This is not my actual code but a simplified version that helps me describe what I mean a bit better.)
This looks like a good example of the template method pattern.
Put doSomething in a base class.
Declare abstract protected anotherMethod in that base class as well, but don't provide an implementation.
Each subclass then provides the proper implementation for anotherMethod.
This is how you could implement the technique that Thilo talked about in the following demo:
Main class:
public class Main extends Method {
public static void main(String[] args) {
Method m = new Main();
m.doSomething();
}
#Override
public int anOtherMethod(int a, int b) {
return a + b;
}
}
Abstact class:
public abstract class Method {
public abstract int anOtherMethod(int a, int b);
public void doSomething() {
int a = 6;
int b = 7;
int c = anOtherMethod(a, b);
System.out.println("Output: "+c);
}
}
This way, all you have to do is override anOtherMethod() in each class that you want to use doSomething() with a different implementation of the method anOtherMethod().
Assuming every version of anOtherFunction takes two integers and returns an integer, I would just have the method accept a function as an argument, making it Higher Order.
A function that takes two arguments of the same type and returns an object of the same type is known as a BinaryOperator. You can add a argument of that type to the method to pass a function in:
// Give the method an operator argument
public void doSomething(BinaryOperator<Integer> otherMethod) {
int a = 6;
int b = 7;
// Then use it here basically like before
// "apply" is needed to call the passed function
int c = otherMethod.apply(a,b);
while(c < 50)
c++;
}
}
How you use it though will depend on your use case. As a simple example using a lambda, you can now call it like:
doSomething((a, b) -> a + b);
Which simply returns the sum of a and b.
For your particular case though, you may find that having doSomething as part of a Interface isn't necessary or optimal. What if instead, anOtherMethod is what's required to be supplied? Instead of expecting your classes to supply a doSomething, have them supply a BinaryOperator<Integer>. Then, when you need to get results from doSomething, get the operator from the class, then pass it to doSomething. Something like:
public callDoSomething(HasOperator obj) {
// There may be a better way than having a "HasOperator" interface
// This is just an example though
BinaryOperator<Integer> f = obj.getOperator();
doSomething(f);
}

The relationship of overload and method return type in Java?

If there are two methods, they have different parameters, and their return types are different. Like this:
int test(int p) {
System.out.println("version one");
return p;
}
boolean test(boolean p, int q) {
System.out.println("version two");
return p;
}
If the return types are same, of course this is overload. But since the return types are different, can we regard this as overload still?
To quote the official tutorial:
The Java programming language supports overloading methods, and Java can distinguish between methods with different method signatures. This means that methods within a class can have the same name if they have different parameter lists (there are some qualifications to this that will be discussed in the lesson titled "Interfaces and Inheritance").
Having a different return type is inconsequential to overloading. In fact, this is quite common with methods that return one of their arguments. E.g., java.util.Math has a bunch of overloaded max methods. A max of two ints return an int, a max of two doubles return a double, etc.
consider following points for overloading:
First and important rule to overload a method in java is to change method signature. Method signature is made of number of arguments, type of arguments and order of arguments if they are of different types.
public class DemoClass {
// Overloaded method
public Integer sum(Integer a, Integer b) {
return a + b;
}
// Overloading method
public Integer sum(Float a, Integer b) { //Valid
return null;
}
}
Return type of method is never part of method signature, so only changing the return type of method does not amount to method overloading.
public class DemoClass {
// Overloaded method
public Integer sum(Integer a, Integer b) {
return a + b;
}
// Overloading method
public Float sum(Integer a, Integer b) { //Not valid; Compile time error
return null;
}
}
Thrown exceptions from methods are also not considered when overloading a method. So your overloaded method throws the same exception, a different exception or it simply does no throw any exception; no effect at all on method loading.
public class DemoClass {
// Overloaded method
public Integer sum(Integer a, Integer b) throws NullPointerException{
return a + b;
}
// Overloading method
public Integer sum(Integer a, Integer b) throws Exception{ //Not valid; Compile time error
return null;
}
}
Yes, this is also an overload. Since only the name and the list of parameters are considered part of method's signature for the purposes of method overloading, both your test methods are overloads of each other.
There may be useful scenarios for overloading a method like that, too. Consider this example:
class Sanitizer {
public static String sanitize(String s) {
...
}
public static int sanitize(int s) {
...
}
public static double sanitize(double s) {
...
}
}
A programmer who uses Sanitizer can write things like
String s2 = Sanitizer.sanitize(s1);
int num2 = Sanitizer.sanitize(num1);
and the overload makes the code looks the same for variables of different types.
In function overloading return types don't play any role.
Function overloading can only be achieved via change in arguments.
So, yes in your given case test() is overloaded

Overloading Java Method from Inherited Interface

Question:
I have the following:
interface A
{
int MethodA(int x, int y);
}
and
interface B extends A
{
//This is meant to overload MethodA
int MethodA(int x, int y, int z);
}
The problem comes when I try to implement interface B, and run the method in main.
class Foo implements B
{
//For interface B
public int MethodA(int x, int y, int z)
{
//Actual implementation
}
//For interface A
public int MethodA(int x, int y)
{
//Actual implementation
}
}
public static void main(String[] s)
{
Foo foo = new Foo();
//Problem occurs here
foo.MethodA(1, 2, 3);
}
Eclipse will complain and say that "The method MethodA(int, int, int) in the type A is not applicable for the arguments (int, int)."
But why? I've already implemented interface B. Shouldn't MethodA(int, int, int) have overload MethodA(int, int), making MethodA able to accept three integers as well?
The above looks a little confused.
You need to specify your return types, specify names for each argument (even in the interface) and declare the implemented methods as public eg.
public int MethodA(int a, int b, int c)
{
//Actual implementation e.g.
return 0;
}
Your static main() method has to reside within a class (e.g. the Foo class above), and finally call the method with real arguments.
Once you've done that, then all should be good. You can certainly provide overloading as in the above. You just need to resolve the more basic issues first. I would get a very basic single method going, and then enhance from there in order to get something working.

Categories

Resources