Java nie obsługuje bezpośredniego przeciążania operatorów tak, jak ma to miejsce np. w C++. Historycznie to ograniczenie zostało wprowadzone, aby uprościć czytanie kodu i zmniejszyć niejednoznaczność: Bjarne Stroustrup (twórca C++) oraz James Gosling (twórca Javy) omawiali tę kwestię i w Javie podjęto decyzję, by nie pozwalać programistom na definiowanie własnego zachowania operatorów dla ich klas.
Problem z przeciążaniem operatorów polega na tym, że nadmiar swobody w definiowaniu arytmetyki i logiki dla klas użytkowników może prowadzić do trudnych do śledzenia błędów oraz pogorszenia czytelności kodu, zwłaszcza w dużych zespołach.
Rozwiązanie — zabronić użytkownikom przeciążania operatorów. Niemniej jednak, Java wewnątrz swoich klas obsługuje przeciążanie metod, a zachowanie operatorów może być symulowane przez wyraźnie zdefiniowane metody (np. .add(), .equals(), .compareTo() itd.).
Przykład kodu:
public class Vector2D { private final int x, y; public Vector2D(int x, int y) { this.x = x; this.y = y; } public Vector2D add(Vector2D other) { return new Vector2D(this.x + other.x, this.y + other.y); } } Vector2D v1 = new Vector2D(2, 3); Vector2D v2 = new Vector2D(1, 4); Vector2D sum = v1.add(v2); // zamiast v1 + v2
Kluczowe cechy:
Czy można w Javie przeciążyć operator "+" dla własnej klasy, aby sumować obiekty?
Odpowiedź: Nie, Java nie obsługuje przeciążania użytkownika operatorów arytmetycznych dla tworzonych klas. Wyjątek stanowi jednak łańcuchy znaków: operator "+" wywołuje konkatenację przez StringBuilder.
Jeśli zdefiniuję metodę equals(), czy operator "==" będzie działał jako porównanie wartości?
Odpowiedź: Nie, operator "==" porównuje odnośniki do obiektów, a nie ich zawartość. Do poprawnego porównania wartości należy użyć nadpisanego equals().
String a = new String("hello"); String b = new String("hello"); System.out.println(a == b); // false System.out.println(a.equals(b)); // true
Czy istnieją wyjątki, gdzie standardowy operator działa w szczególny sposób dla niestandardowych klas?
Odpowiedź: "Szczególne" zachowanie w Javie zaimplementowano tylko dla String z operatorem "+" oraz dla typów prymitywnych (automatyczne promowanie i unboxing). Dla pozostałych klas operatorzy działają standardowo (tj. nie są przeciążani).
Młody programista napisał klasę Money i zaczął porównywać dwa obiekty przez "==", sądząc, że zostaną porównane według wartości. Z tego powodu pojawiły się błędy przy sprawdzaniu równości, które ujawniały się dopiero w produkcji.
Zalety:
Wady:
W projekcie stworzono własną klasę Vector, wszystkie operacje arytmetyczne zostały zrealizowane wyraźnie, operator == nie jest używany dla obiektów, a dokumentacja opisuje semantykę działania metod.
Zalety:
Wady: