Why Java Supports Method Overloading

  • 2021-09-16 07:08:46
  • OfStack

Why does Java support method overloading

Why use overloading? Instead of changing one method name to a different one.

One important feature of any programming language is name. When you create an object, you will give the memory space allocated to this object a name. A method is the name of a behavior. Refer to all kinds of objects, properties and methods by name. Good naming can make the system easy to understand and modify.

Mapping subtle differences in human languages into programming languages will cause one problem. Usually, the same words can express many different meanings-they are "overloaded". This is especially useful when the difference in meaning is small.

You will say "clean the shirt", "clean the car" and "clean the dog". It would seem foolish to insist on saying, "Wash your shirt the way you wash your shirt", "Wash your car the way you wash your dog" and "Wash your dog the way you wash your dog", because the audience doesn't need to distinguish between actions at all. Most human languages are "redundant", so even if you miss a few words, you can understand the meaning. You don't need to use different words for each concept-you can infer the meaning from the context.

Most programming languages (especially C) require that each method (often referred to as a function in these languages) be provided with a one-but-no-two identifier. So, you can't have one print() Functions can print both integer and floating-point types-each function name must be different.

But in Java (C + +), there is another factor that makes it necessary to use method overloads: constructors. Because the constructor method name must be the same as the class name, there will only be one constructor name in one class.
So how do you create an object in different ways? For example, if you want to create a class, this class is initialized in two ways: one is standardized, and the other is to read information from a file. You need two constructors: a parameterless constructor and a constructor with an String type parameter that passes in the file name. The two constructors have the same name-the same as the class name. Therefore, method overloading is necessary, which allows methods to have the same method name but receive different parameters. Although method overloading is important for constructors, you can easily overload any method.

Overloading constructors and methods:


class Tree {
    int height;
    Tree() {
        System.out.println("Planting a seedling");
        height = 0;
    }
    Tree(int initialHeight) {
        height = initialHeight;
        System.out.println("Creating new Tree that is " + height + " feet tall");
    }
    void info() {
        System.out.println("Tree is " + height + " feet tall");
    }
    void info(String s) {
        System.out.println(s + ": Tree is " + height + " feet tall");
    }
}

public class Overloading {
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            Tree t = new Tree(i);
            t.info();
            t.info("overloaded method");
        }
        new Tree(); 
    }
}

An Tree object can be either a sapling, using a parametric constructor, or a tree that has grown up in a greenhouse and has a fixed height, which requires a parametric constructor.

You may want to call in a variety of ways info() . For example, if you want to print additional messages, you can use the info(String) Method. If you have nothing to say, you can use info() Method. It seems strange to define exactly the same concept with two names, but with method overloading, you can define one concept with one name.

Distinguish overloaded methods

If two methods are named the same, how does Java know which one you are calling?
There is a simple rule: every overloaded method must have a parameter list with only 1 but no 2.

There is no way to distinguish two methods with the same name except by different parameter lists. You can even distinguish different methods according to the order of parameters in the parameter list, although this will make the code difficult to maintain.

Overloading and primitive types

Basic types can be automatically changed from small types to large types. When this is combined with overloading, it can be a bit confusing:


public class PrimitiveOverloading {
    void f1(char x) {
        System.out.print("f1(char)");
    }
    void f1(byte x) {
        System.out.print("f1(byte)");
    }
    void f1(short x) {
        System.out.print("f1(short)");
    }
    void f1(int x) {
        System.out.print("f1(int)");
    }
    void f1(long x) {
        System.out.print("f1(long)");
    }
    void f1(float x) {
        System.out.print("f1(float)");
    }
    void f1(double x) {
        System.out.print("f1(double)");
    }
    void f2(byte x) {
        System.out.print("f2(byte)");
    }
    void f2(short x) {
        System.out.print("f2(short)");
    }
    void f2(int x) {
        System.out.print("f2(int)");
    }
    void f2(long x) {
        System.out.print("f2(long)");
    }
    void f2(float x) {
        System.out.print("f2(float)");
    }
    void f2(double x) {
        System.out.print("f2(double)");
    }
    void f3(short x) {
        System.out.print("f3(short)");
    }
    void f3(int x) {
        System.out.print("f3(int)");
    }
    void f3(long x) {
        System.out.print("f3(long)");
    }
    void f3(float x) {
        System.out.print("f3(float)");
    }
    void f3(double x) {
        System.out.print("f3(double)");
    }
    void f4(int x) {
        System.out.print("f4(int)");
    }
    void f4(long x) {
        System.out.print("f4(long)");
    }
    void f4(float x) {
        System.out.print("f4(float)");
    }
    void f4(double x) {
        System.out.print("f4(double)");
    }
    void f5(long x) {
        System.out.print("f5(long)");
    }
    void f5(float x) {
        System.out.print("f5(float)");
    }
    void f5(double x) {
        System.out.print("f5(double)");
    }
    void f6(float x) {
        System.out.print("f6(float)");
    }
    void f6(double x) {
        System.out.print("f6(double)");
    }
    void f7(double x) {
        System.out.print("f7(double)");
    }
    void testConstVal() {
        System.out.print("5: ");
        f1(5);f2(5);f3(5);f4(5);f5(5);f6(5);f7(5);
        System.out.println();
    }
    void testChar() {
        char x = 'x';
        System.out.print("char: ");
        f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
        System.out.println();
    }
    void testByte() {
        byte x = 0;
        System.out.print("byte: ");
        f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
        System.out.println();
    }
    void testShort() {
        short x = 0;
        System.out.print("short: ");
        f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
        System.out.println();
    }
    void testInt() {
        int x = 0;
        System.out.print("int: ");
        f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
        System.out.println();
    }
    void testLong() {
        long x = 0;
        System.out.print("long: ");
        f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
        System.out.println();
    }
    void testFloat() {
        float x = 0;
        System.out.print("float: ");
        f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
        System.out.println();
    }
    void testDouble() {
        double x = 0;
        System.out.print("double: ");
        f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
        System.out.println();
    }

    public static void main(String[] args) {
        PrimitiveOverloading p = new PrimitiveOverloading();
        p.testConstVal();
        p.testChar();
        p.testByte();
        p.testShort();
        p.testInt();
        p.testLong();
        p.testFloat();
        p.testDouble();
    }
}

Output:

5: f1(int)f2(int)f3(int)f4(int)f5(long)f6(float)f7(double)
char: f1(char)f2(int)f3(int)f4(int)f5(long)f6(float)f7(double)
byte: f1(byte)f2(byte)f3(short)f4(int)f5(long)f6(float)f7(double)
short: f1(short)f2(short)f3(short)f4(int)f5(long)f6(float)f7(double)
int: f1(int)f2(int)f3(int)f4(int)f5(long)f6(float)f7(double)
long: f1(long)f2(long)f3(long)f4(long)f5(long)f6(float)f7(double)
float: f1(float)f2(float)f3(float)f4(float)f5(float)f6(float)f7(double)
double: f1(double)f2(double)f3(double)f4(double)f5(double)f6(double)f7(double)

If the parameter type passed in is larger than the parameter type expected to be received by the method, you must first make a narrowing conversion, otherwise the compiler will report an error.

Overload of return value

People often wonder, "Why can't methods be distinguished only by class names and parameter lists, but by their return values?" . For example, the following two methods have the same name and parameters, but they are easy to distinguish:


void f(){}
int f() {return 1;}

In some cases, the compiler can easily infer exactly which method to call from the context, such as int x = f() .

However, you can call 1 method and ignore the return value. This is called a side effect of calling a function, because you don't care about the return value, you just want to do something with the method. So if you call directly f() The Java compiler doesn't know which method you want to call, and the reader doesn't know so. For this reason, you can't distinguish overloaded methods according to the return value type. To support the new features, Java 8 improves the accuracy of guesses in a number of specific situations, but generally it doesn't work.


Related articles: