内容简介:欢迎来到新的本博客中的技术需要付出一些努力才能掌握,但它们会对你作为Java开发人员的日常体验产生重大影响。当你知道如何正确应用核心Java编程技术时,避免错误会更容易,并且当你确切知道Java代码中发生的情况时,跟踪错误会更容易。你准备好开始掌握Java编程中的核心概念了吗?然后让我们开始我们的第一个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中的原始类型
| T ype |
Range |
Default |
Size |
Example 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 ;
这是宽化时基本类型的顺序:
图1.宽化时基本类型的顺序
以下是 自动装箱 的示例:
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会自动将该数字识别为a double。
当然,数字1.0也可以是a 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时将应用相同的规则; 虽然它可能是a 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:方法覆盖与方法重载
- java遗珠之lambda与方法重载
- c# – 如何使用重载的方法访问Web服务
- Java 解惑系列(六):main 方法可以重载或者继承么
- java编程——从jvm角度看懂类初始化、方法重写、重载
- Kotlin 重载个方法,还有两幅面孔,省代码的同时也带来一个深坑
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
How to Solve It
Zbigniew Michalewicz、David B. Fogel / Springer / 2004-03-01 / USD 59.95
This book is the only source that provides comprehensive, current, and detailed information on problem solving using modern heuristics. It covers classic methods of optimization, including dynamic pro......一起来看看 《How to Solve It》 这本书的介绍吧!