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. NETSH WINSOCK RESET这条命令的含义和作用?

    简单来说netsh winsock reset命令含义是重置 Winsock 文件夹.假设一台机器上的Winsock协议配置有问题的话将会导致网络连接等问题,就须要用netsh winsock res ...

  2. cocos2d疑问

    1. pushScene后,如果才能保持前一个Scene的所有动作,比如schedule 2. APP进入到背景模式运行时,如何让它仍然做一些工作?

  3. Android 高仿微信实时聊天 基于百度云推送

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38799363 ,本文出自:[张鸿洋的博客] 一直在仿微信界面,今天终于有幸利用百 ...

  4. (转)php中global和$GLOBALS[]的分析之一

    PHP 的全局变量和 C 语言有一点点不同,在 C 语言中,全局变量在函数中自动生效,除非被局部变量覆盖     这可能引起一些问题,有些人可能漫不经心的改变一个全局变量.PHP 中全局变量在函数中使 ...

  5. onresize的定义方式

    1.直接在html中定义如<body onresize="doResize()"/> 2.直接给onresize赋值给window和body的onresize赋值如wi ...

  6. JavaScript--模拟网络爬虫

    <!doctype html> <html> <head> <meta charset="UTF-8"> <title> ...

  7. 4.HTTP入门

    什么是http协议查看http协议的工具http协议内容Http请求请求行http协议版本请求资源请求方式GET方式提交POST方式提交请求头3.3 实体内容3.4 HttpServletReques ...

  8. [转载]Java synchronized详解

    在编写一个类时,如果该类中的代码可能运行于多线程环境下,那么就要考虑同步的问题.在Java中内置了语言级的同步原语--synchronized,这也大大简化了Java中多线程同步的使用.我们首先编写一 ...

  9. 将对象保存至文件——CArchive

    CArchive允许以一个二进制的形式保存一个对象的复杂网络,也可以再次装载它们,在内存中重新构造,这一过程叫作串行化/序列化(Serialization),简单的说,CArchive与CFile配合 ...

  10. JavaScript的“闭包”到底是什么(2)

    我的上篇博客标题不对,造成一些误解.我认为博客的宗旨不是背教科书,而是分享研发心得.我的上篇标题因该改成“JavaScript 闭包的一个议题:它对outer scope 的影响”,因为我没有严格地去 ...