Overloaded Methods and AutoboxingUnboxing

################## key points extracted ###########################

The rule for a method invocation that uses autoboxing/unboxing follows a two-step process.

If the actual argument being passed is a primitive type (as in test(10)),
Try to find a method with the primitive type argument. If there is no exact match, try widening the primitive type to find a match.
If the previous step fails, box the primitive type and try to find a match.
If the actual argument being passed is a reference type (as in test(new Integer(101)),
Try to find a method with the reference type argument. If there is match, call that method. In this case, a match does not have to be exact. It should follow the subtype and super type assignment rule.
If the previous step fails, unbox the reference type to the corresponding primitive type and try to find an exact match, or widen the primitive type and find a match.

#####################################################################

Overloaded Methods and Autoboxing/Unboxing

You have a few surprises when you call an overloaded method and want to rely on autoboxing/unboxing feature. Suppose you have two methods in a class.

public void test(Integer iObject) {
System.out.println("Integer=" + iObject);
}

public void test(int iValue) {
System.out.println("int=" + iValue);
}

Suppose you make two calls to the test() method.

test(101);
test(new Integer(101));

Which of the following will be the output?

int=101
Integer=101

or

Integer=101
int=101

The rule for a method invocation that uses autoboxing/unboxing follows a two-step process.

If the actual argument being passed is a primitive type (as in test(10)),
Try to find a method with the primitive type argument. If there is no exact match, try widening the primitive type to find a match.
If the previous step fails, box the primitive type and try to find a match.
If the actual argument being passed is a reference type (as in test(new Integer(101)),
Try to find a method with the reference type argument. If there is match, call that method. In this case, a match does not have to be exact. It should follow the subtype and super type assignment rule.
If the previous step fails, unbox the reference type to the corresponding primitive type and try to find an exact match, or widen the primitive type and find a match.

If you apply these rules to the above snippet of code, it will print

int=101
Integer=101

Suppose you have two test() methods.

public void test(Integer iObject) {
System.out.println("Integer=" + iObject);
}

public void test(long iValue) {
System.out.println("long=" + iValue);
}

What will be printed if you use the following code?

test(101);
test(new Integer(101));

It will print

long=101
Integer=101

The first call of test(101) will try to find an exact match for an int argument. It does not find a method test(int), so it widens the int data type, finds a match test(long), and calls this method.

Suppose you have two test() methods.

public void test(Long lObject) {
System.out.println("Long=" + lObject);
}

public void test(long lValue) {
System.out.println("long=" + lValue);
}

What will be printed if you execute the following code?

test(101);
test(new Integer(101));

It will print

long=101
long=101

Are you surprised by looking at the above output? Apply the rules that I have listed and you will find that the above output followed those rules. The call to test(101) is clear because it widens 101 from int to long and executes the test(long) method. To call test(new Integer(101)), it looks for a method test(Integer) and it does not find one. Note that a reference type is never widened. That is, an Integer is never widened to Long. Therefore, it unboxes the Integer to int and looks for test(int) method, which it does not find. Now, it widens the int and finds test(long) and executes it.

I have one more surprise. Consider the following two test() methods:

public void test(Long lObject) {
System.out.println("Long=" + lObject);
}

public void test(Object obj) {
System.out.println("Object=" + obj);
}

What will be printed when you execute the following code?

test(101);
test(new Integer(101));

This time, you will get the following output:

Object=101
Object=101

Does it make sense? Not really. Here is the explanation. When it calls test(101), it has to box int to an Integer, because there is no match for test(int), even after widening the int value. So, test(101) becomes test(Integer.valueOf(101)). Now it does not find any test(Integer) either. Note that Integer is a reference type and it inherits the Number class, which in turn inherits the Object class. Therefore, an Integer is always an Object, and Java allows you to assign an object of subtype (Integer) to a variable of supertype (Object). This is the reason that the test(Object) is called in this case. The second call, test(new Integer(101)), works the same way. It tries for test(Integer) method. When it does not find it, the next match for it is test(Object) based on the subtype and supertype assignment rule for reference types.

时间: 2024-08-15 20:44:01

Overloaded Methods and AutoboxingUnboxing的相关文章

kbmmw 5.0 beta1 发布

经过大半年的等待,kbmmw 的新版终于来了.经过近5年的打磨, kbmmw 的版本号升级到5了. kbmMW is a portable, highly scalable, high end application server and enterprise architecture integration (EAI) development framework for Win32, ..Net and Linux with clients residing on Win32, .Net, L

javascript 函数重载 overloading

函数重载 https://en.wikipedia.org/wiki/Function_overloading In some programming languages, function overloading or method overloading is the ability to create multiple methods of the same name with different implementations. Calls to an overloaded functi

Ref与Out的区别

Ref与Out的区别 ref和out都是C#中的关键字,所实现的功能也差不多,都是指定一个参数按照引用传递. 对于编译后的程序而言,它们之间没有任何区别,也就是说它们只有语法区别. 总结起来,他们有如下语法区别: 1.ref传进去的参数必须在调用前初始化,out不必,即: int i; SomeMethod( ref i );//语法错误 SomeMethod( out i );//通过 2.ref传进去的参数在函数内部可以直接使用,而out不可: public void SomeMethod(

Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(六)之Initialization & Cleanup

Two of these safety issues are initialization and cleanup. initialization -> bug cleanup -> running out of resources (most notably, memory) Java adopted the constructor, and in addition has a garbage collector that automoatically releases memory res

ref(C# 参考)

ref 关键字使参数按引用传递.其效果是,当控制权传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中.若要使用 ref 参数,则方法定义和调用方法都必须显式使用 ref 关键字.例如: class RefExample { static void Method(ref int i) { i = 44; } static void Main() { int val = 0; Method(ref val); // val is now 44 } } 传递到 ref 参数的参数必须最先

How to Write Doc Comments for the Javadoc Tool

http://www.oracle.com/technetwork/java/javase/documentation/index-137868.html This document describes the style guide, tag and image conventions we use in documentation comments for Java programs written at Java Software, Oracle. It does not rehash r

java函数方法

1.方法重载 (1)源代码 // MethodOverload.java // Using overloaded methods public class MethodOverload { public static void main(String[] args) { System.out.println("The square of integer 7 is " + square(7)); System.out.println("\nThe square of doubl

Java语言第四讲

1.纯随机数发生器 Xn+1=(aXn + c)mod m Modulus=2^31-1=int.MaxValue Multiplier=7^5=16807 C=0 当显示过2^31-2个数之后,才可能重复. 动手动脑: 编写一个方法,使用以上算法生成指定数目(比如1000个)的随机整数. package 纯随机数; public class Suiji { private static final int N = 200; private static final int LEFT = 40;

Java动手动脑(二)

1>类的对象实例化 由于main为静态类型,所以在调用函数时也必须调用静态方法,如上代码中的求平方数的静态方法,如何在静态main中调用非静态类的方法呢? 静态方法只能直接访问静态成员,无法访问非静态成员,如果想要访问费静态方法,则实例化该类对象,使用对象名.非静态方法()的方式来访问. 第一:创建类的对象 类名   对象名=new  类名( ); 第二:调用方法或变量 对象名.成员方法名(); 数据类型   变量名= 对象名.成员变量名; 2>编写一个方法,使用以上算法生成指定数目(比如10