1. 什么是重载

  方法名称相同,但它们的参数类型或个数不同,这样,方法在被调用时编译器就可以根据参数的类型与个数的不同加以区分,这就是方法的重载。

  既然可以通过参数类型或参数个数来作为重载条件,那返回值是否可以作为重载的条件呢?

代码如下:

public int returnType() {
return 2;
}
public float returnType() {
return 2f;
}

这时候如果这样调用此方法:

int x = returnType()

将会调用返回值是int类型的方法,这没什么好说的,如果这样调用:

returnType();
double d = returnType();

  因为上面两个方法都符合条件,那么这就让编译器无法选择了,而且,方法在调用时还可以忽略其返回值。
  所以方法的返回值类型不能作为重载的标准,原因就在于其不能提供给编译器足够的信息来识别应该调用哪个方法。

2. 基本类型下重载方法的调用

  在重载方法调用时,如果形参列表与实参列表对应的参数类型不相同,但形参列表的参数类型可以兼容对应的实参列表的参数类型,那么这时候方法会怎么调用呢?

我们用一些简单的代码来说明:

public class Test {
public static void main(String[] args) {
Test test = new Test();
byte b = 20;
test.select(b);
} public void select(short b) {
System.out.println("调用 short方法");
} public void select(char b) {
System.out.println("调用 char方法");
} public void select(int b) {
System.out.println("调用 int方法");
} public void select(float b) {
System.out.println("调用 float方法");
} }

因为方法定义中没有形参为byte的类型,所以除了char参数的方法外,其他几个方法的参数都可以兼容byte类型,那byte会调用哪一个方法呢?

调用 short方法

同理:

public class Test {
public static void main(String[] args) {
Test test = new Test();
long b = 20L;
test.select(b);
} public void select(int b) {
System.out.println("调用 int方法");
} public void select(float b) {
System.out.println("调用 float方法");
} public void select(double b) {
System.out.println("调用 double方法");
} }

结果为:

调用 float方法

大家可以使用这几种基本数值类型多试试看。

  总结:在方法调用时,如果实参的类型与方法中形参的类型不相同,那么系统会调用形参类型可以兼容的实参类型,并且形参类型与实参类型最接近的方法。而基本数据类型顺序由低到高为:

  所以,加入方法调用时实参的类型为char,而要调用的方法中不存在形参为char类型的,而分别为byte,short,int,long,float,double时,byte与short不能兼容char类型,不考虑。剩下的4个方法中int与char的类型最为接近,此时就会调用形参类型为int的方法。

3. 引用类型下重载方法的调用

我们用一个简单的例子来实验:

public class Test {
public static void main(String[] args) {
Test test = new Test();
Test3 test3 = new Test3();
test.select(test3);
} public void select(Test1 test1) {
System.out.println("调用 Test1方法");
} public void select(Test2 test2) {
System.out.println("调用 Test2方法");
} public void select(Object obj) {
System.out.println("调用 Object方法");
} } class Test1 {
} class Test2 extends Test1 {
} class Test3 extends Test2 {
}

结果为:

调用 Test2方法

如果我们将参数为Test2的给去掉,则结果为:

调用 Test1方法

如果我们将参数为Test1的也给去掉,结果为:

调用 Object方法

由此可知,引用类型与基本类型的选择方式也是类似的,都是选择与实参类型最接近的。

总结:其实,不管是基本类型还是引用类型,重载方法调用时,在保证兼容性的情况下,都是会调用与实参类型最接近的方法。

4. 包装类与可变参数类型的重载方法调用

public class Test {
public static void main(String[] args) {
Test test = new Test();
test.select(5);
} public void select(float f) {
System.out.println("调用 float方法");
} public void select(double d) {
System.out.println("调用 double方法");
} public void select(Integer i) {
System.out.println("调用 Integer方法");
} public void select(Number number) {
System.out.println("调用 Number方法");
} public void select(int... i) {
System.out.println("调用 int... 方法");
} }

这种情况下,打印结果为:

调用 float方法

将float和double参数的两个方法注释掉,打印结果为:

调用 Integer方法

将前四个方法都注释掉,打印结果为:

调用 int... 方法

或许从结果中,大家也明白了包装类与可变参数类型的重载方法调用了吧;

总结:就 test.select(5)方法调用 来说:

  包装类与可变参数类型的重载调用顺序,可以简记如下:

  参数完全相同的方法(int) -> 形参兼容实参的方法(float -> double) -> 自动拆箱与封箱操作的方法(Integer)  -> 自动拆箱与封箱的父类(Number -> Object) -> 可变参数类型的方法(int...)

5. 重载无法实现多态

看下面一段代码,并预测一下打印结果:

public class Test {
public static void main(String[] args) {
Test test = new Test();
Object obj = new Animal();
Animal animal = new Dog();
test.select(obj);
test.select(animal);
} public void select(Object number) {
System.out.println("调用 Object方法");
} public void select(Animal animal) {
System.out.println("调用 Animal 方法");
} public void select(Dog animal) {
System.out.println("调用 Dog 方法");
} } class Animal {
} class Dog extends Animal {
}

打印结果为:

调用 Object方法
调用 Animal 方法

  因为重载方法的调用是在编译时确定的,也可以说是“静态绑定”,如果实参的类型是引用类型,编译器会根据引用的类型来决定调用哪个重载方法。

  这种方法调用不同于多态,多态方法的调用是根据运行时对象的实际类型来决定的,也称为“动态绑定”,重载方法的选择只是根据引用的类型来决定的,而与该引用所指向的对象类型无关,因为引用所指向的对象类型是在运行时才确定的,因此,使用重载无法实现多态。

6. 泛型方法的重载

  对于泛型类的参数,因为编译器在编译期间会进行类型擦除,所以和普通的重载方法稍稍有些区别。

看以下例子:

public class JavaTest {
public static void main(String[] args) {
JavaTest test = new JavaTest();
Test2 test2 = new Test2();
test.print(test2);
} public <T extends Test2> void print(T t) {
System.out.println("<T extends Test2>方法");
} public <T> void print(T t) {
System.out.println("<T>方法");
} public void print(Test1 test1) {
System.out.println("Test1方法");
}
} class Test1 {
} class Test2 extends Test1 {
}

打印结果为:

<T extends Test2>方法

有关类型擦除就说两点,其他的直接网上搜索就行:

  • 将所有的泛型参数用其最左边界(最顶级的父类型)类型替换。
  • 移除所有的类型参数。

如对于

public <T extends Test2> void print(T t) {
System.out.println("<T extends Test2>方法");
} public <T> void print(T t) {
System.out.println("<T>方法");
}

擦除之后的方法声明为:

public void print(Test2 t) {}
public void print(Object t) {}

然后调用规则和普通的重载方法是相同的。

参考自:《细说Java》

【细说Java】方法重载的简单介绍的更多相关文章

  1. java方法——重载2

    什么是Java方法重载 方法重载的定义 1 对于同一个类,如果这个类里面有两个或者多个重名的方法,但是方法的参数个数.类型.顺序至少有一个不一样,这时候局构成方法重载. END 方法重载示例 1 pu ...

  2. Java方法重载

    Java允许一个类中定义多个方法,只要参数列表不同就行了.如果同一个类中包含了两个或者两个以上的方法的方法名相同,但形参列表不同,则被称为方法重载. /* 参数类型不同的重载 */ public cl ...

  3. java反射机制的简单介绍

    参考博客: https://blog.csdn.net/mlc1218559742/article/details/52754310 先给出反射机制中常用的几个方法: Class.forName (& ...

  4. Java 方法重载与引用数组类型

    1.方法重载  1)方法的签名 方法的签名包含方法名和参数列表 一个类中,不可以有两个方法的签名完全相同,即一个类中不能有两个方法的方法名和参数列表都一样. public class Test{ pu ...

  5. Java泛型使用的简单介绍

    目录 一. 泛型是什么 二. 使用泛型有什么好处 三. 泛型类 四. 泛型接口 五. 泛型方法 六. 限定类型变量 七. 泛型通配符 7.1 上界通配符 7.2 下界通配符 7.3 无限定通配符 八. ...

  6. Java Linked集合的简单介绍和常用方法的使用

    LinkedList的简单介绍 java.util.LinkedList 集合数据存储的结构是链表结构.LinkedList是一个双向链表在实际开发中,对一个集合元素的添加和删除,经常涉及到首尾操作, ...

  7. Java 方法重载,方法重写(覆盖),继承等细节注意

    1.方法重载(method overload)的具体规范 如果有两个方法的方法名相同,但参数不一致,那么可以说一个方法是另一个方法的重载. 一.方法名一定要相同. 二.方法的参数表必须不同,包括参数的 ...

  8. java方法重载和重写

    1.java的方法重载和重写,表示两种不同的类型.this关键字,出现在类的构造方法中,代表使用该构造方法所创建的对象.,this可以出现在实例方法中核构造方法中.但是不能出现在类方法中.实例方法只能 ...

  9. Java 方法重载 方法重写

    方法重载规则 参数个数不同 参数个数相同,但参数列表中对应的某个参数的类型不一样 方法的返回类型和参数名称不参与重载 "编译期绑定",,因为未产生对象,只看参数.引用类型绑定方法 ...

随机推荐

  1. 精准化测试专业平台Paw:苹果APP应用代码质量的守护者

    众所周知,一款苹果APP进入苹果应用商店后,要上排行榜,要被首页推荐,版本更新必不可少,但作为版本更新的关键所在,软件测试一直被业内吐槽“坑太多”,缺陷防不胜防.相关经验缺乏等等.若问如何“填坑”?以 ...

  2. Android 网络框架Volley的使用

    Volley简介 在平时的开发过程中,我们的应用几乎总是在和网络打交道, 在android下的网络编程一般都是基于Http协议的 ,常见的是HttpURLConnection和HttpClient 两 ...

  3. Activity的任务栈Task以及启动模式与Intent的Flag详解

    什么是任务栈(Task) 官方文档是这么解释的 任务是指在执行特定作业时与用户交互的一系列 Activity. 这些 Activity 按照各自的打开顺序排列在堆栈(即“返回栈”)中. 其实就是以栈的 ...

  4. BeanFactory学习

    关于BeanFactory,一个相对易懂的博客,关于深入的理解,后续继续学习 http://www.cnblogs.com/liuling/archive/2013/04/14/BeanFactory ...

  5. win10的独立存储

    win10的独立存储和win8的大致相同 Windows.Storage.ApplicationDataContainer roamingSettings = Windows.Storage.Appl ...

  6. JS遍历对象或者数组

    一.纯js实现 <script> var obj = {"player_id":"GS001","event_id":" ...

  7. struts2与spring集成时,关于class属性及成员bean自动注入的问题

    http://blog.csdn.net/sun_zhicheng/article/details/24232129

  8. 【转】自动布局之autoresizingMask使用详解(Storyboard&Code)

    原文:http://www.cocoachina.com/ios/20141216/10652.html 自动布局Autolayoutstoryboard 前言:现在已经不像以前那样只有一个尺寸,现在 ...

  9. 四、C#方法和参数

    方法是一种组合一系列语句以执行一个特定操作或计算一个特殊结果的方式. 它能够为构成程序的语句提供更好的结构和组织.   在面向对象的语言中,方法总是和类关联在一起的,我们用类将相关的方法分为一组. 方 ...

  10. Javascript闭包简单理解

    提到闭包,想必大家都早有耳闻,下面说下我的简单理解.平时写代码.第三方框架和组件都或多或少用到了闭包.所以,了解闭包是非常必要的.呵呵... 一.什么是闭包简而言之,就是能够读取其他函数内部变量的函数 ...