首页 > 编程知识 正文

抽象类和接口有什么不同,java接口抽象类区别

时间:2023-05-03 11:50:35 阅读:114223 作者:3961

一、方法重装概述

方法重载:如果两个或多个方法的名称相同,且参数的相应类型或数量不同,则称为方法重载。 当然,编译器也能识别。

编译器如何识别调用了哪些方法?

在继续之前,让我们先了解编译器是如何识别程序调用了其方法的。 其实,这个问题是,在调用方法时,编译器可以得到调用方法的什么信息,并找到相应的方法? 我们常见的方法调用如下:

方法(价值);

也就是说,方法调用方向编译器提供方法名称、参数列表这两个信息。

因此,编译器只能从方法名称和参数列表中标识调用方法。

一个面试问题是:“为什么不能用返回型重载方法?

如上所述,由于方法调用方不提供有关返回类型的信息,因此如果多个方法中只有返回类型不同,编译器就不知道调用了该方法。

虽然我们已经知道编译器是如何识别方法的,但对于方法重载,方法名称必须相同。 只要关注参数列表就可以了。 区分参数列表或区分重载方法:

参数的个数

参数类型

参数顺序

二、方法重载匹配选择

方法重载后,可能会出现在方法调用方应该选择哪种重载方法的问题,但如果只有唯一的重载方法匹配,则没有问题。 然而,在许多情况下,多个过载方法是匹配的,因此在这种情况下应该选择最佳过载方法。

匹配最合适、最明确的重载方法的是,实际上实参列表与当前重载方法中的形参列表相匹配,并且寻找最接近实参列表的形参列表

1、基本类型之间的重载

对于基本类型,缺省情况下允许从“短类型”扩展到“长类型”,并且会自动进行扩展。 这样,实参就有可能与多个“长类型”的形参一致。 让我们来看一个简单的例子。

publicstaticvoidmain (字符串[ ] args ) {

短整型=4;

m(s;

}

公共统计(intx )//方法1

系统. out.println (重载方法1 );

}

公共统计(浮动)//方法2

系统. out.println (重载方法2 );

}

执行结果:

重载方法1

缺省情况下,可以自动将短类型转换为int、“浮动”类型。 然而,m(s )真正匹配的是m ) m(int x )方法,而不是波形参数长度长的m ) m(float x )。 因此可知,基本型s形匹配规则是在与正确型s形不一致的情况下,优先匹配存储器长度(范围)大且最接近实际参数的存储器长度的s形,来决定调用哪个重载方法

2、引用类型之间的重载

对于引用类型,可以匹配多个重载方法的原因是,缺省情况下,JVM还会自动进行引用类型对象类型的上转换,因此它可能匹配多个祖先类型的形式。 请参阅以下示例。

公共类test _3{

publicstaticvoidmain (字符串[ ] args ) {

Children children=new Children (;

somemethod(Children );

}

publicstaticvoidsomethod (ancestor an )//重载方法1

system.out.println (' thisisancestormethod!' );

}

公共服务语音(Parentan )//重载方法2

system.out.println (' thisisparentmethod!' );

}

}

//具有继承关系的三个类

class Ancestor{//祖先类

}

class Parent extends Ancestor{//由父类、Ancestor继承

}

在class Children extends Parent{//子类中,由Parent继承

}

执行结果:

this is Parent Method!

引用类型与基本类型一样,选择“最明确的方法”,选择引用类型之间最明确的重载方法的规则是:重载方法的引用类型与实参不一致,实参在继承树结构上优先匹配与实参类型最近的实参,则存在该实参的重载方法

3、自动装箱开箱、可变参数型

开箱及可变参数列表的处理由编译器自动处理。 也就是说,默认情况下自动进行。 这将确保实际参数列表与多个形状参数列表相匹配,并与多种重载方法相匹配。

本节介绍如何重新加载基本类型、参考类型和自动装箱拆箱可变参数的匹配优先级。

请看下面的例子。 就是这个例子

包括很多情况:

public class Test_3 {

public static void main(String[] args) {

short s = 5;

overloadMethod(s);// test1

Integer i = 10;

overloadMethod(i);//test2

overloadMethod(s,s);//test3

}

public static void overloadMethod(int a) { //m1

System.out.println("调用 overloadMethod(int)");

}

public static void overloadMethod(Short in) {//m2

System.out.println("调用 overloadMethod(short)");

}

public static void overloadMethod(int a,int b) {//m3

System.out.println("调用 overloadMethod(int,int)");

}

public static void overloadMethod(short... s) { //m4

System.out.println("调用 overloadMethod(short...)");

}

public static void overloadMethod(Integer... i) {//m5

System.out.println("调用 overloadMethod(Integer...)");

}

}

运行结果

调用 overloadMethod(int)

调用 overloadMethod(int)

调用 overloadMethod(int,int)

我们来分析一下上面的例子中,方法调用处可以匹配到的方法:

test1 处的方法调用可以匹配的重载方法有:m1(基本类型的短类型自动转为长类型)、m2(自动装箱)、m4(可变参数列表)

test2 处的方法调用可以匹配的重载方法有:m1(自动拆箱)、m5(可变参数列表);

test3 处的方法调用可以匹配的重载方法有:m3(基本类型的短类型自动转换成长类型)、m4(可变参数列表)

查看输出结果,发现:test1处选择了m1、test2选择了m1,test3选择了m3。

根据这样的结果,也就是这几种形参匹配规则还是有个匹配的顺序的。对重载方法的选择作以下总结:先按照实参的类型(基本类型或引用类型)对应匹配规则,进行查找最相近的形参列表,从而找到最明确的重载方法;找不到,则执行第二步;

对实参进行装箱或拆箱转换(前提是实参是基本类型或者是包装类),再安按照转换得到的类型进行匹配形参的类型(形参类型与转换类型要一致,特别注意基本类型);找不到,则执行第三步;

匹配形参是可变参数的重载方法,此时,形参的类型可以是 实参的类型以及通过 基本类型的短转长、自动装箱拆箱、祖先类型 得到的转换类型。

将上面的总结再简化一下,可以简化成 重载方法的形参匹配规则的优先级:

当前类型(基本类型或引用类型)的匹配规则 > 自动装箱拆箱 > 可变参数列表

再看一个例子:

public class MyTest {

public static void main(String[] args) {

int a = 5;

short s = 8;

m(a,s);

}

public static void m(int a,Short b) {//m1

System.out.println("调用了m(int,Short)");

}

public static void m(float f,short s) {//m2

System.out.println("调用了m(float,short)");

}

}

运行结果:

调用了m(float,short)

分析: 实参都是基本类型,优先考虑形参列表都是基本类型的重载方法,找不到才考虑自动装箱拆箱

4、泛型方法的重载

泛型方法的重载规则: 将泛型方法的类型变量擦除,然后与非泛型方法一样,按照上面所说的三种规则一一匹配

public static void main(String[] args) {

//创建Runnable对象

Runnable r = new Runnable() { public void run(){} };

//调用泛型方法

m(r);

}

public static void m(T t) {//m1

System.out.println("调用了 void m(T)");

}

public static void m(T t) {//m2

System.out.println("调用了 void m(T t)");

}

运行结果:

调用了 void m(T t)

上面的两个泛型方法m(T t)进行类型擦除后是:

public static void m(Object t);

public static void m(Runnable t);

显然,调用方法应该是m2,与运行结果相符;

5. 没法确定的重载方法调用

尽管编译器会按照上面所说的三种优先级别去让实参匹配形参,然而匹配的结果却不一定是唯一的,也就是说会匹配到多个方法,从而无法确定调用那个方法,编译失败

情况一: 实参列表的所有最佳匹配的形参不在同一个方法中

public class MyTest {

public static void main(String[] args) {

int aa = 5;

short ss = 8;

m(aa,ss);//编译不通过,无法确定调用了那个重载方法

}

public static void m(int a,double b) {//m1

System.out.println("调用了m(int,Short)");

}

public static void m(float f,int c) {//m2

System.out.println("调用了m(float,short)");

}

}

分析:

m(aa,ss)的调用编译失败,因为实参aa的最佳匹配m(int,double)的第一个形参,而实参ss的最佳匹配则是m(float,short)的第二个形参。

因此,实参列表的(aa,ss)的最佳形参类型匹配分开在了两个重载方法中。

注意一下,即使某个重载方法的形参列表包含最多的最相近的形参类型,只要不是全部,那么依旧无法确定调用了哪个重载方法。

情况二: 可变参数列表的特殊性 -- 无法根据可变参数的类型来重载方法

public static void m(short... s) {}

public static void m(Short... s) {}

public static void m(int... s) {}

调用测试例子:

short s = 8;

Short sl = 10;

m(s,s);//编译不通过

m(s,sl);//编译不通过

m(sl,sl);//编译不通过

重写 与 重载的区别

重写是针对父类与子类间的方法,即必须先得继承父类的方法。而重载则没有这种限制。

重写要求方法的 而方法重载则只需要 方法名相同,参数列表不同就行了。

方法重载时,方法的调用是在编译时期就已经确定了调用那个方法;方法重写,则要在运行时,才能确定调用的是子类还是父类的方法。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。