jvm7 jvm8_JVM中的方法重载

jvm7 jvm8

欢迎来到新的Java Challengers博客! 该博客致力于处理Java编程中的挑战性概念。 掌握它们,您将逐步成为一名高技能的Java程序员。

本博客中的技术需要花费一些精力来掌握,但是它们对于您作为Java开发人员的日常体验将产生巨大的影响。 当您知道如何正确应用核心Java编程技术时,避免bug会更容易;而当您确切了解Java代码中发生的事情时,跟踪bug会容易得多。

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

术语:方法重载

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

什么是方法重载?

方法重载是一种编程技术,它允许开发人员在相同的类中使用相同的方法名称多次,但使用不同的参数。 在这种情况下,我们说该方法是重载的。 清单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中,您将看到原始类型intdouble 。 我们将进一步处理这些类型和其他类型,因此请花一点时间来回顾Java中的原始类型。

表1. Java中的原始类型

类型 范围 默认 尺寸 示例文字
boolean 对或错 1位 真假
byte -128 .. 127 0 8位 1,-90,128
char Unicode字符或0到65,536 \ u0000 16位 'a','\ u0031','\ 201','\ n',4
short -32,768 .. 32,767 0 16位 1,3,720,22,000
int -2,147,483,648 .. 2,147,483,647 0 32位 -2,-1、0、1、9
long -9,223,372,036,854,775,808至9,223,372,036,854,775,807 0 64位 -4000L,-900L,10L,700L
float 3.40282347 x 1038,1.40239846 x 10-45 0.0 32位 1.67e200f,-1.57e-207f,.9f,10.4F
double

1.7976931348623157 x 10308,4.9406564584124654 x 10-324

0.0 64位 1.e700d,-123457e,37e1d

为什么要使用方法重载?

重载使您的代码更整洁,更易于阅读,还可以帮助您避免程序中的错误。

与清单1相比,想象一下一个程序,其中有多个名称为calculate 1, calculate2calculate3 calculate()方法。 。 。 不好吧? 重载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 Challenger吗? 让我们找出答案!

首先仔细查看以下代码。

清单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. 贝菲
  2. bfce
  3. efce
  4. 交流电

在这里检查您的答案。

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

为了了解清单2中发生的情况,您需要了解有关JVM如何编译重载方法的一些知识。

首先,JVM是聪明的懒惰者 :它将始终尽最大的努力来执行一种方法。 因此,在考虑JVM如何处理重载时,请记住以下三种重要的编译器技术:

  1. 加宽
  2. 装箱(自动装箱和拆箱)
  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();

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


execute(int… numbers){}

什么是可变参数?

用于可变参数的varargs基本上是由三个点(…)指定的值的数组。我们可以将想要的许多int数传递给此方法。

例如:


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

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

加宽:一个实际的例子

当我们将数字1直接传递给executeAction方法时,JVM会自动将其视为int 。 这就是为什么数字不属于executeAction(short var)方法的原因。

同样,如果我们传递数字1.0,则JVM会自动将该数字识别为double

当然,数字1.0也可以是float ,但是类型是预定义的。 这就是清单2中调用executeAction(double var)方法的原因。

当我们使用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不能为LongFloat不能为Double 。 没有继承。 这些类型中的每一个( IntegerLongFloatDouble--is一个Number和一个Object

如有疑问,请记住包装号可以扩展为NumberObject 。 (关于包装器,还有很多要探索的地方,但是我将其留在另一篇文章中。)

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 float数:


  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 。 扩展是执行最懒惰的路径,装箱或拆箱紧随其后,最后一个操作将始终是varargs

奇怪的是,您知道char类型接受数字吗?


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

关于重载的注意事项

对于需要相同方法名称和不同参数的方案,重载是一项非常强大的技术。 这是一种有用的技术,因为在代码中使用正确的名称对可读性有很大的影响 。 您可以简单地重载它,而不是复制方法并给代码增加混乱。 这样做可以使您的代码保持整洁和易于阅读,并减少了重复方法破坏系统某些部分的风险。

注意事项 :重载方法时,JVM将尽力而为。 这是最懒惰的执行路径的顺序:

  • 首先是扩大
  • 第二是拳击
  • 第三是瓦拉格斯

需要注意的是 :直接声明数字会产生棘手的情况:1将是int而1.0将是double

还要记住,您可以使用1F或1f的float语法或1D或1d的double语法明确声明这些类型。

结束我们的第一个Java Challenger,介绍了JVM在方法重载中的作用。 重要的是要认识到JVM本质上是惰性的,并且将始终遵循最懒惰的执行路径。

答案键

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

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

这个故事“ JVM中的方法重载”最初是由JavaWorld发布的

翻译自: https://www.infoworld.com/article/3268983/java-challengers-1-method-overloading-in-the-jvm.html

jvm7 jvm8

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值