📜  Java中自动装箱和扩展的方法重载

📅  最后修改于: 2020-03-31 01:27:02             🧑  作者: Mango

先决条件:方法重载自动装箱和拆箱
在Java中,有两种类型的变量:原始类型和引用类型。将原始类型转换为对应的包装对象称为自动装箱,将包装对象转换为对应的原始类型称为拆箱。

自动装箱方法重载

在方法重载中,您可能会遇到签名采用引用类型或原始类型作为形式参数的情况。编译器首先搜索具有相同数据类型参数的方法。如果您使用包装器类Object作为实际参数,并且编译器未找到具有相同引用类型(即类或接口类型)的参数的方法,则它将开始搜索具有对应参数的基本数据类型方法。

// Java展示自动装箱
// 解析参数类型:
// a)引用 b)原始类型
import java.io.*;
public class Conversion
{
    // 1.使用原始数据类型重载
    public void method(int i)
    {
        System.out.println("原始的int形参 :" + i);
    }
    // 使用引用形参重载
    public void method(Integer i)
    {
        System.out.println("引用为Integer的形参 :" + i);
    }
    // 2. overloaded method primitive formal argument
    // and to be invoked for wrapper Object as overloaded method
    // with wrapper object of same(Long) type as an argument is not
    // available.
    public void method(long i)
    {
        System.out.println("Primitive type long formal argument :" + i);
    }
}
class GFG
{
    public static void main (String[] args)
    {
        Conversion c = new Conversion();
        // invoking the method with different signature.
        c.method(10);
        c.method(new Integer(15));
        c.method(new Long(100));
        // Using short will give, argument mismatch;
        // possible lossy conversion from int to short
        // c.method(new Short(15));
    }
}

输出:

Primitive type int formal argument :10
Reference type Integer formal argument :15
Primitive type long formal argument :100

拓展方法重载

如果编译器未能找到与自动装箱相对应的任何方法,则它将开始搜索扩展后的原始数据类型的方法参数。
在下面的示例中,我们将使用具有原始数据类型与实际参数的数据类型相同的、带有原始(int)形式参数的重载方法。我们正在调用带有Long wrapper Object参数的另一种方法。编译器开始搜索具有相同引用类型(长包装类)的方法。由于没有方法具有Long包装器类的参数。因此,它搜索可以接受大于Long原始数据类型的参数作为参数的方法。在这种情况下,它将找到具有float基本数据类型的方法并调用它。

// Java展示拓展的方法重载
import java.io.*;
public class Conversion
{
    // 重载方法
    public void method(int i)
    {
        System.out.println("原始数据类型int形参 :" + i);
    }
    // 原始类型形参重载
    public void method(float i)
    {
        System.out.println("原始数据类型float形参 :" + i);
    }
}
class GFG
{
    public static void main (String[] args)
    {
        Conversion c = new Conversion();
        // 调用方法,此方法签名有拓展的参数类型
        c.method(10);
        c.method(new Long(100));
    }
}

输出:

原始数据类型int形参 :10
原始数据类型float形参 :100.0

方法重载与拓展和装箱在一起

如果拓展和装箱同时发生会怎样?编译器可以执行什么方法调用?
原始类型的扩展已优先于装箱boxing和var-args。但是原始类型的扩展和装箱不能一起使用。

// Java展示方法重载,拓展,装箱一起使用
import java.io.*;
public class Conversion
{
    // 重载方法使用引用形参
    public void method(Integer a)
    {
        System.out.println("原始数据类型byte形参 :" + a);
    }
}
class GFG
{
    public static void main (String[] args)
    {
        Conversion c = new Conversion();
        // 调用方法
        byte val = 5;
        c.method(val);
    }
}

输出:

25: error: incompatible types: byte cannot be converted to Integer
        c.method(val);
                 ^
 Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error

但是如果将其传递给Object类型的引用,则可以接受装箱后的拓展。为此,请参见以下示例。

// Java展示接受自动装箱后的拓展
import java.io.*;
public class Conversion
{
    // 重载方法,使用引用形参
    public void method(Object b)
    {
        // 对象b先被转换成Byte,之后被打印
        Byte bt = (Byte) b;
        System.out.println("数据类型为引用形参 :" + bt);
    }
}
class GFG
{
    public static void main (String[] args)
    {
        Conversion c = new Conversion();
        byte val = 5;
        // b先被拓展成Byte
        // 然后Byte被传递给Object.
        c.method(val);
    }
}

输出:

数据类型为引用形参 :5

使用Varargs参数的方法重载

基本类型的扩展比var-args具有更高的优先级。
例:

// Java使用var-args和拓展一起使用
import java.io.*;
public class Conversion
{
    // 重载方法原始类型(byte),使用var-args形参
    public void method(byte... a)
    {
        System.out.println("原始类型byte为形参:" + a);
    }
    // 重载方法,原始类型int形参
    public void method(long a, long b)
    {
        System.out.println("加宽long形参 :" + a);
    }
}
class GFG
{
    public static void main (String[] args)
    {
        Conversion c = new Conversion();
        // 调用方法,使用拓展原始类型参数
        byte val = 5;
        c.method(val,val);
    }
}

输出:

Widening type long formal argument :5