@Suma Jak to może być duplikat, jeśli pytanie, o którym wspomniałeś, zostało opublikowane rok później?
Ani
1
Java 8 ma funkcję podobną do delegatów. To się nazywa lambda.
tbodt
4
@tbodt, aby być bardziej poprawnym, Java 8 ma funkcję podobną do delegatów. To się nazywa interfejsy funkcjonalne . Lambdas to jeden ze sposobów tworzenia takich delegowanych instancji (anonimowo).
nawfal
3
Poniższe odpowiedzi pochodzą z wersji wcześniejszej niż Java 8. Po opublikowaniu w języku Java 8 odpowiedzi znajdują się w tym wątku: stackoverflow.com/questions/20311779/…
Michael Lloyd Lee mlk
@nawfal, +1, ale aby być jeszcze bardziej poprawnym, Java 7 i poniżej ma już funkcję podobną do delegatów. Nazywa się to zwykłymi interfejsami.
Pacerier,
Odpowiedzi:
152
Nie, naprawdę nie.
Możesz uzyskać ten sam efekt, używając odbicia, aby uzyskać obiekty Method, które następnie możesz wywołać, a innym sposobem jest utworzenie interfejsu z pojedynczą metodą „invoke” lub „execute”, a następnie utworzenie ich instancji w celu wywołania metody jesteś zainteresowany (tj. używając anonimowej klasy wewnętrznej).
Dzięki anonimowym klasom wewnętrznym możesz nawet uniknąć deklarowania oddzielnych nazwanych klas i prawie traktować je jak prawdziwe funkcje delegowania.
// JavapublicvoidSomeMethod(ISomeBehaviour pSomeBehaviour){...}...SomeMethod(newISomeBehaviour(){@OverridepublicvoidSomeFunction(){// your implementation}});
Należy tego prawdopodobnie użyć tylko wtedy, gdy implementacja jest bardzo specyficzna dla obecnego kontekstu i nie przyniosłaby korzyści z ponownego użycia.
A potem oczywiście w Javie 8 stają się one w zasadzie wyrażeniami lambda:
// Java 8SomeMethod(()->{/* your implementation */});
+1. jest to przyzwoite obejście, a gadatliwość może zostać zrekompensowana utrzymywalnością w przyszłości.
nawfal
to jest świetne ... Obecnie pracuję nad projektem, w którym nie jestem w stanie użyć refleksji z powodu ograniczeń projektu i to obejście sprawia, że praca jest wykonywana pięknie :)
Jonathan Camarena
Czy Java ma konwencję nazewnictwa I-prefix dla interfejsów? Nie widziałem tego wcześniej
Najnowsza wersja środowiska programistycznego Microsoft Visual J ++ obsługuje konstrukcję języka o nazwie delegaci lub powiązane odwołania do metod . Konstrukcja ta oraz nowe słowa kluczowe delegatei
multicastwprowadzone w celu jej obsługi nie są częścią języka
programowania Java TM , który jest określony w specyfikacji języka Java i zmieniony w specyfikacji klas wewnętrznych zawartych w dokumentacji oprogramowania JDKTM 1.1 .
Jest mało prawdopodobne, aby język programowania Java kiedykolwiek zawierał tę konstrukcję. Firma Sun już starannie rozważała przyjęcie go w 1996 r. W zakresie budowy i odrzucania działających prototypów. Doszliśmy do wniosku, że powiązane odniesienia do metod są niepotrzebne i szkodliwe dla języka. Ta decyzja została podjęta w porozumieniu z Borland International, który miał wcześniejsze doświadczenie z powiązanymi referencjami metod w Delphi Object Pascal.
Uważamy, że powiązane odniesienia do metod są niepotrzebne, ponieważ inna alternatywa projektowa, klasy wewnętrzne , zapewnia równą lub lepszą funkcjonalność. W szczególności klasy wewnętrzne w pełni obsługują wymagania dotyczące obsługi zdarzeń interfejsu użytkownika i zostały wykorzystane do implementacji interfejsu API interfejsu użytkownika co najmniej tak kompleksowego, jak klasy Windows Foundation.
Uważamy, że powiązane odniesienia do metod są szkodliwe, ponieważ szkodzą prostocie języka programowania Java i wszechobecnemu obiektowemu charakterowi interfejsów API. Odwołania do powiązanych metod wprowadzają również nieprawidłowości w składni języka i regułach określania zakresu. Wreszcie, osłabiają one inwestycje w technologie maszyn wirtualnych, ponieważ maszyny wirtualne muszą efektywnie obsługiwać dodatkowe i różnorodne typy referencji i metody łączenia.
Jak napisano w tym, co połączył Patrick , zamiast tego chcesz użyć klas wewnętrznych.
SCdF,
16
Świetny artykuł. UWIELBIAM ich definicję „prosty”: Java jest zaprojektowana tak, aby była prostym językiem, ponieważ w „Java musi być prosta do pisania kompilatora / maszyny wirtualnej dla”, ignorując „Java musi być łatwa do pisania / czytania przez osobę” . Wiele wyjaśnia.
Juozas Kontvainis
5
Myślę, że SUN popełnił wielki błąd. Po prostu nie przekonał ich funkcjonalny paradygmat i to wszystko.
Stephane Rolland
7
@Juozas: Python został wyraźnie zaprojektowany tak, aby był łatwy do pisania / czytania przez osobę i implementuje funkcje / delegaty lambda .
Stephane Rolland
5
Zamieniono na link archive.org. To naprawdę głupie, Oracle.
Delegaci są użyteczną konstrukcją w systemach opartych na zdarzeniach. Zasadniczo Delegaci to obiekty, które kodują wysłanie metody do określonego obiektu. Ten dokument pokazuje, w jaki sposób wewnętrzne klasy Java zapewniają bardziej ogólne rozwiązanie takich problemów.
Co to jest delegat? Naprawdę jest bardzo podobny do wskaźnika do funkcji składowej stosowanej w C ++. Ale delegat zawiera obiekt docelowy wraz z metodą, która ma zostać wywołana. Idealnie byłoby miło móc powiedzieć:
obj.registerHandler (ano.methodOne);
.. i że metoda methodOne będzie wywoływana ano, gdy zostanie odebrane jakieś określone zdarzenie.
To właśnie osiąga struktura Delegata.
Klasy wewnętrzne Java
Argumentowano, że Java zapewnia tę funkcjonalność poprzez anonimowe klasy wewnętrzne, a zatem nie potrzebuje dodatkowej konstrukcji Delegata.
Na pierwszy rzut oka wydaje się to poprawne, ale jednocześnie uciążliwe. Ponieważ w wielu przykładach przetwarzania zdarzeń prostota składni Delegatów jest bardzo atrakcyjna.
Generał Handler
Jeśli jednak programowanie oparte na zdarzeniach jest stosowane w bardziej wszechstronny sposób, powiedzmy na przykład jako część ogólnego asynchronicznego środowiska programistycznego, istnieje większe ryzyko.
W takiej ogólnej sytuacji nie wystarczy podać tylko metodę docelową i instancję obiektu docelowego. Zasadniczo mogą być wymagane inne parametry, które są określane w kontekście, gdy rejestrator obsługi zdarzeń jest zarejestrowany.
W tej bardziej ogólnej sytuacji podejście java może zapewnić bardzo eleganckie rozwiązanie, szczególnie w połączeniu z użyciem zmiennych końcowych:
Zauważ, że końcowe zmienne są dostępne z poziomu anonimowych definicji metod klas. Pamiętaj, aby dokładnie przestudiować ten kod, aby zrozumieć konsekwencje. Jest to potencjalnie bardzo potężna technika. Na przykład można go wykorzystać z dobrym skutkiem podczas rejestrowania programów obsługi w MiniDOM i w bardziej ogólnych sytuacjach.
Natomiast konstrukcja Delegata nie zapewnia rozwiązania tego bardziej ogólnego wymogu i jako taka powinna zostać odrzucona jako idiom, na którym można oprzeć projekty.
Wiem, że ten post jest stary, ale Java 8 dodała lambdy i koncepcję funkcjonalnego interfejsu, którym jest dowolny interfejs z tylko jedną metodą. Razem oferują one podobną funkcjonalność jak delegaci C #. Zobacz tutaj, aby uzyskać więcej informacji, lub po prostu Google Java Lambdas.
http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html
Zaletą tego idiomu jest to, że możesz sprawdzić, czy istnieje metoda delegowana do, i że ma ona wymagany podpis w punkcie, w którym tworzysz delegującego (chociaż nie w czasie kompilacji, niestety, chociaż wtyczka FindBugs może pomoc tutaj), a następnie bezpiecznie użyj go do delegowania do różnych instancji.
Zaimplementowałem obsługę wywołania zwrotnego / delegowania w Javie za pomocą refleksji. Szczegóły i działające źródło są dostępne na mojej stronie internetowej .
Jak to działa
Istnieje klasa zasadnicza o nazwie Callback z zagnieżdżoną klasą o nazwie WithParms. Interfejs API, który wymaga wywołania zwrotnego, przyjmie obiekt Callback jako parametr i, jeśli to konieczne, utworzy Callback.WithParms jako zmienną metody. Ponieważ wiele aplikacji tego obiektu będzie rekurencyjnych, działa to bardzo czysto.
Ponieważ wydajność wciąż ma dla mnie wysoki priorytet, nie chciałem być zmuszony do tworzenia tablicy obiektów typu flip-out do przechowywania parametrów dla każdego wywołania - w końcu w dużej strukturze danych mogą być tysiące elementów, a podczas przetwarzania wiadomości scenariusz może zakończyć się przetwarzaniem tysięcy struktur danych na sekundę.
Aby być bezpiecznym dla wątków, tablica parametrów musi istnieć jednoznacznie dla każdego wywołania metody API, a dla wydajności należy używać tego samego dla każdego wywołania wywołania zwrotnego; Potrzebowałem drugiego obiektu, którego utworzenie byłoby tanie, aby połączyć wywołanie zwrotne z tablicą parametrów do wywołania. Jednak w niektórych scenariuszach wywoływacz miałby już tablicę parametrów z innych powodów. Z tych dwóch powodów tablica parametrów nie należy do obiektu wywołania zwrotnego. Również wybór wywołania (przekazanie parametrów jako tablicy lub jako pojedynczych obiektów) należy do interfejsu API za pomocą wywołania zwrotnego, umożliwiającego użycie dowolnego wywołania, które najlepiej odpowiada jego wewnętrznemu działaniu.
Klasa zagnieżdżona WithParms jest zatem opcjonalna i służy dwóm celom, zawiera tablicę obiektów parametrów potrzebną do wywołań zwrotnych i zapewnia 10 przeciążonych metod invoke () (od 1 do 10 parametrów), które ładują tablicę parametrów, a następnie wywołać cel wywołania zwrotnego.
Poniżej znajduje się przykład użycia wywołania zwrotnego do przetworzenia plików w drzewie katalogów. Jest to wstępny przebieg sprawdzania poprawności, który po prostu zlicza pliki do przetworzenia i zapewnia, że żaden nie przekroczy określonego z góry maksymalnego rozmiaru. W tym przypadku po prostu tworzymy wywołanie zwrotne w połączeniu z wywołaniem interfejsu API. Odbieramy jednak metodę docelową jako wartość statyczną, aby odbicie nie było wykonywane za każdym razem.
staticprivatefinalMethod COUNT =Callback.getMethod(Xxx.class,"callback_count",true,File.class,File.class);...IoUtil.processDirectory(root,newCallback(this,COUNT),selector);...privatevoid callback_count(File dir,File fil){if(fil!=null){// file is null for processing a directory
fileTotal++;if(fil.length()>fileSizeLimit){thrownewAbort("Failed","File size exceeds maximum of "+TextUtil.formatNumber(fileSizeLimit)+" bytes: "+fil);}}
progress("Counting",dir,fileTotal);}
IoUtil.processDirectory ():
/**
* Process a directory using callbacks. To interrupt, the callback must throw an (unchecked) exception.
* Subdirectories are processed only if the selector is null or selects the directories, and are done
* after the files in any given directory. When the callback is invoked for a directory, the file
* argument is null;
* <p>
* The callback signature is:
* <pre> void callback(File dir, File ent);</pre>
* <p>
* @return The number of files processed.
*/staticpublicint processDirectory(File dir,Callback cbk,FileSelector sel){return _processDirectory(dir,newCallback.WithParms(cbk,2),sel);}staticprivateint _processDirectory(File dir,Callback.WithParms cbk,FileSelector sel){int cnt=0;if(!dir.isDirectory()){if(sel==null|| sel.accept(dir)){ cbk.invoke(dir.getParent(),dir); cnt++;}}else{
cbk.invoke(dir,(Object[])null);File[] lst=(sel==null? dir.listFiles(): dir.listFiles(sel));if(lst!=null){for(int xa=0; xa<lst.length; xa++){File ent=lst[xa];if(!ent.isDirectory()){
cbk.invoke(dir,ent);
lst[xa]=null;
cnt++;}}for(int xa=0; xa<lst.length; xa++){File ent=lst[xa];if(ent!=null){ cnt+=_processDirectory(ent,cbk,sel);}}}}return cnt;}
Ten przykład ilustruje piękno tego podejścia - logika specyficzna dla aplikacji jest abstrakcyjna w wywołaniu zwrotnym, a hałaśliwość rekurencyjnego chodzenia po drzewie katalogów jest ładnie schowana w całkowicie statycznej metodzie użyteczności wielokrotnego użytku. I nie musimy wielokrotnie płacić ceny za zdefiniowanie i wdrożenie interfejsu dla każdego nowego zastosowania. Oczywiście argument za interfejsem jest to, że jest ono o wiele bardziej wyraźne na temat tego, co należy wdrożyć (jest wymuszone, a nie tylko udokumentowane) - ale w praktyce nie stwierdziłem, że jest problem z prawidłową definicją wywołania zwrotnego.
Definiowanie i implementacja interfejsu nie jest wcale taka zła (chyba, że dystrybuujesz aplety, tak jak ja, gdzie unikanie tworzenia dodatkowych klas naprawdę ma znaczenie), ale to naprawdę świeci, gdy masz wiele wywołań zwrotnych w jednej klasie. Nie tylko jest zmuszany do popchnięcia ich do osobnej klasy wewnętrznej dodanej narzutu we wdrożonej aplikacji, ale programowanie jest wręcz żmudne, a cały kod płyty kotłowej jest po prostu „hałasem”.
Tak i nie, ale można by pomyśleć o takim schemacie delegowania w Javie. Ten samouczek wideo dotyczy wymiany danych między fragmentami aktywności i ma wielką istotę delegowania sortowania wzorca za pomocą interfejsów.
Nie ma jawnego delegatesłowa kluczowego jako C #, ale można osiągnąć podobne w Javie 8, używając interfejsu funkcjonalnego (tj. Dowolnego interfejsu z dokładnie jedną metodą) i lambda:
privateinterfaceSingleFunc{void printMe();}publicstaticvoid main(String[] args){SingleFunc sf =()->{System.out.println("Hello, I am a simple single func.");};SingleFunc sfComplex =()->{System.out.println("Hello, I am a COMPLEX single func.");};
delegate(sf);
delegate(sfComplex);}privatestaticvoid delegate(SingleFunc f){
f.printMe();}
Każdy nowy obiekt typu SingleFuncmusi zostać zaimplementowany printMe(), więc można bezpiecznie przekazać go do innej metody (np. delegate(SingleFunc)) W celu wywołania printMe()metody.
Chociaż ten link może odpowiedzieć na pytanie, lepiej dołączyć tutaj istotne części odpowiedzi i podać link w celach informacyjnych. Odpowiedzi zawierające tylko łącze mogą stać się nieprawidłowe, jeśli połączona strona ulegnie zmianie.
StackFlowed
2
@StackFlowed Zdejmij link i co otrzymasz? Post z informacją. Głosuj, aby zachować.
Scimonster,
1
@ Scimonster, co by się stało, gdyby link już nie był ważny?
StackFlowed
@StackFlowed Nadal zapewnia odpowiedź - użyj serwera proxy Java.
Scimonster
to może być pozostawiony jako komentarz?
StackFlowed
0
Nie, ale wewnętrznie ma podobne zachowanie.
W języku C # delegaty są używane do tworzenia osobnego punktu wejścia i działają podobnie jak wskaźnik funkcji.
W Javie nie ma czegoś takiego jak wskaźnik funkcji (w wyglądzie górnym), ale wewnętrznie Java musi zrobić to samo, aby osiągnąć te cele.
Na przykład tworzenie wątków w Javie wymaga klasy rozszerzającej wątek lub implementującej Runnable, ponieważ zmiennej obiektu klasy można użyć wskaźnika lokalizacji pamięci.
Opisany kod oferuje wiele zalet delegatów C #. Metody, zarówno statyczne, jak i dynamiczne, można traktować w jednolity sposób. Złożoność wywoływania metod poprzez refleksję jest zmniejszona, a kod nadaje się do wielokrotnego użytku, co oznacza, że nie wymaga żadnych dodatkowych klas w kodzie użytkownika. Uwaga: nazywamy alternatywną wygodną wersję invoke, w której można wywołać metodę z jednym parametrem bez tworzenia tablicy obiektów. Kod Java poniżej:
Java nie ma delegatów i jest z tego dumna :). Z tego, co tu przeczytałem, znalazłem w istocie 2 sposoby na sfałszowanie delegatów: 1. odbicie; 2. klasa wewnętrzna
Refleksje są powolne! Klasa wewnętrzna nie obejmuje najprostszego przypadku użycia: funkcji sortowania. Nie chcę wchodzić w szczegóły, ale rozwiązaniem z klasą wewnętrzną jest w zasadzie utworzenie klasy opakowania dla tablicy liczb całkowitych do sortowania w kolejności rosnącej i klasy dla tablicy liczb całkowitych do sortowania w kolejności malejącej.
Odpowiedzi:
Nie, naprawdę nie.
Możesz uzyskać ten sam efekt, używając odbicia, aby uzyskać obiekty Method, które następnie możesz wywołać, a innym sposobem jest utworzenie interfejsu z pojedynczą metodą „invoke” lub „execute”, a następnie utworzenie ich instancji w celu wywołania metody jesteś zainteresowany (tj. używając anonimowej klasy wewnętrznej).
Ten artykuł może być również interesujący / przydatny: programista Java patrzy na delegatów C # (@ archive.org)
źródło
Zależnie od tego, co masz na myśli, możesz osiągnąć podobny efekt (omijając metodę) za pomocą Wzorca Strategii.
Zamiast linii takiej jak ta deklarująca nazwaną sygnaturę metody:
zadeklaruj interfejs:
Dla konkretnych implementacji metody zdefiniuj klasę, która implementuje zachowanie:
Następnie, gdziekolwiek miałbyś
SomeFunction
delegata w C #,ISomeBehaviour
zamiast tego użyj odwołania:Dzięki anonimowym klasom wewnętrznym możesz nawet uniknąć deklarowania oddzielnych nazwanych klas i prawie traktować je jak prawdziwe funkcje delegowania.
Należy tego prawdopodobnie użyć tylko wtedy, gdy implementacja jest bardzo specyficzna dla obecnego kontekstu i nie przyniosłaby korzyści z ponownego użycia.
A potem oczywiście w Javie 8 stają się one w zasadzie wyrażeniami lambda:
źródło
Krótka historia: nie .
źródło
Czytałeś to :
źródło
Wiem, że ten post jest stary, ale Java 8 dodała lambdy i koncepcję funkcjonalnego interfejsu, którym jest dowolny interfejs z tylko jedną metodą. Razem oferują one podobną funkcjonalność jak delegaci C #. Zobacz tutaj, aby uzyskać więcej informacji, lub po prostu Google Java Lambdas. http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html
źródło
Nie, ale można je sfałszować przy użyciu serwerów proxy i refleksji:
Zaletą tego idiomu jest to, że możesz sprawdzić, czy istnieje metoda delegowana do, i że ma ona wymagany podpis w punkcie, w którym tworzysz delegującego (chociaż nie w czasie kompilacji, niestety, chociaż wtyczka FindBugs może pomoc tutaj), a następnie bezpiecznie użyj go do delegowania do różnych instancji.
Zobacz kod karg na github, aby uzyskać więcej testów i implementacji .
źródło
Zaimplementowałem obsługę wywołania zwrotnego / delegowania w Javie za pomocą refleksji. Szczegóły i działające źródło są dostępne na mojej stronie internetowej .
Jak to działa
Istnieje klasa zasadnicza o nazwie Callback z zagnieżdżoną klasą o nazwie WithParms. Interfejs API, który wymaga wywołania zwrotnego, przyjmie obiekt Callback jako parametr i, jeśli to konieczne, utworzy Callback.WithParms jako zmienną metody. Ponieważ wiele aplikacji tego obiektu będzie rekurencyjnych, działa to bardzo czysto.
Ponieważ wydajność wciąż ma dla mnie wysoki priorytet, nie chciałem być zmuszony do tworzenia tablicy obiektów typu flip-out do przechowywania parametrów dla każdego wywołania - w końcu w dużej strukturze danych mogą być tysiące elementów, a podczas przetwarzania wiadomości scenariusz może zakończyć się przetwarzaniem tysięcy struktur danych na sekundę.
Aby być bezpiecznym dla wątków, tablica parametrów musi istnieć jednoznacznie dla każdego wywołania metody API, a dla wydajności należy używać tego samego dla każdego wywołania wywołania zwrotnego; Potrzebowałem drugiego obiektu, którego utworzenie byłoby tanie, aby połączyć wywołanie zwrotne z tablicą parametrów do wywołania. Jednak w niektórych scenariuszach wywoływacz miałby już tablicę parametrów z innych powodów. Z tych dwóch powodów tablica parametrów nie należy do obiektu wywołania zwrotnego. Również wybór wywołania (przekazanie parametrów jako tablicy lub jako pojedynczych obiektów) należy do interfejsu API za pomocą wywołania zwrotnego, umożliwiającego użycie dowolnego wywołania, które najlepiej odpowiada jego wewnętrznemu działaniu.
Klasa zagnieżdżona WithParms jest zatem opcjonalna i służy dwóm celom, zawiera tablicę obiektów parametrów potrzebną do wywołań zwrotnych i zapewnia 10 przeciążonych metod invoke () (od 1 do 10 parametrów), które ładują tablicę parametrów, a następnie wywołać cel wywołania zwrotnego.
Poniżej znajduje się przykład użycia wywołania zwrotnego do przetworzenia plików w drzewie katalogów. Jest to wstępny przebieg sprawdzania poprawności, który po prostu zlicza pliki do przetworzenia i zapewnia, że żaden nie przekroczy określonego z góry maksymalnego rozmiaru. W tym przypadku po prostu tworzymy wywołanie zwrotne w połączeniu z wywołaniem interfejsu API. Odbieramy jednak metodę docelową jako wartość statyczną, aby odbicie nie było wykonywane za każdym razem.
IoUtil.processDirectory ():
Ten przykład ilustruje piękno tego podejścia - logika specyficzna dla aplikacji jest abstrakcyjna w wywołaniu zwrotnym, a hałaśliwość rekurencyjnego chodzenia po drzewie katalogów jest ładnie schowana w całkowicie statycznej metodzie użyteczności wielokrotnego użytku. I nie musimy wielokrotnie płacić ceny za zdefiniowanie i wdrożenie interfejsu dla każdego nowego zastosowania. Oczywiście argument za interfejsem jest to, że jest ono o wiele bardziej wyraźne na temat tego, co należy wdrożyć (jest wymuszone, a nie tylko udokumentowane) - ale w praktyce nie stwierdziłem, że jest problem z prawidłową definicją wywołania zwrotnego.
Definiowanie i implementacja interfejsu nie jest wcale taka zła (chyba, że dystrybuujesz aplety, tak jak ja, gdzie unikanie tworzenia dodatkowych klas naprawdę ma znaczenie), ale to naprawdę świeci, gdy masz wiele wywołań zwrotnych w jednej klasie. Nie tylko jest zmuszany do popchnięcia ich do osobnej klasy wewnętrznej dodanej narzutu we wdrożonej aplikacji, ale programowanie jest wręcz żmudne, a cały kod płyty kotłowej jest po prostu „hałasem”.
źródło
Tak i nie, ale można by pomyśleć o takim schemacie delegowania w Javie. Ten samouczek wideo dotyczy wymiany danych między fragmentami aktywności i ma wielką istotę delegowania sortowania wzorca za pomocą interfejsów.
źródło
Nie ma jawnego
delegate
słowa kluczowego jako C #, ale można osiągnąć podobne w Javie 8, używając interfejsu funkcjonalnego (tj. Dowolnego interfejsu z dokładnie jedną metodą) i lambda:Każdy nowy obiekt typu
SingleFunc
musi zostać zaimplementowanyprintMe()
, więc można bezpiecznie przekazać go do innej metody (np.delegate(SingleFunc)
) W celu wywołaniaprintMe()
metody.źródło
Chociaż nie jest to tak czyste, ale można zaimplementować coś w rodzaju delegatów C # przy użyciu serwera proxy Java .
źródło
Nie, ale wewnętrznie ma podobne zachowanie.
W języku C # delegaty są używane do tworzenia osobnego punktu wejścia i działają podobnie jak wskaźnik funkcji.
W Javie nie ma czegoś takiego jak wskaźnik funkcji (w wyglądzie górnym), ale wewnętrznie Java musi zrobić to samo, aby osiągnąć te cele.
Na przykład tworzenie wątków w Javie wymaga klasy rozszerzającej wątek lub implementującej Runnable, ponieważ zmiennej obiektu klasy można użyć wskaźnika lokalizacji pamięci.
źródło
Nie, Java nie ma tej niesamowitej funkcji. Ale możesz utworzyć go ręcznie, używając wzorca obserwatora. Oto przykład: napisz delegata C # w Javie
źródło
Opisany kod oferuje wiele zalet delegatów C #. Metody, zarówno statyczne, jak i dynamiczne, można traktować w jednolity sposób. Złożoność wywoływania metod poprzez refleksję jest zmniejszona, a kod nadaje się do wielokrotnego użytku, co oznacza, że nie wymaga żadnych dodatkowych klas w kodzie użytkownika. Uwaga: nazywamy alternatywną wygodną wersję invoke, w której można wywołać metodę z jednym parametrem bez tworzenia tablicy obiektów. Kod Java poniżej:
źródło
Java nie ma delegatów i jest z tego dumna :). Z tego, co tu przeczytałem, znalazłem w istocie 2 sposoby na sfałszowanie delegatów: 1. odbicie; 2. klasa wewnętrzna
Refleksje są powolne! Klasa wewnętrzna nie obejmuje najprostszego przypadku użycia: funkcji sortowania. Nie chcę wchodzić w szczegóły, ale rozwiązaniem z klasą wewnętrzną jest w zasadzie utworzenie klasy opakowania dla tablicy liczb całkowitych do sortowania w kolejności rosnącej i klasy dla tablicy liczb całkowitych do sortowania w kolejności malejącej.
źródło