本篇内容主要讲解“Java为什么支持方法重载”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java为什么支持方法重载”吧!
为什么要使用重载?而不是把一个方法名字换成不同的。
任何编程语言中都具备的一项重要特性就是名称。当你创建一个对象时,就会给此对象分配的内存空间一个名称。一个方法就是一种行为的名称。通过名称引用所各种对象,属性和方法。良好的命名可以让系统易于理解和修改。
将人类语言细微的差别映射到编程语言中会产生一个问题。通常,相同的词可以表达多种不同的含义——它们被"重载"了。特别是当含义的差别很小时,这会更加有用。
你会说"清洗衬衫"、“清洗车"和"清洗狗”。而如果硬要这么说就会显得很愚蠢:“以洗衬衫的方式洗衬衫”、“以洗车的方式洗车"和"以洗狗的方式洗狗”,因为听众根本不需要区分行为的动作。大多数人类语言都具有"冗余"性,所以即使漏掉几个词,你也能明白含义。你不需要对每个概念都使用不同的词汇——可以从上下文推断出含义。
大多数编程语言(尤其是 C)要求为每个方法(在这些语言中经常称为函数)提供一个独一无二的标识符。所以,你不能有一个 print()
函数既能打印整型,也能打印浮点型——每个函数名都必须不同。
但在 Java (C++) 中,还有一个因素也促使了必须使用方法重载:构造器。因为构造器方法名肯定与类名相同,所以一个类中只会有一个构造器名。
那么你怎么通过不同方式创建一个对象?例如,你想创建一个类,这个类的初始化方式有两种:一种是标准化方式,另一种是从文件中读取信息的方式。你需要两个构造器:无参构造器和有一个 String 类型参数的构造器,该参数传入文件名。两个构造器具有相同的名字——与类名相同。因此,方法重载是必要的,它允许方法具有相同的方法名但接收的参数不同。尽管方法重载对于构造器很重要,但也可以对任何方法很方便地进行重载。
重载构造器和方法:
class Tree { int height; Tree() { System.out.println("Planting a seedling"); height = 0; } Tree(int initialHeight) { height = initialHeight; System.out.println("Creating new Tree that is " + height + " feet tall"); } void info() { System.out.println("Tree is " + height + " feet tall"); } void info(String s) { System.out.println(s + ": Tree is " + height + " feet tall"); } } public class Overloading { public static void main(String[] args) { for (int i = 0; i < 5; i++) { Tree t = new Tree(i); t.info(); t.info("overloaded method"); } new Tree(); } }
一个 Tree 对象既可以是一颗树苗,使用无参构造器,也可以是一颗在温室中已长大的树,已经有一定高度,这就需要有参构造器。
你也许想以多种方式调用 info()
。比如,如果你想打印额外的消息,就可以使用 info(String)
方法。若你无话可说,就可以使用 info()
方法。用两个命名定义完全相同的概念看起来很奇怪,而使用方法重载,你就可以使用一个命名来定义一个概念。
如果两个方法命名相同,Java是怎么知道你调用的是哪个呢?
有一条简单的规则:每个被重载的方法必须有独一无二的参数列表。
除了通过参数列表的不同来区分两个相同命名的方法,其他也没什么方式了。你甚至可以根据参数列表中的参数顺序来区分不同的方法,尽管这会造成代码难以维护。
基本类型可以自动从小类型转为大类型。当这与重载结合时,这会令人有点困惑:
public class PrimitiveOverloading { void f1(char x) { System.out.print("f1(char)"); } void f1(byte x) { System.out.print("f1(byte)"); } void f1(short x) { System.out.print("f1(short)"); } void f1(int x) { System.out.print("f1(int)"); } void f1(long x) { System.out.print("f1(long)"); } void f1(float x) { System.out.print("f1(float)"); } void f1(double x) { System.out.print("f1(double)"); } void f2(byte x) { System.out.print("f2(byte)"); } void f2(short x) { System.out.print("f2(short)"); } void f2(int x) { System.out.print("f2(int)"); } void f2(long x) { System.out.print("f2(long)"); } void f2(float x) { System.out.print("f2(float)"); } void f2(double x) { System.out.print("f2(double)"); } void f3(short x) { System.out.print("f3(short)"); } void f3(int x) { System.out.print("f3(int)"); } void f3(long x) { System.out.print("f3(long)"); } void f3(float x) { System.out.print("f3(float)"); } void f3(double x) { System.out.print("f3(double)"); } void f4(int x) { System.out.print("f4(int)"); } void f4(long x) { System.out.print("f4(long)"); } void f4(float x) { System.out.print("f4(float)"); } void f4(double x) { System.out.print("f4(double)"); } void f5(long x) { System.out.print("f5(long)"); } void f5(float x) { System.out.print("f5(float)"); } void f5(double x) { System.out.print("f5(double)"); } void f6(float x) { System.out.print("f6(float)"); } void f6(double x) { System.out.print("f6(double)"); } void f7(double x) { System.out.print("f7(double)"); } void testConstVal() { System.out.print("5: "); f1(5);f2(5);f3(5);f4(5);f5(5);f6(5);f7(5); System.out.println(); } void testChar() { char x = 'x'; System.out.print("char: "); f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); System.out.println(); } void testByte() { byte x = 0; System.out.print("byte: "); f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); System.out.println(); } void testShort() { short x = 0; System.out.print("short: "); f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); System.out.println(); } void testInt() { int x = 0; System.out.print("int: "); f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); System.out.println(); } void testLong() { long x = 0; System.out.print("long: "); f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); System.out.println(); } void testFloat() { float x = 0; System.out.print("float: "); f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); System.out.println(); } void testDouble() { double x = 0; System.out.print("double: "); f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); System.out.println(); } public static void main(String[] args) { PrimitiveOverloading p = new PrimitiveOverloading(); p.testConstVal(); p.testChar(); p.testByte(); p.testShort(); p.testInt(); p.testLong(); p.testFloat(); p.testDouble(); } }
输出:
5: f1(int)f2(int)f3(int)f4(int)f5(long)f6(float)f7(double)
char: f1(char)f2(int)f3(int)f4(int)f5(long)f6(float)f7(double)
byte: f1(byte)f2(byte)f3(short)f4(int)f5(long)f6(float)f7(double)
short: f1(short)f2(short)f3(short)f4(int)f5(long)f6(float)f7(double)
int: f1(int)f2(int)f3(int)f4(int)f5(long)f6(float)f7(double)
long: f1(long)f2(long)f3(long)f4(long)f5(long)f6(float)f7(double)
float: f1(float)f2(float)f3(float)f4(float)f5(float)f6(float)f7(double)
double: f1(double)f2(double)f3(double)f4(double)f5(double)f6(double)f7(double)
若传入的参数类型大于方法期望接收的参数类型,你必须首先做缩窄转换,否则编译器就会报错。
经常会有人困惑,“为什么只能通过类名和参数列表,不能通过方法的返回值区分方法呢?”。例如以下两个方法,它们有相同的命名和参数,但是很容易区分:
void f(){} int f() {return 1;}
有些情况下,编译器很容易就可以从上下文准确推断出该调用哪个方法,如 int x = f()
。
但是,你可以调用一个方法且忽略返回值。这叫做调用一个函数的副作用,因为你不在乎返回值,只是想利用方法做些事。所以如果你直接调用 f()
,Java 编译器就不知道你想调用哪个方法,阅读者也不明所以。因为这个原因,所以你不能根据返回值类型区分重载的方法。为了支持新特性,Java 8 在一些具体情形下提高了猜测的准确度,但是通常来说并不起作用。
到此,相信大家对“Java为什么支持方法重载”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。