`
kingj
  • 浏览: 425655 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

java重载

 
阅读更多

     今天看到think in java的重载部分,大家都知道java的重载是一个方法的方法名称不变,参数类型,参数数量不同(如果这些相同,返回值类型不同,是不同通过javac编译的),但是java重载仅仅只有这些吗?

这里涉及到2个概念:

     1、静态分派

     2、动态分派

那么,什么是静态分派和动态分派呢?我们来看一个例子(暂时不涉及动态分派的概念),相信大家就都会明白了

 

package com.zx.exception;

public class Overload {
	static class Human{}
	static class Man extends Human{}
	static class Women extends Human{}
	public void hello(Human h){
		System.out.println("human");
	}
	
	public void hello(Man man){
		System.out.println("man");
	}
	
	public void hello(Women woman){
		System.out.println("woman");
	}
	
	public static void main(String[] args) {
		Overload l=new Overload();
		Human man=new Man();
		Human women=new Women();
		l.hello(man);
		l.hello(women);
		System.out.println("=======================");
	}
}

   我们看到在overload类中有三个重载版本的hello方法,只是参数类型不同,在main方法中我们实例化了Human的两个子类Man以及Woman,执行的结果如下:

 

human
human
=======================
 

    相信大家都能一眼看出结果,执行结果是两个human,对重载有一定认识的朋友都会知道为什么,这就是我要重点讲解的部分。

          java重载是基于静态分派技术实现的,说的通俗一点就是java编译器在编译阶段就会确定方法调用的参数类型,

在main中 声明了这两个对象,Human man=new Man();     Human women=new Women();,对于编译器来说,我们认为它没有那么聪明的知道man是一个Man的实例,women是一个Woman的实例,实际上这些是在运行时才能确定的,所以当你调用l.hell(man)   ,   l.hello(women)的时候,java编译器都会选择

public void hello(Human h){
		System.out.println("human");
	}

 这个hello方法的重载版本,如果你还有疑惑的话,那我们用javap -c com.zx.exception.Overload 来看一下实际编译的字节码是什么:

 

D:\java\thinkinjava\bin>javap -c com.zx.exception.Overload
Compiled from "Overload.java"
public class com.zx.exception.Overload extends java.lang.Object{
public com.zx.exception.Overload();
  Code:
   0:   aload_0
   1:   invokespecial   #8; //Method java/lang/Object."<init>":()V
   4:   return

public void hello(com.zx.exception.Overload$Human);
  Code:
   0:   getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc     #22; //String human
   5:   invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   8:   return

public void hello(com.zx.exception.Overload$Man);
  Code:
   0:   getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc     #33; //String man
   5:   invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   8:   return

public void hello(com.zx.exception.Overload$Women);
  Code:
   0:   getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc     #37; //String woman
   5:   invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   8:   return

public static void main(java.lang.String[]);
  Code:
   0:   new     #1; //class com/zx/exception/Overload
   3:   dup
   4:   invokespecial   #42; //Method "<init>":()V
   7:   astore_1
   8:   new     #43; //class com/zx/exception/Overload$Man
   11:  dup
   12:  invokespecial   #45; //Method com/zx/exception/Overload$Man."<init>":()V
   15:  astore_2
   16:  new     #46; //class com/zx/exception/Overload$Women
   19:  dup
   20:  invokespecial   #48; //Method com/zx/exception/Overload$Women."<init>":()V
   23:  astore_3
   24:  aload_1
   25:  aload_2
   26:  invokevirtual   #49; //Method hello:(Lcom/zx/exception/Overload$Human;)V
   29:  aload_1
   30:  aload_3
   31:  invokevirtual   #49; //Method hello:(Lcom/zx/exception/Overload$Human;)V
   34:  getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
   37:  ldc     #51; //String =======================
   39:  invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   42:  return

}

   首先来看一下三个hello重载方法的字节码:

   hello(Huma)的字节码为:

 

public void hello(com.zx.exception.Overload$Human);
  Code:
   0:   getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc     #22; //String human
   5:   invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   8:   return

 4条指令,getstatic获取System.out的常量池引用,ldc将常量池中索引为0xF6的项"human"加载到当前栈的栈顶,

  invokevirtual指令调用System.out的println方法,参数为当前栈顶的值,最后返回。

 

 第二个重载方法

 hello(Overload$Man)的字节码为:

 

public void hello(com.zx.exception.Overload$Man);
Code:
0: getstatic #16; //Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #33; //String man
5: invokevirtual #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return

 方法执行同上

 

 第三个重载方法

 hello(Overload$Man)的字节码为:

 

public void hello(com.zx.exception.Overload$Woman);
Code:
0: getstatic #16; //Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #33; //String man
5: invokevirtual #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return

 方法执行同上

 

看完了这三个方法后,回到main中去:

 

 

 

public static void main(java.lang.String[]);
  Code:
   0:   new     #1; //class com/zx/exception/Overload
   3:   dup
   4:   invokespecial   #42; //Method "<init>":()V
   7:   astore_1
   8:   new     #43; //class com/zx/exception/Overload$Man
   11:  dup
   12:  invokespecial   #45; //Method com/zx/exception/Overload$Man."<init>":()V
   15:  astore_2
   16:  new     #46; //class com/zx/exception/Overload$Women
   19:  dup
   20:  invokespecial   #48; //Method com/zx/exception/Overload$Women."<init>":()V
   23:  astore_3
   24:  aload_1
   25:  aload_2
   26:  invokevirtual   #49; //Method hello:(Lcom/zx/exception/Overload$Human;)V
   29:  aload_1
   30:  aload_3
   31:  invokevirtual   #49; //Method hello:(Lcom/zx/exception/Overload$Human;)V
   34:  getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
   37:  ldc     #51; //String =======================
   39:  invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   42:  return

 执行的字节码很简单,就是new 创建三个对象的实例,dup复制这三个实例并推到当前栈顶,astore将实例变量的保存到当前栈的局部变量表中去,关键的地方看26行和31行,我们分别传入了一个Human的实例man和women,然而字节码却是这样的:

 

26:  invokevirtual   #49; //Method hello:(Lcom/zx/exception/Overload$Human;)V

 

31:  invokevirtual   #49; //Method hello:(Lcom/zx/exception/Overload$Human;)V

这下真相大白于天下了,调用的是Overload类的hello(Human )版本的重载方法

 

 

总结:java的重载是基于静态分派实现,也就是说对于某一个类C中方法A的若干个重载版本(A1....AN),C实例的方法A被调用时,java编译器在编译阶段就已经确定了调用者会调用的某一个确定的A版本。这和java的重写Overrite恰恰相反,下一章我会详细讲解Overrite的原理。

 

 

 

分享到:
评论

相关推荐

    Java方法重载+Java重载案例

    Java方法重载+Java重载案例+Java重载 Java方法重载+Java重载案例+Java重载 Java方法重载+Java重载案例+Java重载 Java方法重载+Java重载案例+Java重载

    java重载的实现方法

    Java重载的实现方法详解 Java重载(Overload)是Java编程语言中的一种机制,它允许在同一个类中定义多个方法,具有相同的名称,但参数列表不同。这种机制可以提高代码的灵活性和可读性。本文将详细介绍Java重载的...

    JAVA重载概念

    ### JAVA重载概念详解 #### 一、方法重载的概念 在 Java 编程语言中,方法重载(Method Overloading)是一种非常重要的特性,它允许我们在同一个类中定义多个同名但参数列表不同的方法。这种方法重载的概念是实现...

    java重载代码分享.zip

    下面将详细解释Java重载的概念、规则以及在实际编程中的应用。 1. **概念理解**: - 重载(Overloading)是多态性的一种表现,即在同一个作用域内,一个类可以有多个同名的方法,它们之间的区别在于传入的参数列表...

    java 重载,重写以及继承,多态的区别

    "java 重载,重写以及继承,多态的区别" Java 中的重载、重写、继承和多态是四个不同的概念,它们之间存在一定的关系,但也存在明显的区别。 重载(Overload) 重载是指在同一个类中可以定义多个同名的方法,但这些...

    java重载介绍及使用

    在Java编程语言中,方法的重载(Overloading)是一个重要的概念,它允许我们在同一个类中定义多个同名方法,但这些方法的实现必须有所不同。主要的不同之处在于它们的参数列表,包括参数的数量、类型或者顺序。这种...

    Java重载.docx

    Java中的方法重载是面向对象编程的一个重要特性,它允许我们在同一个类中定义多个具有相同名称但参数列表不同的方法。这样做不仅提高了代码的可读性,还使得代码更易于维护和扩展。以下是对方法重载的详细解释: 1....

    【Java编程教程】详解Java 重载.pdf

    Java中的方法重载是面向对象编程的一个重要特性,它允许在一个类中定义多个同名方法,但这些方法的参数列表必须有所不同。这主要是通过改变参数的数量或参数的类型来实现的。下面我们将深入探讨这个主题。 1. **...

    Java中重载和重写总结

    Java 中重载和重写总结 Java 中的重载(Overloading)和重写(Overriding)是两个非常重要的概念,它们都是多态性的体现形式。 一、Java 中的重载(Overloading) Java 中的重载是指在同一个类中可以创建多个...

    java中重载与重写

    在Java编程语言中,方法的重载(Overloading)与重写(Overriding)是两个非常重要的概念。它们虽然只有一字之差,但其实质却大相径庭。理解这两者的不同对于深入掌握Java语言至关重要。 ### 一、重载(Overloading...

    Java方法重载的实例

    Java方法重载是面向对象编程中的一个重要概念,它允许在一个类中定义多个具有相同名称但参数列表不同的方法。这样做的好处在于,通过方法名就可以直观地理解方法的功能,而具体的执行逻辑则由传入的参数类型和数量...

    Java的重载和重写

    Java编程语言中的重载(Overloading)和重写(Overriding)是两个关键的概念,它们都是多态性的重要体现,但各自有着不同的含义和规则。 首先,我们来详细了解一下方法的重载。重载,简单来说,就是在一个类中定义多个...

    Java重载,Java实现一个类中多个相同名字的方法

    Java 语言中的重载(Overload)是一种多态性(Polymorphism)的表现,它允许在同一个类中定义多个同名方法,但每个方法的参数列表必须不同。这些差异主要体现在参数的类型、个数或者顺序上。重载与返回值类型无关,...

    java 重载,继承,重写和多态的区别. doc

    Java编程语言中的重载、继承、重写和多态是面向对象编程的四个核心概念,它们各自具有独特的功能和用途。 1. **重载(Overloading)**: 重载发生在同一个类内部,指的是可以有多个同名方法,但这些方法的参数列表...

    Java重载和重写的区别--源码实例

    Java中的重载(Overloading)和重写(Overriding)是面向对象编程中的两种关键特性,它们涉及到方法的多态性。理解这两者的区别对于编写高效、可维护的代码至关重要。 **重载(Overloading)**是指在一个类中,可以有多个...

    Java语言中的 覆盖重载和多态

    Java语言中的覆盖(Override)和重载(Overload)以及多态(Polymorphism)是面向对象编程的重要概念,它们是实现代码复用和灵活性的关键。 **多态性(Polymorphism)** 多态性是Java中一种允许一个接口有多种实现的方式。...

    java学习笔记 继承 重载 覆盖

    Java编程语言的学习涉及众多核心概念,本篇笔记主要探讨了几个关键知识点:继承、重载和覆盖。首先,我们从Java环境配置开始,确保能够正确地运行Java程序。在Windows系统中,需要设置环境变量PATH,指向JDK安装目录...

    Java重载构造原理与用法详解

    Java重载构造原理与用法详解 Java重载构造原理与用法详解是Java编程语言中的一种重要概念,它涉及到方法重载、构造器、可变参数、递归算法、封装等多个方面的知识点。下面将对这些知识点进行详细的解释和分析。 一...

    63.java方法重载.zip

    63.java方法重载.zip63.java方法重载.zip63.java方法重载.zip63.java方法重载.zip63.java方法重载.zip63.java方法重载.zip63.java方法重载.zip63.java方法重载.zip63.java方法重载.zip63.java方法重载.zip63.java...

    第四章 java 重载&amp;访问修饰符&amp;静态&amp;常用类 - 模板.md

    Java

Global site tag (gtag.js) - Google Analytics