Перегрузка методов в Java
Перегрузка (overloading) — это объявление в одном классе нескольких методов с одинаковым именем, но разными списками параметров. Компилятор выбирает нужный метод во время компиляции, исходя из типов и числа аргументов в месте вызова.
Перегрузка делает API класса удобнее: пользователь вызывает «одно и то же действие» в разных формах — например, print(), print(int x), print(String s). В библиотеках Java перегрузка встречается повсюду — System.out.println(...) имеет более десятка перегрузок.
Важно: тип возвращаемого значения не входит в сигнатуру перегрузки. Два метода, различающиеся только типом результата, компилироваться не будут.
Правила различения
Методы можно перегружать, если они отличаются:
числом параметров;
типами параметров;
порядком параметров.
Не различает перегрузку:
имя параметра;
тип возвращаемого значения;
модификаторы (
public,staticи т. д.).
Пример 1. Различия по числу параметров
public class Led {
void on() {
System.out.println("LED ON (default)");
}
void on(int pin) {
System.out.println("LED ON pin=" + pin);
}
void on(int pin, int brightness) {
System.out.println("LED ON pin=" + pin + " brightness=" + brightness);
}
public static void main(String[] args) {
Led led = new Led();
led.on();
led.on(13);
led.on(9, 128);
}
}
Output:
LED ON (default)
LED ON pin=13
LED ON pin=9 brightness=128
Пример 2. Различия по типам параметров
public class Printer {
void print(int x) {
System.out.println("int: " + x);
}
void print(double x) {
System.out.println("double: " + x);
}
void print(String x) {
System.out.println("String: " + x);
}
public static void main(String[] args) {
Printer p = new Printer();
p.print(42);
p.print(3.14);
p.print("hello");
}
}
Output:
int: 42
double: 3.14
String: hello
Пример 3. Перегрузка конструкторов
public class Sensor {
String type;
int pin;
public Sensor() {
this("generic", -1);
}
public Sensor(String type) {
this(type, -1);
}
public Sensor(String type, int pin) {
this.type = type;
this.pin = pin;
}
void info() {
System.out.println(type + " на пине " + pin);
}
public static void main(String[] args) {
new Sensor().info();
new Sensor("DHT22").info();
new Sensor("BH1750", 14).info();
}
}
Output:
generic на пине -1
DHT22 на пине -1
BH1750 на пине 14
Пример 4. Различия по порядку параметров
public class Robot {
void move(int speed, String direction) {
System.out.println("speed=" + speed + " dir=" + direction);
}
void move(String direction, int speed) {
System.out.println("dir=" + direction + " speed=" + speed);
}
public static void main(String[] args) {
Robot r = new Robot();
r.move(150, "forward");
r.move("backward", 100);
}
}
Output:
speed=150 dir=forward
dir=backward speed=100
Пример 5. Автоматическое расширение типа
public class Calc {
static void show(int x) {
System.out.println("int: " + x);
}
static void show(long x) {
System.out.println("long: " + x);
}
static void show(double x) {
System.out.println("double: " + x);
}
public static void main(String[] args) {
show(10); // int
show(10L); // long
show(10.0); // double
short s = 5;
show(s); // расширится до int
}
}
Output:
int: 10
long: 10
double: 10.0
int: 5
Пример 6. Перегрузка статических методов
public class MathUtils {
static int max(int a, int b) {
return a > b ? a : b;
}
static int max(int a, int b, int c) {
return max(max(a, b), c);
}
static double max(double a, double b) {
return a > b ? a : b;
}
public static void main(String[] args) {
System.out.println(max(3, 5));
System.out.println(max(3, 5, 7));
System.out.println(max(1.5, 2.7));
}
}
Output:
5
7
2.7
Подводные камни
Перегрузка решается на этапе компиляции по статическим типам аргументов. Это не то же самое, что переопределение (
@Override), которое работает на этапе исполнения по фактическому типу объекта.Тип результата не различает перегрузки:
int sum(int a)иdouble sum(int a)в одном классе — ошибка компиляции.При перегрузке с
nullкомпилятор может «не понять», какой метод вы хотите — приводите явно:print((String) null).autoboxingи расширение типа создают неочевидные приоритеты выбора метода. Лучше избегать пар вродеf(Integer)иf(long).Сильно перегруженные API трудно читать — иногда лучше дать методам разные имена.
См. также
Примечание
Лицензия и источники
Концепция описана на основе официального Java Tutorial от Oracle (https://docs.oracle.com/javase/tutorial/), Oracle Free Documentation License. Перевод, примеры и пояснения — © AlashEd Wiki.