Click here to Skip to main content
Click here to Skip to main content

Delegates, Events and Pass by ref in Java using bytecode manipulation

, 15 May 2012
Rate this:
Please Sign up or sign in to vote.
Support for Delegates, Events and Pass by ref in Java using bytecode manipulation

Introduction 

C# language has come up with some very beautiful features where Java is lacking. People are still able to manage but having those in Java would make life of the developers much easy. Recently, I found Javassist library which is able to manipulate bytecode and compile classes at runtime. Using that I was able to implement some of the features. 

Delegate 

A delegate is a type that references a method. 

C# declaration

public delegate int PerformCalculation(int x, int y);

Equivalent Java declaration 

public abstract class PerformCalculation extends csharp.Delegate {
    public abstract int invoke(int x, int y);
}

C# instantiation 

PerformCalculation performCalculation = new PerformCalculation(this.myMethod); //instance 
PerformCalculation performCalculation = new PerformCalculation(AClass.myMethod); //static  

Equivalent Java instantiation  

PerformCalculation performCalculation = Delegate.<PerformCalculation> getInstance(PerformCalculation.class, this, "myMethod"); //instance  
PerformCalculation performCalculation = Delegate.<PerformCalculation> getInstance(PerformCalculation.class, AClass.class, "myMethod"); //static 

You can just call invoke of the performCalculation object. A new delegate class is created on runtime for each AClass type used (but only once throughout the life of the application). 

Requirements 

  1. The declared 'Delegate' class and 'invoke' method should be 'public abstract'. 
  2. Signature of the 'invoke' method should match to that of 'myMethod' function.
  3. Only one 'invoke' method should be present. 
  4. It would be better if 'myMethod' function is public or protected else reflection is used which may have performance issues. 

Event 

An event in C# is a way for a class to provide notifications to clients of that class when some interesting thing happens to an object. This is actually list of delegates. 

C# declaration/instantiation

public event PerformCalculation myEvent; 

Equivalent Java declaration 

public abstract class MyEvent<D extends PerformCalculation> extends csharp.Event<D> {
    public abstract int invoke(int x, int y);
}

Equivalent Java instantiation 

MyEvent<PerformCalculation> performEvent = Event.<MyEvent<PerformCalculation>> getInstance(MyEvent.class, PerformCalculation.class); 

You can now add PerformCalculation delegates to performEvent object by calling its 'add' method. Calling invoke of the performEvent object which will call invoke of all the delegates added.

Requirements 

  1. The declared 'Event' class and 'invoke' method should be 'public abstract'. 
  2. Signature of the 'invoke' method should match to that of delegates to be added.
  3. Only one 'invoke' method should be present. 

Pass by ref

The ref keyword in C# causes an argument to be passed by reference. This feature is not available in Java. It means if this is available in future primitive types will be passed by reference and objects will be passed by reference of a reference (by default reference of object is passed).

So, following would not change the original variable. 

list = new ArrayList(); 

But the 'list' variable will point to a new memory location. For this, I have included few wrapper classes (one of each primitive type and one with generics for objects) in my code that can be used to pass reference and get it back. This is nothing new but included them in the code just in case somebody wants to use this feature.

Notes 

If you are hardcore Java developer please read about events and delegates. You may not appreciate these features till you have actually used them in your code.

Update 

  1. Use of class.getCanonicalName instead of class.getName. The latter had issues in case of inner classes. 
  2. There is no need of writing dynamically compiled classes to filesystem.  

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

abhinav_soni

India India
No Biography provided

Comments and Discussions

 
QuestionReason for my vote of 3 and some comments PinmemberRoger Norling16-May-12 2:32 
I gave a vote of 3 because execution of the idea is rather good, but as for the idea itself it's a bit unnecessary.
 
What it comes down to is the different advantages between delegates in c# and anonymous objects in Java. The strength of delegates comes from enabling diverse objects to act on a named type of change in a particular class. The strength of anonymous objects is in more easily driving iterative design. An interface can quickly be implemented to get tests to pass and then immediately expanded in the next step.
 
There is no real need to implement an equivalent to delegates and events in java since the observer design pattern already exists and it even have an implementation in the java standard library. In this respect I rather find c# to be lacking since implementing an interface require a complete class declaration (as stand alone or as an inner member).
 
As for your code I need to point out that using the hash code as a key is a hidden bug. Equal values do produce the same 32 bit value, but there is no guarantee that different strings wouldn't produce a collision. Use the string you form from the class names as the key instead.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140821.2 | Last Updated 15 May 2012
Article Copyright 2012 by abhinav_soni
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid