Przeciążenie operatora w Javie

Odpowiedzi:

235

Nie, Java nie obsługuje przeciążania operatora zdefiniowanego przez użytkownika. Jedynym aspektem Java, który zbliża się do „niestandardowego” przeciążenia operatora, jest obsługa + dla łańcuchów, co powoduje albo konkatenację stałych w czasie kompilacji, albo konkatenację w czasie wykonywania przy użyciu StringBuilder / StringBuffer. Nie można jednak zdefiniować własnych operatorów, którzy działają w ten sam sposób.

Dla Java-like (JVM i oparte na języku), który robi przeciążanie operatorów wsparcie, można spojrzeć na Kotlin lub Groovy . Alternatywnie możesz znaleźć szczęście dzięki rozwiązaniu wtyczki kompilatora Java .

Jon Skeet
źródło
4
Mówisz, że nie możemy stworzyć opakowania w Javie? Takich jak SmallInteger jak Integer?
huseyin tugrul buyukisik
3
@ tuğrulbüyükışık: Istnieją już opakowania dla wszystkich istniejących pierwotnych typów - ale jeśli chciałbyś stworzyć swój własny nowy typ opakowania, nie byłbyś w stanie sprawić, by zachowywał się jak inne, ponieważ mają one specjalne wsparcie w języku.
Jon Skeet
1
dzięki, przejrzałem o tym i nie mogłem znaleźć. Chciałem wiedzieć, czy mogę stworzyć złożoną zmienną złożoną z dwóch prymitywów (podwójnej i int ---> dobrej precyzji + dobrego zasięgu)
huseyin tugrul buyukisik 12.12
40
@djaqeel: Przeciążenie operatora powoduje, że kod jest mniej czytelny, gdy jest źle używany . Przy dobrym użyciu może znacznie poprawić czytelność IMO. Spójrz na kod, który używa BigIntegerw Javie, a następnie spójrz na podobny kod przy BigIntegerużyciu operatorów C #. Nie rozumiem, jak delegaci łamią zasady OOP - musisz być znacznie bardziej precyzyjny w swoich sprzeciwach. Nie znam szczegółów, dlaczego projektanci Java nie uwzględnili różnych funkcji, ale podejrzewam, że istnieje mieszanka presji zasobów i chęci, aby język był mały i stosunkowo prosty.
Jon Skeet
4
Wiem, że jest późno, ale przykład wart jest tysiąca argumentów. Biorąc pod uwagę, m0jak Matrixi v0, v1, v2, v3, i v4jako Vectors, wystarczy porównać jak długo to trwa, aby poprawnie zinterpretować następujące wyrażenie matematyczne m0.transpose().mult(v0.add(v1.mult(v2)).cross(v3)).sub(v4);. Gdyby uwzględniono obsługę przeciążania operatora, można by ją zapisać jako m0.transpose() * (v0 + v1 * v2).cross(v3) - v4;.
code_dredd
38

Przeciążenie operatora jest używane w Javie do konkatenacji typu String:

String concat = "one" + "two";

Nie można jednak zdefiniować przeciążeń własnego operatora.

teabot
źródło
26

Oprócz wszystkich osób wskazujących, że +jest przeciążony dla ciągów, -jest również przeciążony zarówno dla operacji zmiennoprzecinkowych, jak i liczb całkowitych, tak jak *i /.

[edit] %jest również przeciążony zmiennoprzecinkowym, co może być nieco zaskoczeniem dla osób z tłem C lub C ++.

MSalters
źródło
21

Java nie pozwala na przeciążanie operatora. Preferowanym podejściem jest zdefiniowanie metody w klasie do wykonania akcji: a.add(b)zamiast a + b. Możesz zobaczyć podsumowanie innych bitów Java pominiętych z języków podobnych do C: Funkcje usunięte z C i C ++

obrabować
źródło
2
Ważną rzeczą jest cel projektu polegający na uniezależnieniu kontekstowego pliku źródłowego Java. Próbując czytać bardzo duże (MLOC), programy C o dużej zawartości makr mają bardzo długą krzywą uczenia. Porównywalny (lub większy) program Java nie jest trudniejszy do zanurzenia niż mały program Java. Jak powiedział Gosling: język, w którym programiści powinni pracować. [I każdy, kto uważa, że ​​gadatliwość jest szkodliwa, powinien przeczytać o dzieleniu się na poziomie eksperckim].
Tim Williscroft
2
Dzięki oracle żaden z linków java.sun.com nie działa. Czy możesz podać zaktualizowany link, jeśli to możliwe?
Syed Aqeel Ashiq
17

Nie możesz tego zrobić sam, ponieważ Java nie pozwala na przeciążanie operatora.

Jednak z jednym wyjątkiem. + i + = są przeciążone dla obiektów String.

Brian Agnew
źródło
8
Istnieje wiele innych przykładów przeciążenia operatora w Javie. Na przykład &, |i ^są przeciążeniem dla booleantypów integralnych. I rzeczywiście, operatory arytmetyczne i relacyjne są przeciążone dla różnych typów liczbowych. (Oczywiście semantyka przeciążeń jest znacznie bliższa ...)
Stephen C
16

Jak wielu innych odpowiedziało: Java nie obsługuje przeciążania operatora zdefiniowanego przez użytkownika.

Może to nie na temat, ale chcę skomentować niektóre rzeczy, które czytam w niektórych odpowiedziach.

O czytelności.
Porównać:

  1. c = a + b
  2. c = a.add (b)

Spójrz ponownie!
Który jest bardziej czytelny?

Język programowania, który umożliwia tworzenie typów zdefiniowanych przez użytkownika, powinien umożliwiać im działanie w taki sam sposób, jak typy wbudowane (lub typy pierwotne).

Zatem Java łamie podstawową zasadę programowania ogólnego:
powinniśmy być w stanie wymieniać obiekty typów wbudowanych z obiektami typów zdefiniowanych przez użytkownika.
(Być może zastanawiasz się: „Czy powiedział„ obiekty wbudowane ”?”. Tak, zobacz tutaj .)

O łączeniu ciągów:

Matematycy używają symbolu + do operacji przemiennych na zbiorach.
Możemy więc być pewni, że a + b = b + a.
Łączenie łańcuchów (w większości języków programowania) nie respektuje tego wspólnego zapisu matematycznego.

a := "hello";
b := "world";
c := (a + b = b + a);

lub w Javie:

String a = "hello";
String b = "world";
boolean c = (a + b).equals(b + a);

Dodatkowo:
Zauważ, że w Javie równość i tożsamość są mylone. W == (równość) symbol oznacza:
a. Równość dla typów pierwotnych.
b. Sprawdzanie tożsamości dla typów zdefiniowanych przez użytkownika, dlatego jesteśmy zmuszeni używać funkcji equals () do równości.
Ale ... Co to ma wspólnego z przeciążeniem operatora?
Jeśli język pozwala przeciążeniu operatora, użytkownik może nadać operatorowi równości odpowiednie znaczenie.

Fernando Pelliccioni
źródło
Symbol ==służy do równości w Javie, podobnie jak w C i C ++. Nie ma to nic wspólnego z przeciążeniem operatora.
Hot Licks
2
Operator ==, w Javie oznacza tylko równość dla typów pierwotnych. Dla typów zdefiniowanych przez użytkownika oznacza Tożsamość. W C ++ semantyczny jest definiowany przez użytkownika, ale powinien zachować wbudowaną semantykę, równość. Ciąg a = „cześć”; Ciąg b = „cześć”; wartość logiczna c = (a == b);
Fernando Pelliccioni
3
Więc to, co powiedziałeś w pierwszym komentarzu, jest błędne. Dobrze? Proszę, powiedz mi, jak testować równość i tożsamość na typach zdefiniowanych przez użytkownika w C. Masz rację, mój komentarz na temat równości jest OT, ale ja to wyjaśniłem (patrz „dodatki”). Fakt, że nie stworzyłem języka programowania, nie oznacza, że ​​nie mogę krytykować istniejącego. Przykro mi, jeśli widziałeś krytykę jako wojnę religijną.
Fernando Pelliccioni
1
Krótko mówiąc: Java jest do bani.
Kolya Ivankov
6

Wystarczy użyć Xtend wraz z kodem Java. Obsługuje przeciążenie operatora:

    package com.example;

@SuppressWarnings("all")
public class Test {
  protected int wrapped;

  public Test(final int value) {
    this.wrapped = value;
  }

  public int operator_plus(final Test e2) {
    return (this.wrapped + e2.wrapped);
  }
}

package com.example

class Test2 {

    new() {
        val t1 = new Test(3)
        val t2 = new Test(5)
        val t3 = t1 + t2
    }

}

Na oficjalnej stronie znajduje się lista metod do wdrożenia dla każdego operatora!

Aurelien B.
źródło
5

Lub możesz zrobić Java Groovy i po prostu przeciążać te funkcje, aby osiągnąć to, czego chcesz

//plus() => for the + operator
//multiply() => for the * operator
//leftShift() = for the << operator
// ... and so on ...

class Fish {
    def leftShift(Fish fish) {
        print "You just << (left shifted) some fish "
    }
}


def fish = new Fish()
def fish2 = new Fish()

fish << fish2

Kto nie chce być / używać groovy? :RE

Nie, nie możesz używać skompilowanych świetnych plików JAR w Javie w ten sam sposób. Nadal jest to błąd kompilatora Java.

alknows
źródło
1

W przeciwieństwie do C ++, Java nie obsługuje przeciążania operatora zdefiniowanego przez użytkownika. Przeciążenie odbywa się wewnętrznie w java.

Możemy wziąć +(plus) na przykład:

int a = 2 + 4;
string = "hello" + "world";

Tutaj plus dodaje dwie liczby całkowite i łączy dwa ciągi. Możemy więc powiedzieć, że Java obsługuje przeciążanie operatora wewnętrznego, ale nie jest zdefiniowane przez użytkownika.

nayanjyoti sharma
źródło