为什么我应该重载方法?
我在我的重载方法书中发现了两个例子,但是它并没有清楚地解释为什么它是有用的:
package keepo; public class Main{ public static void main(String [] args) { int newScore = calculateScore("Tim", 500); System.out.println("New Score is" + newScore); calculateScore(75); } public static int calculateScore(String playerName, int score){ System.out.println("Player" + playerName +"Has score" + score); return score * 1000; } public static int calculateScore(int score){ System.out.println("Unnamed player scored" + score + "points"); return score * 1000; } }
这很简单,但老实说,在这里重载方法似乎是无用的,而且似乎只是为了这样做而做的。
本书的下一个例子是方法重载,这似乎更有用,因为这个程序计算英尺到厘米,有一种方法,你可以放在脚和英寸,一种方法,你可以把英寸。 但是,对于这两种方法来说,看起来还是很容易的。
这就是说,这样做有没有真正的好处? (我读过这个 ,但是我不是很满意,看起来很简单。)
我想如果你谈论函数/方法重载的真正好处,那么没有它的东西你不会绕过,那么就像你在你的问题中指出的一样,你不会find任何东西。
但是它有帮助吗? 我们来考虑一下这个例子。
假设我正在制作一个应用程序,用他的名字find一个人,然后我声明并定义一个方法
public Person[] findPerson(String name)
现在我们得到一个要求,我们必须根据他的出生datefind一个人,所以引入一个新的方法
public Person[] findPerson_byDOB(Date date)
让我们假设这继续下去,我们的应用程序中有很多方法。
public Person[] findPerson(String name) public Person[] findPerson_byDOB(Date date) public Person[] findPerson_byAddress(Address address) public Person[] findPerson_bySSN(SSN ssn) public Person[] findPerson_byDepartment(Department department) public Person[] findPerson_byMobile(Mobile mobile)
这只是一个部分; 当我们被要求引入多个参数时,这可以继续
public Person[] findPerson_byMobileAndAddress(Mobile mobile, Address address) public Person[] findPerson_byAddressAndDepartment(Address address, Department department) public Person[] findPerson_byDOBAndDepartment(DOB dob, Department, department) public Person[] findPerson_byAddressAndDOB(Address address, DOB dob)
和许多更多…
虽然这看起来有些夸张,但相信我,在制定实际的行业级应用程序时,我们可能会遇到这样的情况,当我们得到上百种这样的方法时,最终我们需要一个所有这些方法的目录他们究竟做了什么
这实际上是一个噩梦,当我们不得不使用它的时候,我们必须find所有这些方法的名字。
但是,当所有参数不同时,我们可以给函数赋予相同的名称,并且真的变得非常容易记住。
public Person[] findPerson(String name) public Person[] findPerson(Date date) public Person[] findPerson(Address address) public Person[] findPerson(SSN ssn) public Person[] findPerson(Department department) public Person[] findPerson(Mobile mobile) public Person[] findPerson(Mobile mobile, Address address) public Person[] findPerson(Address address, Department department) public Person[] findPerson(DOB dob, Department, department) public Person[] findPerson(Address address, DOB dob)
现在大卫在他的回答中指出,我们都知道如何获得整数的String
值; 可能我们已经在某处读过了。
static String.valueOf(new Integer(1));
但是你知道还有多less方法是用同一个名字重载吗?
static String.valueOf(boolean b) static String.valueOf(char c) static String.valueOf(char[] data) static String.valueOf(double d) static String.valueOf(float f) static String.valueOf(int i) static String.valueOf(long l) static String.valueOf(Object obj)
好处是你不必记住所有的东西。 你甚至不用猜,因为它一直是同一个名字。
编辑 根据Namnodorel的build议
考虑这个PrintStream
类的重载方法。
void println() void println(boolean x) void println(char x) void println(char[] x) void println(double x) void println(float x) void println(int x) void println(long x) void println(Object x) void println(String x)
如果我们必须写下来,请考虑一下可读性:
void println_emptyLine() void println_boolean(boolean x) void println_character(char x) void println_characterArray(char[] x) void println_double(double x) void println_float(float x) void println_integer(int x) void println_long(long x) void println_object(Object x) void println_string(String x)
当您使用不同types的值执行相同操作的方法时,重载非常有用。
Math
课提供了一个完美的例子 – 它有function过载的types – 四个abs
,四min
,四个max
,等等:
int max(int a, int b) {...} float max(float a, float b) {...} long max(long a, long b) {...} double max(double a, double b) {...}
没有重载的替代方法会迫使你将types“编码”为你的方法的名字,例如Math.intMax(a, b)
,这对用户代码的可读性是有害的。
简单而简洁:重载只是由Java提供的一种可能性(但大多数现代和灵活的语言都使用它) (和其他语言,如C ++或C#),以允许开发人员创build相同的方法/函数名称,它。
为什么?
因为方法命名是重要的,方法命名应该传达它的行为。 所以,如果两个方法具有相同的行为(例如转换为string),但是一个使用long作为input,而另一个使用int作为input,为什么使用不同的方法名?
String myString = String.valueOf(new Integer(1)); String myOtherString = String.valueOf(new Long(2));
意图和目标是一样的,只是input参数的改变。
当重载是有意义的,你应该使用它,而不是创build一些变体笨拙的名字。
方法重载在以下情形中很有用:
考虑你有一个跟踪名单列表的类。 你有上面的代码样式,每个方法都有自己的对这个名字列表的操作。
突然间,列表的内部表示发生了变化(可能从一个array
到一个ArrayList
,这并不重要)。 你想成为每一个负责重构的人吗? 单身 。 方法?
方法重载是有用的,因为那么你可以通过一个单一的generics方法来路由所有的操作。 这意味着每当内部表示发生变化时,您只需更改该generics方法,而其他所有专用方法的工作方式仍然相同。
另外,考虑你提供的例子。 如果你想改变程序如何打印信息会发生什么? 你将不得不修改两种方法来打印相同types的消息,这是一个维护的噩梦。 当然,现在看起来很小,但是想想你的项目在何时发展,并且你开始有更多的方法依赖于这个(有效的)消息格式。
我是一个对象,我有能力,能力是固定的,但可以接受各种参数。
如果能力可以接受1000种参数,你是否想绞尽脑汁考虑1000个能力名称?
把别人的post作为一个重载的好习惯,拿JNIEnv做为不好的做法,因为C不支持重载。
CallStaticObjectMethod, CallStaticObjectMethodV, CallStaticObjectMethodA, CallStaticBooleanMethod, CallStaticBooleanMethodV, CallStaticBooleanMethodA, CallStaticByteMethod, CallStaticByteMethodV, CallStaticByteMethodA, CallStaticCharMethod, CallStaticCharMethodV, CallStaticCharMethodA, CallStaticShortMethod, CallStaticShortMethodV, CallStaticShortMethodA, CallStaticIntMethod, CallStaticIntMethodV, CallStaticIntMethodA, CallStaticLongMethod, CallStaticLongMethodV, CallStaticLongMethodA, CallStaticFloatMethod, CallStaticFloatMethodV, CallStaticFloatMethodA, CallStaticDoubleMethod, CallStaticDoubleMethodV, CallStaticDoubleMethodA, CallStaticVoidMethod, CallStaticVoidMethodV, CallStaticVoidMethodA,
Reger到JNI以获得更详细的结构定义
超载的另一个原因是提供一个或多个默认参数。
考虑以下:
class Something { // Imagine that this is a real class, that does real work. public void doSomething(boolean b, char c, double d, int i) { // Imagine that this is one of the main components of class Something. System.out.println("Hi. You passed: " + b + ", " + c + ", " + d + ", and " + i + "."); } public void doSomething(boolean b, char c, double d) { doSomething(b, c, d, 42); } public void doSomething(boolean b, char c) { doSomething(b, c, 1.3579); } public void doSomething(boolean b) { doSomething(b, 'q'); } public void doSomething() { doSomething(true); } }
在这个例子中,每个重载提供了其中一个参数的默认值,将它们链接在一起,直到完全调用实际完成工作的doSomething()
版本。
Something s = new Something(); Something t = new Something(); Something u = new Something(); // ... s.doSomething(true, 'c', 2.9); t.doSomething(false, 'z'); u.doSomething();
看这里的例子。