Overloading with Widening、Boxing and Var-args

2024-01-22 01:08

本文主要是介绍Overloading with Widening、Boxing and Var-args,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


区别不同函数的唯一标志是参数列表,重载的函数,它们的函数名相同,返回类型可以相同也可以不同,但它们的参数列表一定不能相同。与继承中的方法重写不同,重写的方法要求函数名和参数列表一定相同。


There are three factors that make overloading a little tricky:

(1) Widening

(2) Boxing

(3) Var-args


1. 自动提升时的规则

class EasyOver {static void go(short x) { System.out.print("short "); }static void go(int x) { System.out.print("int "); }static void go(long x) { System.out.print("long "); }static void go(double x) { System.out.print("double "); }public static void main(String [] args) {char c = 'a';byte b = 5;                                                                            short s = 5;long l = 5;float f = 5.0f;go(c);         //go(int)go(b);         //go(short)go(s);         //go(short)go(l);         //go(long)go(f);         //go(double)}
}

Which produces the output:



This probably isn't much of a surprise. 

In every case, when an exact match isn't found, the JVM uses the method with the smallest argument that is wider than the parameter.

char produces a slightly different effect, since if it do not find an exactchar match,it is promoted to int. char can not be promotedbyte and short whenever it is, it can be promotedlong,float and double if int does not exist.


2. Overloading with Boxing and Var-args

(1) overloading with boxing

class AddBoxing {static void go(Integer x) { System.out.println("Integer"); }static void go(long x) { System.out.println("long"); }public static void main(String [] args) {int i = 5;go(i); // which go() will be invoked?}
} 

Does the compiler think that widening a primitive parameter is more desirable than performing an autoboxing operation? The answer is that the compiler willchoose widening over boxing, so the output will be:
     


(2) overloading with var-args

class AddVarargs {static void go(long x, long y) { System.out.println("long,long");}static void go(byte... x) { System.out.println("byte... "); }       public static void main(String[] args) {byte b = 5;go(b,b);      // which go() will be invoked?}
}

The output is:



So far, we have seen that

(*) Wideningbeats boxing

(**) Widening beats var-args


At this point, inquiring minds want to know, does boxing beat var-args?

(3) Box or Var-args

class BoxOrVararg {static void go(Byte x, Byte y) { System.out.println("Byte, Byte"); }static void go(byte... x) { System.out.println("byte... "); }                                          public static void main(String [] args) {byte b = 5;go(b,b);         // which go() will be invoked?}
}

As it turns out, the output is



So we have seen another rule:

(*) boxing beats var-args

And var-args is the last choice to select.


3. Overloading When Combining Widening and Boxing

In this case the compiler will have to widen and then autobox the parameter for a match to be made:

class WidenAndBox {static void go(Long x) { System.out.println("Long"); }public static void main(String [] args) {byte b = 5;go(b);      //widen then box, it is illegal                                            }
}

This is just too much for the compiler:



Widen then box, it is illegal.

Strangely enough, it IS possible for the compiler to perform a boxing operation followed by a widening operation in order to match an invocation to a method.

class BoxAndWiden {static void go(Object o) {Byte b2 = (Byte) o;     // ok - it's a Byte objectSystem.out.println(b2);}public static void main(String [] args) {byte b = 5;go(b);                 // can this byte turn into an Object ?                          }
}

This compiles (!), and produces the output:



It should box then widen.

Wow! Here's what happened under the covers when the compiler, then the JVM, got to the line that invokes the go() method:
1) The byte b was boxed to a Byte.
2) The Byte reference was widened to an Object (since Byte extends Object).
3) The go() method got an Object reference that actually refers to a Byte object.
4) The go() method cast the Object reference back to a Byte reference (remember, there was never an object of type Object in this scenario, only anobject of type Byte!).
5) The go() method printed the Byte's value.


4. Overloading in Combination with Var-args

What happens when we attempt to combine var-args with either widening or boxing in a method-matching scenario? Let's take a look:

class Vararg {static void wide_vararg(long... x) { System.out.println("long..."); }static void box_vararg(Integer... x) { System.out.println("Integer..."); }public static void main(String [] args) {int i = 5;wide_vararg(i,i);      // needs to widen and use var-argsbox_vararg(i,i);       // needs to box and use var-args}
}

This compiles and produces:



As we can see, you can successfully combine var-args with either widening or boxing. 

So the following codes wil be failed.

class Ambiguous {static void vararg(long... x) { System.out.println("long..."); }static void vararg(Integer... x) { System.out.println("Integer..."); }public static void main(String [] args) {int i = 5;vararg(i,i);      // widen first or box first and before using var-arg? Both yes!}                                                                                          
}

This is just too much for the compiler:



Another example:

public class Ambiguous2 {public static void test(float a, Character... c) {System.out.println("float, Character...");}public static void test(Character... c) {System.out.println("Character...");}public static void main(String[] args) {test('a', 'b'); // widen first or box first before using var-arg ?}
}

This is also too much for the compiler:



5. review of the rules for overloading methods using widening, boxing, and var-args


(1) Primitive widening uses the "smallest" method argument possible.

(2) Used individually, boxing and var-args are compatible with overloading.

(3) You CANNOT widen from one wrapper type to another. (IS-A fails.)

(4) You can box and then widen. (An int can become an Object, via Integer.)

(4) You can combine var-args with either widening or boxing.



这篇关于Overloading with Widening、Boxing and Var-args的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/631410

相关文章

用Python实现时间序列模型实战——Day 14: 向量自回归模型 (VAR) 与向量误差修正模型 (VECM)

一、学习内容 1. 向量自回归模型 (VAR) 的基本概念与应用 向量自回归模型 (VAR) 是多元时间序列分析中的一种模型,用于捕捉多个变量之间的相互依赖关系。与单变量自回归模型不同,VAR 模型将多个时间序列作为向量输入,同时对这些变量进行回归分析。 VAR 模型的一般形式为: 其中: ​ 是时间  的变量向量。 是常数向量。​ 是每个时间滞后的回归系数矩阵。​ 是误差项向量,假

【JavaScript】var that = this

var that = this 就是将当前的this对象复制一份到that变量中。这样做有什么意义呢? $('#content').click(function(){// this 是被点击的#contentvar that = this;$('.content').each(function(){// this 是.content循环中当前的对象// that 仍然是刚才被点击的#conten

【JavaScript】var a = b = 3;是如何执行的?

(function(){var a = b = 3;})();console.log("a defined? " + (typeof a !== 'undefined'));console.log("b defined? " + (typeof b !== 'undefined'));   由于 a 和 b 都定义在函数的封闭范围内,并且都始于 var关键字,大多数JavaScript开发人

【JavaScript】let与var的区别及变量、函数提升

有var与无var的区别   在函数内部,有var和没var声明的变量是不一样的。有var声明的是局部变量,没var的,声明的全局变量,所以可以借此向外暴露接口。 let与var的区别   在上面代码中,我们使用var语句声明变量x。因此,变量x的范围是函数范围。if语句内的变量x就是if语句外创建的变量x。因此,在你修改if语句块内变量x的值的时候,也会修改函数中变量x的所有引用的

Delphi Dll中传递Pchar类型参数是否需要加var

比如原来有个函数是这样的: procedure GetMsg(ret: Integer; var Msg: string); stdcall; //返回消息 begin   Msg := 'OK'; end; 现在改成这样: procedure GetMsg(ret: Integer; var Msg: PChar); stdcall; //返回消息 begin   StrPCopy(Msg, '

【docker无法启动】 can't create unix socket /var/run/docker.sock: is a directory

一次重启docker后出现的问题 Oct 18 19:18:20 worker systemd[1]: Starting Docker Application Container Engine...Oct 18 19:18:20 worker1 dockerd-current[118257]: time="2018-10-18T19:18:20.734668371+08:00" level=w

/var/log/secure安全日志分析

1、tail -f /var/log/secure 看安全日志判断是否有人恶意攻击服务器 1.1 表示root用户关闭了会话(也就是关闭了终端) xxx sshd: pam_unix(sshd:session): session closed for user root 1.2 表示接受来自14.23.168.10的root用户的公钥登录 xxx sshd: Accepted public

“少写了一个var毁了我的网站”

MelonCard发布了一篇文章——”how one missing var ruined our launch“(”少写了一个var毁了我的网站”),这篇文章是说MelonCard用Node.js做后台,因为出了一个小高峰——有50-100人注册,结果整个网站都不响应了,而且还出现了很多奇怪的问题。当他们调查到问题的要源的时候,他们发现下面的代码少写了一个var。 app.all(‘/a

yolov8代码记录---(tasks.py中的c1、c2和args) / (断点续训)

一、task中的c1、c2和args参数解析 如果你想在yolov8中修改或添加 新的结构块,基本都会修改到task.py中的c1、c2和args参数。 此处以Conv所在的判断分支代码为例: if m in (Classify, Conv, ConvTranspose, ..., C3x, RepC3):c1, c2 = ch[f], args[0]if c2 != nc:c2 = make_

template<typename ... _Args>可变参数模板

template<typename ... _Args> 是一种用于定义可变参数模板(variadic template)的语法。这种模板允许你在编译时处理数量可变的参数列表。这种特性非常有用,尤其是在需要处理不确定数量的参数时。 #include <iostream>// 可变参数模板函数template<typename... Args>void print(Args... args