ERLEDIGT
JA
JA
ANTWORTEN
6
6
ZUGRIFFE
731
731
EMPFEHLEN
-
Hallo zusammen,
Wie ich im Netz lesen konnte ist es in Java momentan nicht möglich Funktionszeiger zu verwenden. Da ich bis vor wenigen Tagen noch praktisch nur in C# programmiert habe ist das natürlich für mich ein ziemlich grosser Schock, da mit anonymen Delegaten und anderem das Konzept der Funktionszeiger in C# sozusagen auf die Spitze getrieben wurde und ich dies auch gerne verwende.
Nun habe ich mich also gefragt was es denn für gute Alternativen gäbe. Als Beispiel habe ich folgende Situation:
Code java:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
class LogonClient { protected void handleLogonInit(byte[] data) { } protected void handleLogonProof(byte[] data) { } @Override protected void OnDataReceived(byte[] data) { if(data == null || data.length == 0) return; int opcode = data[0]; } }
Während sich hier das ganze noch relativ in Grenzen hält und über einen switch oder ein if realisierbar ist (opcode 0 -> handleLogonInit, opcode 1 -> handleLogonProof) ist es natürlich verständlich, dass in späteren Stadien meines Protokolls viel mehr hinzukommen wird. Ich würde jetzt eigentlich gerne eine assoziative Verbindung opcode -> Handlerfunktion machen.
Ich habe mal eine Variante mit anonymer Klasse gemacht, diese ist aber vom Schreibaufwand her auch nicht gerade schonend
Code java:1 2 3 4 5 6 7 8 9 10 11 12
class LogonClient { private static HashMap<Integer, IPacketFunction> mPacketFunctions; private interface IPacketFunction { public void execute(byte[] data, LogonClient client); } static { mPacketFunctions = new HashMap<Integer, IPacketFunction>(); mPacketFunctions.put(0, new IPacketFunction() { public void execute(byte[] data, LogonClient client) { client.handleLogonInit(data); } }); } }
Gibt es da noch kürzere oder elegantere Versionen?
Grüsse
MuepeViele Tutorials und Artikel zur Programmierung unter Windows mit C++ und C#. Tägliche Updates und Antworten auf eure Fragen:
Win32Easy - Blog
Es würde mich freuen, wenn ihr einen Kommentar postet!
-
14.05.11 13:48 #2
- Registriert seit
- Jun 2009
- Beiträge
- 870
Hab ich das richtig verstanden (zum 1. Codebeispiel):
Du willst Daten mit der Methode OnDataReceived() empfangen und je nach Inhalt des Parameters (byte[]) entweder handleLogonInit() oder handleLogonProof() aufrufen.
Dafür ist doch eine if-Abfrage bzw. ein switch-Block gedacht, warum nicht?Code bitte so einfügen: [java]System.out.println("Hallo");[/java] (Analog für andere Programmiersprachen)
hilfreich zu Java: Really Big Index, Java ist auch eine Insel Band 1 und Band 2.Code java:1
System.out.println("Hallo");
___________
Ubuntu Bug #1: Microsoft has a majority market share
Casecon: Projekt leiser Käse
-
14.05.11 14:18 #3SE Tutorials.de Gastzugang
Ich denke eher das TO das so änlich wie mit Reflections machen will das er dierekt per String angeben kann welche Methode zu verweden ist ... ansonsten verstehe ich so gut wie nichts aus dem Post da ich mich weder mit C noch dem geschildertem Problem auskenne ...
-
Hallo genodeftest,
Dazu habe ich in meinem Posting auch was geschrieben:
Mit "viel mehr" meine ich Sachen wie 1500 verschiedene Opcodes mit entsprechend ungefähr 1000 Handlern. Da alles mit switches bzw. if-Abfragen zu machen ist viel zu aufwändig.
In C# zum Beispiel habe ich ein Enum für alle Opcodes und kann folgenden Ansatz verwenden:
Code csharp:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
enum Opcodes { MSG_LOGON_INIT, MSG_LOGON_PROOF, } public class LogonClient { public void OnDataReceived(byte[] data) { int opcode = data[0]; if(mPacketHandlers.ContainsKey(opcode)) { var method = mPacketHandlers[opcode]; if(method != null) method.Invoke(this, data); } } public void Handle_MSG_LOGON_INIT(byte[] data) { } public void Handle_MSG_LOGON_PROOF(byte[] data) { } private static Dictionary<int, MethodInfo> mPacketHandlers = new Dictionary<int, MethodInfo>(); static LogonClient() { var values = Enum.GetValues(typeof(Opcodes)); var handler = typeof(LogonClient); foreach(var value in values) { var method = "Handle_" + value.ToString(); var info = handler.GetMethod(method); if(info != null) mPacketHandlers.Add((Opcodes)value, info); } } }
Dadurch kann ich beliebig Opcodes hinzufügen und entfernen und habe dadurch keinen zusätzlichen Schreibaufwand mehr. Ist eine von vielen Möglichkeiten wie man das realisieren kann. Sämtliche Informationen werden erst zu Laufzeit zusammengestellt.
So etwas ähnliches möchte ich auch Java machen.
Gruss
MuepeViele Tutorials und Artikel zur Programmierung unter Windows mit C++ und C#. Tägliche Updates und Antworten auf eure Fragen:
Win32Easy - Blog
Es würde mich freuen, wenn ihr einen Kommentar postet!
-
14.05.11 14:30 #5SE Tutorials.de Gastzugang
Ja ... sowas geht auch ganz gut in Java ... allerdings nur mit den sog. Reflections was eigentlich ein nicht so gutes Design ist aber für dynamischen Code das Mittel der Wahl ist.
Du kannst die via Class.getDelclearedMethodes() ein Array geben lassen das alle in dieser Klasse deklarierten Methoden enthält *wenn du alle willst verwende stattdessen Class.getMethodes()*.
Nun kannst du dir mit Methode.getName() den Methoden-Namen geben lassen ... diesen dann mit String.equals(String) vergleichen und dann fast genau so wie in deinem C-Code mittels invoke aufrufen.
Du kannst auch dierekt Methoden-Namen konstruieren ... dies meldet der Compiler aber dann mit einer UNCHECKED-WARNING ... was einfach nur aufzeigen soll das der Code leicht zum Crach gebracht werden kann wenn etwas nicht wirklich so ist wie du es zur Compile-Zeit angenommen hast. Daher ist es sicherer sich die Methoden als Array zu holen und diese abzugleichen. Dadurch hast du bei Fehlern ein etwas besseres Error-Handling weil du nicht umständlich Exceptions abfangen und parsen musst sondern dierekt mit den übergebenen Werten arbeiten kannst.
Ich habe grade leider keinen Link zu Reflections parat .. aber google sollte dir da einiges liefern.
-
Als ich das Beispiel oben schrieb habe ich auch gemerkt, dass ich ja gar keine Delegate/Funktionszeiger mehr benötige sondern alles über Reflection geregelt habe und das ja in Java auch möglich sein müsste. Mit deinen Hinweisen noch dazu habe ich das dann folgendermassen implementiert:
Code java:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
private static HashMap<Integer, Method> mPacketMethods; static { mPacketMethods = new HashMap<Integer, Method>(); Class<LogonClient> cls = LogonClient.class; Opcodes[] values = Opcodes.class.getEnumConstants(); for(Opcodes opcode : values) { String name = "handle_" + opcode.toString(); try { Method m = cls.getDeclaredMethod(name, byte[].class); mPacketMethods.put(opcode.getOpcode(), m); } catch (NoSuchMethodException e) { System.out.println("The opcode '" + opcode.toString() + "' has no handler!"); continue; } } }
Viele Tutorials und Artikel zur Programmierung unter Windows mit C++ und C#. Tägliche Updates und Antworten auf eure Fragen:
Win32Easy - Blog
Es würde mich freuen, wenn ihr einen Kommentar postet!
-
14.05.11 15:35 #7SE Tutorials.de Gastzugang
Du könntest das foreach noch um drehen in dem du
schreiben würdest und dann mitCode java:1
for(Methode method : cls.getDeclaredMethods())
oder sowas auf Vorhandensein der Methode prüfst. Wäre im Prinzip nichts anderes als der try-catch-Block ... würde aber etwas eleganter aussehen.Code java:1
if(methode.getName().equals("handle_"+opcode.toString()))
Ähnliche Themen
-
Alternative zu if-else
Von Conners im Forum Java GrundlagenAntworten: 8Letzter Beitrag: 30.10.08, 08:22 -
Alternative zu GET?
Von Vertigo21 im Forum PHPAntworten: 5Letzter Beitrag: 09.06.06, 19:15 -
Alternative zu <br /> ?
Von Boof im Forum HTML & XHTMLAntworten: 3Letzter Beitrag: 07.06.06, 13:51 -
Einen Array mit Funktionszeigern erstellen.
Von Gottox im Forum C/C++Antworten: 3Letzter Beitrag: 23.12.04, 20:22 -
Alternative pdf.ocx
Von _tYze im Forum Visual Basic 6.0Antworten: 0Letzter Beitrag: 16.09.04, 09:35





Zitieren
Login





