参考链接: Java中自动装箱和扩展的方法重载

欢迎来到新的Java Challengers博客!本博客致力于挑战Java编程中的概念。掌握它们,你将成为一名技术娴熟的Java程序员。

本博客中的技术需要付出一些努力才能掌握,但它们会对你作为Java开发人员的日常体验产生重大影响。当你知道如何正确应用核心Java编程技术时,避免错误会更容易,并且当你确切知道Java代码中发生的情况时,跟踪错误会更容易。

你准备好开始掌握Java编程中的核心概念了吗?然后让我们开始我们的第一个Java挑战!

术语:方法重载

由于重载,开发人员倾向于认为这种技术会使系统过载,但事实并非如此。在编程中,方法重载意味着使用相同的方法名和不同的参数。

什么是方法重载?

方法重载是一种编程技术,允许开发人员在同一个类中多次使用相同的方法名,但具有不同的参数。在这种情况下,我们说该方法是重载的。清单1显示了一个方法,其参数在数量,类型和顺序上有所不同。 清单1.三种类型的方法重载

Number of parameters:

public class Calculator {

void calculate(int number1, int number2) { }

void calculate(int number1, int number2, int number3) { }}

Type of parameters:

public class Calculator {

void calculate(int number1, int number2) { }

void calculate(double number1, double number2) { }

}

Order of parameters:

public class Calculator {

void calculate(double number1, int number2) { }

void calculate(int number1, double number2) { }

}

方法重载和原始类型 在清单1中,你可以看到基本类型int和double。我们将更多地使用这些和其他类型,所以花一点时间来回顾Java中的原始类型。 表1. Java中的原始类型

TypeRangeDefaultSizeExample literals boolean true or false false 1 bit true, false byte -128 .. 127 0 8 bits 1, -90, 128 char Unicode character or 0 to 65,536 \u0000 16 bits 'a', '\u0031', '\201', '\n', 4 short -32,768 .. 32,767 0 16 bits 1, 3, 720, 22,000 int -2,147,483,648 .. 2,147,483,647 0 32 bits -2, -1, 0, 1, 9 long -9,223,372,036,854,775,808 to  9,223,372,036,854,775,807 0 64 bits -4000L, -900L, 10L, 700L float 3.40282347 x 1038, 1.40239846 x 10-45 0.0 32 bits 1.67e200f, -1.57e-207f, .9f, 10.4F double 1.7976931348623157 x 10308,  4.9406564584124654 x 10-324 0.0 64 bits 1.e700d, -123457e, 37e1d

**为什么我们要使用方法重载?** 重载使你的代码更清晰,更易于阅读,它还可以帮助你避免程序中的错误。 与清单1相比,想象一个程序,其中有多个calculate()方法,其名称为calculate1 calculate2, calculate3. 。。不好,对吗?重载calculate()方法允许你使用相同的方法名称,同时仅更改需要更改的内容:参数。找到重载方法也很容易,因为它们在代码中组合在一起。 **什么不是重载?** 请注意,更改变量的名称不是重载。以下代码将无法编译:

public class Calculator {

void calculate(int firstNumber, int secondNumber){}

void calculate(int secondNumber, int thirdNumber){}

}

你也不能通过更改方法签名中的返回类型来重载方法。以下代码不会编译:

public class Calculator {

double calculate(int number1, int number2){return 0.0;}

long calculate(int number1, int number2){return 0;}

}

构造函数重载 你可以像对待方法一样重载构造函数:

public class Calculator {

private int number1;

private int number2;

public Calculator(int number1) {this.number1 = number1;}

public Calculator(int number1, int number2) {

this.number1 = number1;

this.number2 = number2;}

}

挑战方法重载!

你准备好迎接你的第一个Java挑战吗?我们来看看吧! 首先仔细查看以下代码。 清单2.高级方法重载挑战

public class AdvancedOverloadingChallenge3 {

static String x = "";

public static void main(String... doYourBest) {

executeAction(1);

executeAction(1.0);

executeAction(Double.valueOf("5"));

executeAction(1L);

System.out.println(x);

}

static void executeAction(int ... var) {x += "a"; }

static void executeAction(Integer var) {x += "b"; }

static void executeAction(Object var) {x += "c"; }

static void executeAction(short var) {x += "d"; }

static void executeAction(float var) {x += "e"; }

static void executeAction(double var) {x += "f"; }}

好的,你已经查看了代码。输出是什么?

1.befe 2.bfce 3.efce 4.aecf

刚刚发生了什么?JVM如何编译重载方法

为了理解清单2中发生的事情,你需要了解有关JVM如何编译重载方法的一些信息。 首先,JVM是智能懒惰的:它总是尽可能少地执行一个方法。因此,当你考虑JVM如何处理重载时,请记住三种重要的编译器技术:

1.宽化类型转换 2.box(自动装箱和拆箱) 3.可变参数

如果你从未遇到过这三种技术,那么一些示例应该有助于使它们清晰明了。请注意,JVM 按给定的顺序执行它们。 这是一个宽化的例子:

int primitiveIntNumber = 5;

double primitiveDoubleNumber = primitiveIntNumber ;

这是宽化时基本类型的顺序:  以下是自动装箱的示例:

int primitiveIntNumber = 7;

Integer wrapperIntegerNumber = primitiveIntNumber;

注意编译此代码时幕后发生的事情:

Integer wrapperIntegerNumber = Integer.valueOf(primitiveIntNumber);

这是一个拆箱的例子 :

Integer wrapperIntegerNumber = 7;

int primitiveIntNumber= wrapperIntegerNumber;

以下是编译此代码时幕后发生的事情:

int primitiveIntNumber = wrapperIntegerNumber.intValue();

这是一个可变参数的例子; 请注意,可变参数它始终是最后执行的:

execute(int… numbers){}

什么是可变参数?

用于可变数量参数,可变参数基本上是由三个点指定的值数组(…)我们可以传递许多int我们想要给这个方法的数字。 例如:

execute(1,3,4,6,7,8,8,6,4,6,88...); // We could continue…

可变参数非常方便,因为值可以直接传递给方法。如果我们使用数组,我们必须使用值实例化数组。

宽化:一个实际的例子

当我们将数字1直接传递给executeAction方法时,JVM会自动将其视为一个int。这就是为什么这个数字不适用于该executeAction(short var)方法。 同样,如果我们传递数字1.0,JVM会自动将该数字识别为double。 当然,数字1.0也可以是 float,但类型是预先定义的。这就是executeAction(double var)清单2中调用该方法的原因。 当我们使用Double包装器类型时,有两种可能性:包装器数字可以解包为基本类型,也可以宽化为Object。(请记住,Java中的每个类都继承了Object类。)在这种情况下,JVM选择将Double类型宽化为一个Object,因为它比取消装箱所需的工作量少,正如我之前所解释的那样。 我们传递的最后一个数字是1L,因为我们这次指定了变量类型,所以它是long。

重载常见错误

到目前为止,你可能已经发现方法重载会让事情变得棘手,所以让我们考虑一下你可能遇到的一些挑战。 使用包装器进行自动装箱 Java是一种强类型编程语言,当我们使用包装器进行自动装箱时,我们必须记住一些事情。首先,以下代码将无法编译:

int primitiveIntNumber = 7;Double wrapperNumber = primitiveIntNumber;

自动装箱只适用于该double类型,因为编译此代码时发生的情况与以下内容相同:

Double number = Double.valueOf(primitiveIntNumber);

上面的代码将编译。第一种 int类型将被扩展为double,然后它将被包装成Double。但是当自动装箱时,没有类型宽化,函数Double.valueOf将收到一个double,而不是一个int。在这种情况下,自动装箱仅在我们强制转换时才有效,如下所示:

Double wrapperNumber = (double) primitiveIntNumber;

请记住, Integer不能转换为Long和Float不能转换为Double。没有继承关系。这些每个类型–Integer,Long,Float,和Double-- 是一个Number和Object。 如有疑问,请记住包装数字可以扩展为Number或Object。(还有很多关于包装的探索,但我会将它留给另一篇文章。)

JVM中的硬编码数字类型

当我们没有为数字指定类型时,JVM将为我们执行此操作。如果我们直接在代码中使用数字1,JVM将创建它作为int。如果你尝试将1直接传递给接收short的方法,则无法编译。 例如:

class Calculator {

public static void main(String… args) {

// This method invocation will not compile

// Yes, 1 could be char, short, byte but the JVM creates it as an int

calculate(1);

}

void calculate(short number) {}

}

使用数字1.0时将应用相同的规则; 虽然它可能是 float,但JVM会将此数字视为double:

class Calculator {

public static void main(String… args) {

// This method invocation will not compile

// Yes, 1 could be float but the JVM creates it as double

calculate(1.0);

}

void calculate(float number) {}

}

另一个常见错误是认为该Double包装类型或任何其他包装类型更适用于接收double的方法。事实上,对于JVM来说,将Double宽化到Object而不是将其拆箱为double类型花费的工作更少。 总而言之,当直接在Java代码中使用时,1将是int,1.0将是 double。宽化是最懒的执行路径,接下来是装箱或拆箱,最后的操作将始终是可变参数。 作为一个奇怪的事实,你知道这个char类型接受数字吗?

char anyChar = 127; // Yes, this is strange but it compiles

关于重载要记住什么

对于需要使用不同参数的相同方法名称的情况,重载是一种非常强大的技术。这是一种有用的技术,因为在代码中使用正确的名称会对可读性产生重大影响。你可以简单地重载它,而不是复制方法并为你的代码添加混乱。这样做可以使代码保持清洁,易于阅读,并降低了重复方法破坏系统某些部分的风险。 需要记住的是:当重载方法时,JVM将尽可能少地工作; 这是最懒惰的执行路径的顺序:

l 首先是宽化 l 第二是装箱 l 第三是可变参数

需要注意的是:直接声明一个数字会产生棘手的情况:1将是int,而1.0将是 double。 还要记住,你可以使用语法显式声明这些类型,1F或1f用于float或者1D或1d用于 double。 这就是我们的第一个Java挑战,介绍了JVM在方法重载中的作用。重要的是要意识到JVM本质上是懒惰的,并且总是遵循最懒的执行路径。

答案

清单2中的Java Challenger的答案是:选项3. efce。

有关Java中方法重载的更多信息

· Java 101: Classes and objects in Java: A true beginner’s introduction to classes and objects, including short sections on methods and method overloading. · Java 101: Elementary Java language features: Learn more about why it matters that Java is a strongly typed language and get a full introduction to primitive types in Java. · Too many parameters in Java methods, Part 4: Explore the limitations and disadvantages of method overloading, and how they may be remedied by integrating custom types and parameter objects. 点击英文原文链接 更多文章欢迎访问: http://www.apexyun.com 公众号:银河系1号 联系邮箱:public@space-explore.com (未经同意,请勿转载)

[转载] Java Challengers#1:JVM中的方法重载相关推荐

  1. java 返回值判断_在Java中判断方法重载的条件除了参数外,还可以通过返回值类型判断。_学小易找答案...

    [单选题]若int x;且有下面的程序片断,则输出结果是() . for (x=3; x<6; x++) { printf((x%2) ? "##%d" : "** ...

  2. java方法重载和重载方法_Java中的方法重载

    java方法重载和重载方法 The concept of Method Overloading in Java is where a class can have multiple methods w ...

  3. WCF中的方法重载 实现

    操作重载 注意:WCF是不支持重载的,如果硬是写成重载的话,会抛出异常 InvalidOperationException,但是我们可以模拟! 原C#中的方法重载: interface ICalcul ...

  4. python方法重载_关于类:如何在Python中使用方法重载?

    我尝试在python中实现方法重载: class A: def stackoverflow(self): print 'first method' def stackoverflow(self, i) ...

  5. scala 方法重载_Scala中的方法重载

    scala 方法重载 Scala方法重载 (Scala method overloading) Method overloading is a method that is redefined in ...

  6. Java基础之不一样的方法重载!

    类层次结构中,如果子类中的一个方法与它超类中的方法有相同的方法名和类型声明,称子类中的方法重载(override)超类中的方法.从子类中调用重载方法时,它总是引用子类定义的方法.而超类中定义的方法将被 ...

  7. 探索Java语言与JVM中的Lambda表达式

    2019独角兽企业重金招聘Python工程师标准>>> 转载来源:http://www.admin10000.com/document/1291.html Lambda表达式是自Ja ...

  8. 深入Java虚拟机:JVM中的Stack和Heap

    http://www.cnblogs.com/laoyangHJ/archive/2011/08/17/gc-Stack.html 在JVM中,内存分为两个部分,Stack(栈)和Heap(堆),这里 ...

  9. JAVA对象在JVM中内存分配

    如果你还不了解JVM内存模型的建议您先看下JVM内存模型 以一下代码为例,来分析下,java对象在内存中的空间分配. public class Student {private String name ...

最新文章

  1. vim 的中文编码问题
  2. 大型网站技术架构 读书笔记
  3. 基本包装类和System类
  4. 第六篇: 分布式配置中心(Spring Cloud Config)(Finchley版本)V2.0_dev
  5. chechbox 的颜色android,Android 之 CheckBox 详解
  6. jQuery.noConflict() 解决冲突 原理深入
  7. mysql批量插入跟更新_Mysql批量插入和更新的性能-问答-阿里云开发者社区-阿里云...
  8. 蓝桥杯2017年第八届C/C++省赛B组第二题-等差素数列
  9. zookeeper 可以干什么
  10. “飞客蠕虫”形成全球最大僵尸网络 每日感染数万网民
  11. 动态数据源,帆软报表同一个sql语句,根据不同的角色使用不同的连接
  12. ipod nano7安装linux,奔泪求助ipod nano5怎么取消外放功能
  13. ms vc9 php,php连接sql server数据库库
  14. 抖音直播间截流黑科技
  15. 智能呼叫系统关键技术(一)
  16. Bezier曲线生成【计算机图形学】
  17. Macbook因电池隐患被禁上飞机
  18. 51nod3137 圆形巧克力
  19. 程序员接私活的10个平台和一些建议,别掉坑里去了
  20. 通过SE14重建数据库表

热门文章

  1. 【编辑器】常用编程环境使用感受20190804
  2. Windows10/Servers2016应用商店恢复/安装
  3. mysql 8.0 yum_CentOS7使用yum安装MySQL8.0
  4. SpringMVC→简介、MVC、SpringMVC工作原理、Maven搭建第一个SpringMVC、请求参数接收、重定向、文件上传、AJAX异步访问、请求参数接收绑定JSON、@注解及传参
  5. html调用mysql数据库表里值,如何从MYSQL数据库正确调用行到HTML表中
  6. Python入门--__init__,__new__
  7. python逻辑运算的一些流程图_Python大牛历时一个月打造的Python系统学习流程图,超详细!...
  8. wps 甘特图_【WPS神技能】在Excel表格中用图表阶梯式的展示任务进程?找甘特图呀...
  9. 标识符的作用域与可见性
  10. C++的STL标准库学习(stack)栈