How can I create custom compiler warnings in java? - java

I'm looking for something that's similar to implementing the java.lang.AutoCloseable interface, where a compiler warning indicating Resource leak: 'xxxx' is never closed is generated.
The use case for this is in a wrapper around a Synchronized Collection in java. The wrapper has an internal semaphore to prevent concurrent modification of the collection.
It allows atomic operations on the collection, in which case the semaphore is acquired and released internally. It also allows the lock to be acquired externally, providing a unique key with which operations can be executed on the collection. The key must be released at the end of the "transaction".
My goal is to create a compiler warning when the lock is acquired and not released within the same method, to prevent deadlock. An alternative design solution that would prevent this is also acceptable.
It's kind of a fun little problem, so I appreciate any insight into it.

As you said
An alternative design solution that would prevent this is also acceptable.
So here it is: As an alternative design solution, use Functional Programming.
Instead of finding out about the error, why not prevent the error from happening in the first place?
Lacking your source code, I make a few assumptions about your code:
Semaphore is your class (or interface) that provides the semaphore to your SynchronizedCollection.
Semaphore provides two methods obtain() and release().
The problem that you're actually facing is a problem of State resp. Change of State which leads to Temporal Coupling. obtain() and release() must be called in order. You can use elements from Functional Programming as an alternative design.
The Semaphore would currently look like this:
public class Sempahore {
// ...
public void obtain() {
// Lock code
}
public void release() {
// Release code
}
}
The Semaphore user would currently look like this:
semaphore.obtain();
// Code protected by the Sempahore.
semaphore.release();
The solution is to combine obtain() and release() into a single function which takes the code to be protected as its argument. This technique is also known as Passing a Block, or more formally as a higher order function - a function that takes another function as an argument or returns another function.
Java also has function pointers, not directly, but indirectly, via references to interfaces. Since Java 8, an interface that has only one abstract method is even called Functional Interface, and Java 8 provides an optional annotation #FunctionalInterface for that.
So, your class Sempahore could instead look like this:
public class Semaphore {
// ...
private void obtain() {
// Lock code
}
private void release() {
// Release code
}
public <V> void protect(final Callable<V> c) throws Exception {
obtain();
try {
return c.call();
} finally {
release();
}
}
}
And the caller would look like this, in Java 7 and older:
semaphore.protect(new Callable<Object>() {
public Object call() {
// Code protected by the Semaphore.
}
});
In Java 8 and newer, the code could also look like this:
semaphore.protect(() -> {
// Code protected by the Semaphore.
});
Quirks about this solution
There's one aspect about Java which sucks completely in this context: Exception Handling. With functional programming, there is urgent need to fix that, but Oracle didn't. I'm still hoping for Java 9, but that won't help all that broken API like java.util.stream that's already out there in the wild. Java 8 still maintains the handle-or-declare-rule of checked exceptions, but functional programming does not take that into account nicely.
There are a few workarounds for that:
Use Runnable, if you do not need return values.
Use your own Callable interface which declares a type parameter for exceptions.
I bet using Runnable is straight-forward and self-explanatory, therefore I won't elaborate on that.
Using your own version of the Callable interface would look like this:
public interface ProtectedCode<V,E> {
V call() throws E;
}
public class Semaphore {
// ...
private void obtain() {
// Lock code
}
private void release() {
// Release code
}
public <V, E> void protect(final ProtectedCode<V, E> c) throws E {
obtain();
try {
return c.call();
} finally {
release();
}
}
}
Now you don't need to mess around with Exception as long as the limited (because it can reflect only one type, not a type set) type inference for type parameter E leads to reasonable results in the compiler.
If you want to be extraordinarily friendly to your users, you could actually offer three variants of the protect method:
public void protect(final Runnable r)
public <V> V protect(final Callable<V> c) throws Exception
public <V,E> V protect(final ProtectedCode<V,E> c) throws E

In order to create compiler warnings, you will need to extend the Eclipse compiler.
An alternative solution was to create a custom check in a software quality analysis system such as Teamscale or SonarQube. The custom checks perform a static analysis of the code (usually based on the abstract syntax tree enriched with semantic information) and create issues whey they detect dodgy code. The issues are displayed on the user interface of the quality analysis system. Eclipse plugins allow an integration of the systems in Eclipse so that the issues can be listed there as well.

While #Christian Hujer did provide a solid solution, I chose to go another route which has been working out well.
There is a wrapper class "Resource" around the SynchronizedCollection which contains:
A semaphore for locking the collection
A randomly generated ID representing the key to the currently held lock
Methods for performing atomic operations on the collection (They acquire the lock, perform the operation, and immediately release it)
Methods for performing non-atomic operations on the collection (They accept an ID as the key and perform the requested operation if the provided key matches the key currently holding the lock)
The class described above is enough to provide sufficient protection around the collection, but what I wanted was compiler warnings if the lock wasn't released.
To accomplish this, there is a "ResourceManager" which implements java.lang.AutoCloseable
This class:
Is passed a reference to the "Resource" via the constructor
Acquires the lock for the reference in the constructor
Provides an API for calling the non-atomic methods on the "Resource" using the key it acquired during construction
Provides a close() method, overriding java.lang.AutoCloseable, which releases the lock acquired during construction
The resource manager is created wherever multiple operations need to be performed on the Resource and a compiler warning is generated if close() is not called on any particular code path. Additionally, in java 7+, the manager can be created in a try-with-resource block and the lock is automatically released, regardless of what happens in the block.

Related

Can anonymous classes be completely immutable?

In the book Java Concurrency In Practice, there is this example of an almost immutable object which is at risk of failure if not properly published:
// Taken from Java Concurrency In Practice
// p.51 Listing 3.15: Class at risk of failure if not properly published.
public class Holder {
private int n;
public Holder(int n) { this.n = n; }
public void assertSanity() {
if(n != n)
throw new AssertionError("This statement is false.");
}
}
// p.50 Listing 3.14: Publishing an object without adequate synchronization. Don't do this.
class Client {
public Holder holder;
public void initialize() {
holder = new Holder(42);
}
}
If I understand the chapter in the book correctly, adding final to the n field of the Holder class will make the object completely immutable and eliminate the chance of getting the AssertionError thrown even if it's still published without adequate synchronization like it's done in the Client class.
Now I'm wondering how anonymous classes behave in this respect. Please see the following example:
public interface IHolder {
void assertSanity();
}
class IHolderFactory {
static IHolder create(int n) {
return new IHolder() {
#Override
public void assertSanity() {
if (n != n)
throw new AssertionError("This statement is false.");
}
};
}
}
class IHolderClient {
public IHolder holder;
public void initialize() {
// is this safe?
holder = IHolderFactory.create(42);
}
}
It's published without adequate synchronization just like in the example from the book, but the difference is that now the Holder class has become an interface and there is a static factory method which returns an anonymous class implementing the interface, and the anonymous class uses the method parameter n.
My question is: is there any chance of getting the AssertionError from my latter example thrown? If there is, what is the best way to make it completely immutable and eliminate the problem? Does it change something if it was written in a functional way like the following?
class IHolderFactory {
static IHolder create(int n) {
return () -> {
if (n != n)
throw new AssertionError("This statement is false.");
};
}
}
This is a very tricky issue.
JLS, §17.4.1. Shared Variables says:
Local variables (§14.4), formal method parameters (§8.4.1), and exception handler parameters (§14.20) are never shared between threads and are unaffected by the memory model.
This seems to contradict the fact that you can use them within an inner class or lambda expression that can be shared between threads, but those constructs capture the value of the variable and use the value. This process, however, is not very well specified.
The only mentioning I could ever find, is in §15.27.2 explaining the (effective) final requirement:
The restriction to effectively final variables prohibits access to dynamically-changing local variables, whose capture would likely introduce concurrency problems.
In practice, the captured values are stored in synthetic final fields of the inner class or the class generated at runtime for the lambda expression. So you will never see the error with the current implementation.
This, however, is not specified anywhere. The language specification says little about the bytecode format and the virtual machine specification says little about the language constructs.
So, local variables, formal method parameters, and exception handler parameters are explicitly excluded from the JMM and their captured values are not variables in the JMM’s regard and not even mentioned there. The question is what does that mean.
Are they generally immune to data races (my interpretation) or are they unsafe and we do no get any guaranty from the JMM at all? In the latter case, it would even imply that we were not able to make them safe, as any safe publication mechanism gets its safety from guarantees of the JMM which does not cover our case. It’s worth noting that the JMM also does not cover the outer this reference nor an instance’s implicit reference to a Class object returned by getClass().
So while I’d consider them immune to data races, I wish that was specified more explicit.
It does not matter if you use an anonymous class or lambda, you have zero synchronization mechanisms here to correctly publish the reference; as such, this code can throw that Exception.
In other words, there are tools and conditions that you must meet so that your code is safe: these are using final, volatile or some sort of synchronized or locks, etc. Since you use none, no guarantees are provided.
The Java Language Specification offers these guarantees only when you use special semantics, like final that you have shown in the first example. There are others too, but making an object immutable is the simplest, most trivial way. This is the best article that I am aware of on this subject, you might want to read it.

Why can static and default interface methods not be synchronized but can be strictfp? [duplicate]

This question already has answers here:
What is the reason why “synchronized” is not allowed in Java 8 interface methods?
(2 answers)
Closed 5 years ago.
Why can static and default interface methods not be synchronized?
People say that synchronized is an implementation detail. Well, strictfp is an implementation detail as well, but that doesn't prevent allowing strictfp on static and default interface methods.
A default method is inherited and it may be quite convenient to have it already synchronized if the class implementing the interface does not override the default method.
I have a guess that synchronized (as well as strictfp) is not inherited (am I right here?), but that does not explain why strictfp is allowed for static and default interface methods either.
The strictfp keyword ensures that your floating-point operations are consistent across all platforms. stricftp then becomes a guarantee of the JVM that your floating-point operations are going to be the same on all platforms, and that one can expect that floating-point operations are portable and consistent throughout.
A method marked synchronized is actually an implementation detail, and cannot be dictated or controlled by any one interface for any of its implementations. It was intentionally excluded from default methods, as explained by Brian Goetz, due to them being inherently dangerous (emphasis mine):
...So, why are they dangerous? Synchronization is about locking. Locking is about coordinating shared access to mutable state. Each object should have a synchronization policy that determines which locks guard which state variables. (See Java Concurrency in Practice, section 2.4.)
...It is the class that owns the state that gets to determine that object's synchronization policy. But interfaces do not own the state of the objects into which they are mixed in. So using a synchronized method in an interface assumes a particular synchronization policy, but one which you have no reasonable basis for assuming, so it might well be the case that the use of synchronization provides no additional thread safety whatsoever (you might be synchronizing on the wrong lock).
I think this is because if it were allowed:
interface I {
static synchronized void x() {
}
}
class C implements I {
synchronized static void y() {
}
}
then two different threads could enter C.y() and C.x() because x() is synchronized on I.class and y() on C.class. It is only my guess
class C {
public synchronized void f () {
}
}
is the same as
class C {
public void f () {
synchronized(this){
}
}
}
If f were static, there would be no this object to synchronize on.

Generic writer/outputter. What Reader is to Iterator, what is Writer to X?

In Java the abstract version of a Reader that works with pulling Objects (instead of characters) is an Iterator.
The question is there an abstract version of Appendable or Writer where I can push objects (ie an interface)?
In the past I just make my own interface like:
public interface Pusher<T> {
public void push(T o);
}
Is there a generic interface that is available in most environments that someone knows about that makes sense so I don't have to keep creating the above interface?
Update:
Here is an example of where it would be useful:
public void findBadCategories(final Appendable a) {
String q = sql.getSql("product-category-bad");
jdbcTemplate.query(q, new RowCallbackHandler() {
#Override
public void processRow(ResultSet rs) throws SQLException {
String id = rs.getString("product_category_id");
String name = rs.getString("category_name");
if (! categoryMap.containsKey(id)) {
try {
a.append(id + "\t" + name + "\n");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
});
}
I'm using an Appendable here but I would much rather have my Pusher callback. Believe me once Java 8 comes out I would just use closure but that closure still needs an interface.
Finally the other option I have chosen before is to completely violate Guava's Predicate or Function (although that seems even worse). Its violation of the contract because these aim to be idempotent (although I suppose if you return true all the time... ).
What Guava does provide though is sort of analagous to Python's generators thanks to its AbstractIterator.
I added an enhancement issue to Guava but I agree with them that its not really their job to add something fundamental like that.
On several projects now, I've defined for this purpose what I call a sink:
interface Sink<T> {
void put(T contribution);
}
With that, methods that produce objects of type T would demand a parameter of type Sink<? super T>.
Several design questions arise:
As declared, Sink#put() throws no checked exceptions. That doesn't play well with I/O operations that usually throw IOException. To address this, you can add a type parameter that extends Exception and advertise that put() throws this type, but at that point, if you know that much about the nature of value consumption, you're probably better off defining a custom interface for it.
As declared, Sink#put() does not return a value. It's not possible to indicate to the caller whether the value was accepted or not.
With a generic interface like this, you're forced to box contributions of primitive types like int and char, which also means they can be null. Consider annotating the contribution parameter with #NonNull.
To go along with this type, related to the generator concept that Petr Pudlák mentions in his answer, I've defined a source interface:
interface Source<T> {
T get();
}
Methods looking to draw items of type T from such a source demand a parameter of type Source<? extends T>.
For coordination with channels among concurrent processes, I've defined both Sink#put() and Source#get() to throw InterruptedException:
interface Sink<T> {
void put(T contribution) throws InterruptedException;
}
interface Source<T> {
T get() throws InterruptedException;
}
These are analogous to Doug Lea's original Puttable and Takable interfaces that didn't make it into the java.util.concurrent package, though lacking in an equivalent to the timed wait Puttable#offer() and Takable#poll() methods.
All sorts of implementations then arise that can be composed easily, such as exchangers, filters, and transformers.
Beyond my own library, I've seen the Guava library provide the PrimitiveSink and Funnel types for hashing-related purposes. You may find those to be useful abstractions as well.
There can be several views on the subject:
The dual of an iterator is a generator. Iterators "consume" values from a collection, generator "provide" them. But generators are a bit different than writers. For a writer, you decide when you push an element into it. On the other hand, generators provide you with a sequence of values, one by one. Java doesn't have any specific language support for generators. See also What is the difference between an Iterator and a Generator?
The opposite to iterators is something you could push values into. I don't think Java has any abstraction for that. The closes I have seen is Scala's Growable (neglecting the clear() method).
The closest is Observable but it isn't used so much.
public update(Observable o, Object arg)
I would not use Iterable instead of Reader and I would create a consumer of your choice.
A common pattern is to not use an interface but rather an annotation.
e.g.
#Subscriber
public void onUpdate(Update update) { }
#Subscriber
public void onInsert(Insert insert) { }
#Subscriber
public void onDelete(Delete delete) { }
When this class is added as a listener it subscribes to Update, Insert and Delete objects, and ignores any others. This allows one object to subscribe to different type of message in a Type safe way.
Here is what I decided to do (and I think its the best option out of what others gave :P ).
I'm going to backport Java 8's Lambda classes (java.util.functions.*). Particularly this one:
/**
* Performs operations upon an input object which may modify that object and/or
* external state (other objects).
*
* <p>All block implementations are expected to:
* <ul>
* <li>When used for aggregate operations upon many elements blocks
* should not assume that the {#code apply} operation will be called upon
* elements in any specific order.</li>
* </ul>
*
* #param <T> The type of input objects to {#code apply}.
*/
public interface Block<T> {
/**
* Performs operations upon the provided object which may modify that object
* and/or external state.
*
* #param t an input object
*/
void apply(T t);
// Some extension methods that I'll have to do with below.
}
Basically I'll make a new namespace like com.snaphop.backport.java.util.functions.* and move over the interfaces and make them work with Guava. Obviously I won't have the lambda syntax or the extension methods but those I can work around. Then in theory when Java 8 comes out it all I would have to do is a namespace switch.

Consistency of processing environment members across compilation rounds

The Java Annotation Processing API as it stands in JDK 6 and 7 (not the apt tool API from 5) defines the lifecycle of an annotation processor. One is instantiated via the no-args constructor, the init method is called with a ProcessingEnvironment instance and then that processor is used via the process method. Only one instance of the processor is made and used throughout all subsequent processing rounds if applicable.
Since my processor class was getting a bit bloated, I've created handler classes for separate annotations it's supposed to deal with. In the methods of those classes I'm always passing in Elements and Types instances that I've obtained from the ProcessingEnvironment for their utility methods. This is making my method signatures rather long.
I'd rather just keep a reference to the Elements and Types instances in the handlers, as well as in the processor instance. I've done this by getting them from the ProcessingEnvironment passed into the init method. Now, I'm wondering if this is safe. The JavaDoc for Processor makes it clear that some methods are only called once for a processor, but init isn't mentioned here. I was kind of assuming this is implicitly understood, but I'm not 100% certain.
I'd also like to know if the Messager instance, which can be obtained from ProcessingEnvironment as well, remains the same across all processing rounds. I'd rather not have warnings/errors from one round showing up but others getting left out. I'm reasonably certain that it should be safe to use the same instances across rounds, but just would like some certainty.
I've asked myself the same question and decided to always use the current round's ProcessingEnvironment's utilities provided by init. There doesn't seem to be any difference when using javac, but there are other annotation processing tools which may show different behaviour. I've already experienced a few differences between the processing tool in javac and the one used by eclipse, so I handle anything not explicit in the documentation with great care. The question is, do you want test all existing processing tools?
Also, I think if those processing helper tools were meant to never change, they would be arguments of the processor's constructor.
It may be worth mentioning that the AbstractProcessor (which is suggested by the javadoc of the Process class as a subclass which could be used by implementors) throws IllegalStateException if its init method is called more than once.
It does not mean the passed ProcessingEnvironment could not return different values on subsequent getter calls or in different rounds although it would not be conventional. Anyway, it could be worth checking at the beginning of the process method:
private ProcessingEnvironment processingEnv;
private Elements elementUtils;
private Types typeUtils;
public Processor() {
}
#Override
public synchronized void init(final ProcessingEnvironment processingEnv) {
this.processingEnv = processingEnv;
elementUtils = processingEnv.getElementUtils();
typeUtils = processingEnv.getTypeUtils();
}
private void checkEnvironmentChange() {
checkSame(elementUtils, processingEnv.getElementUtils(), "elementUtils");
checkSame(typeUtils, processingEnv.getTypeUtils(), "typeUtils");
}
private <T> void checkSame(final T object1, final T object2, final String name) {
if (object1 != object2) {
throw new IllegalStateException(name + " should not change");
}
}
#Override
public boolean process(final Set<? extends TypeElement> annotations,
final RoundEnvironment roundEnv) {
checkEnvironmentChange();
...
}

Java Delegates?

Does the Java language have delegate features, similar to how C# has support for delegates?
Not really, no.
You may be able to achieve the same effect by using reflection to get Method objects you can then invoke, and the other way is to create an interface with a single 'invoke' or 'execute' method, and then instantiate them to call the method your interested in (i.e. using an anonymous inner class).
You might also find this article interesting / useful : A Java Programmer Looks at C# Delegates (#blueskyprojects.com)
Depending precisely what you mean, you can achieve a similar effect (passing around a method) using the Strategy Pattern.
Instead of a line like this declaring a named method signature:
// C#
public delegate void SomeFunction();
declare an interface:
// Java
public interface ISomeBehaviour {
void SomeFunction();
}
For concrete implementations of the method, define a class that implements the behaviour:
// Java
public class TypeABehaviour implements ISomeBehaviour {
public void SomeFunction() {
// TypeA behaviour
}
}
public class TypeBBehaviour implements ISomeBehaviour {
public void SomeFunction() {
// TypeB behaviour
}
}
Then wherever you would have had a SomeFunction delegate in C#, use an ISomeBehaviour reference instead:
// C#
SomeFunction doSomething = SomeMethod;
doSomething();
doSomething = SomeOtherMethod;
doSomething();
// Java
ISomeBehaviour someBehaviour = new TypeABehaviour();
someBehaviour.SomeFunction();
someBehaviour = new TypeBBehaviour();
someBehaviour.SomeFunction();
With anonymous inner classes, you can even avoid declaring separate named classes and almost treat them like real delegate functions.
// Java
public void SomeMethod(ISomeBehaviour pSomeBehaviour) {
...
}
...
SomeMethod(new ISomeBehaviour() {
#Override
public void SomeFunction() {
// your implementation
}
});
This should probably only be used when the implementation is very specific to the current context and wouldn't benefit from being reused.
And then of course in Java 8, these do become basically lambda expressions:
// Java 8
SomeMethod(() -> { /* your implementation */ });
Short story: ­­­­­­­­­­­­­­­­­­­no.
Introduction
The newest version of the Microsoft Visual J++ development environment
supports a language construct called delegates or bound method
references. This construct, and the new keywords delegate and
multicast introduced to support it, are not a part of the JavaTM
programming language, which is specified by the Java Language
Specification and amended by the Inner Classes Specification included
in the documentation for the JDKTM 1.1 software.
It is unlikely that the Java programming language will ever include
this construct. Sun already carefully considered adopting it in 1996,
to the extent of building and discarding working prototypes. Our
conclusion was that bound method references are unnecessary and
detrimental to the language. This decision was made in consultation
with Borland International, who had previous experience with bound
method references in Delphi Object Pascal.
We believe bound method references are unnecessary because another
design alternative, inner classes, provides equal or superior
functionality. In particular, inner classes fully support the
requirements of user-interface event handling, and have been used to
implement a user-interface API at least as comprehensive as the
Windows Foundation Classes.
We believe bound method references are harmful because they detract
from the simplicity of the Java programming language and the
pervasively object-oriented character of the APIs. Bound method
references also introduce irregularity into the language syntax and
scoping rules. Finally, they dilute the investment in VM technologies
because VMs are required to handle additional and disparate types of
references and method linkage efficiently.
Have you read this :
Delegates are a useful construct in event-based systems. Essentially
Delegates are objects that encode a method dispatch on a specified
object. This document shows how java inner classes provide a more
generic solution to such problems.
What is a Delegate? Really it is very similar to a pointer to member
function as used in C++. But a delegate contains the target object
alongwith the method to be invoked. Ideally it would be nice to be
able to say:
obj.registerHandler(ano.methodOne);
..and that the method methodOne would be called on ano when some specific event was received.
This is what the Delegate structure achieves.
Java Inner Classes
It has been argued that Java provides this
functionality via anonymous inner classes and thus does not need the additional
Delegate construct.
obj.registerHandler(new Handler() {
public void handleIt(Event ev) {
methodOne(ev);
}
} );
At first glance this seems correct but at the same time a nuisance.
Because for many event processing examples the simplicity of the
Delegates syntax is very attractive.
General Handler
However, if event-based programming is used in a more
pervasive manner, say, for example, as a part of a general
asynchronous programming environment, there is more at stake.
In such a general situation, it is not sufficient to include only the
target method and target object instance. In general there may be
other parameters required, that are determined within the context when
the event handler is registered.
In this more general situation, the java approach can provide a very
elegant solution, particularly when combined with use of final
variables:
void processState(final T1 p1, final T2 dispatch) {
final int a1 = someCalculation();
m_obj.registerHandler(new Handler() {
public void handleIt(Event ev) {
dispatch.methodOne(a1, ev, p1);
}
} );
}
final * final * final
Got your attention?
Note that the final variables are accessible from within the anonymous
class method definitions. Be sure to study this code carefully to
understand the ramifications. This is potentially a very powerful
technique. For example, it can be used to good effect when registering
handlers in MiniDOM and in more general situations.
By contrast, the Delegate construct does not provide a solution for
this more general requirement, and as such should be rejected as an
idiom on which designs can be based.
I know this post is old, but Java 8 has added lambdas, and the concept of a functional interface, which is any interface with only one method. Together these offer similar functionality to C# delegates. See here for more info, or just google Java Lambdas.
http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html
No, but they're fakeable using proxies and reflection:
public static class TestClass {
public String knockKnock() {
return "who's there?";
}
}
private final TestClass testInstance = new TestClass();
#Test public void
can_delegate_a_single_method_interface_to_an_instance() throws Exception {
Delegator<TestClass, Callable<String>> knockKnockDelegator = Delegator.ofMethod("knockKnock")
.of(TestClass.class)
.to(Callable.class);
Callable<String> callable = knockKnockDelegator.delegateTo(testInstance);
assertThat(callable.call(), is("who's there?"));
}
The nice thing about this idiom is that you can verify that the delegated-to method exists, and has the required signature, at the point where you create the delegator (although not at compile-time, unfortunately, although a FindBugs plug-in might help here), then use it safely to delegate to various instances.
See the karg code on github for more tests and implementation.
Yes & No, but delegate pattern in Java could be thought of this way. This video tutorial is about data exchange between activity - fragments, and it has great essence of delegate sorta pattern using interfaces.
I have implemented callback/delegate support in Java using reflection. Details and working source are available on my website.
How It Works
There is a principle class named Callback with a nested class named WithParms. The API which needs the callback will take a Callback object as a parameter and, if neccessary, create a Callback.WithParms as a method variable. Since a great many of the applications of this object will be recursive, this works very cleanly.
With performance still a high priority to me, I didn't want to be required to create a throwaway object array to hold the parameters for every invocation - after all in a large data structure there could be thousands of elements, and in a message processing scenario we could end up processing thousands of data structures a second.
In order to be threadsafe the parameter array needs to exist uniquely for each invocation of the API method, and for efficiency the same one should be used for every invocation of the callback; I needed a second object which would be cheap to create in order to bind the callback with a parameter array for invocation. But, in some scenarios, the invoker would already have a the parameter array for other reasons. For these two reasons, the parameter array does not belong in the Callback object. Also the choice of invocation (passing the parameters as an array or as individual objects) belongs in the hands of the API using the callback enabling it to use whichever invocation is best suited to its inner workings.
The WithParms nested class, then, is optional and serves two purposes, it contains the parameter object array needed for the callback invocations, and it provides 10 overloaded invoke() methods (with from 1 to 10 parameters) which load the parameter array and then invoke the callback target.
What follows is an example using a callback to process the files in a directory tree. This is an initial validation pass which just counts the files to process and ensure none exceed a predetermined maximum size. In this case we just create the callback inline with the API invocation. However, we reflect the target method out as a static value so that the reflection is not done every time.
static private final Method COUNT =Callback.getMethod(Xxx.class,"callback_count",true,File.class,File.class);
...
IoUtil.processDirectory(root,new Callback(this,COUNT),selector);
...
private void callback_count(File dir, File fil) {
if(fil!=null) { // file is null for processing a directory
fileTotal++;
if(fil.length()>fileSizeLimit) {
throw new Abort("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.
*/
static public int processDirectory(File dir, Callback cbk, FileSelector sel) {
return _processDirectory(dir,new Callback.WithParms(cbk,2),sel);
}
static private int _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;
}
This example illustrates the beauty of this approach - the application specific logic is abstracted into the callback, and the drudgery of recursively walking a directory tree is tucked nicely away in a completely reusable static utility method. And we don't have to repeatedly pay the price of defining and implementing an interface for every new use. Of course, the argument for an interface is that it is far more explicit about what to implement (it's enforced, not simply documented) - but in practice I have not found it to be a problem to get the callback definition right.
Defining and implementing an interface is not really so bad (unless you're distributing applets, as I am, where avoiding creating extra classes actually matters), but where this really shines is when you have multiple callbacks in a single class. Not only is being forced to push them each into a separate inner class added overhead in the deployed application, but it's downright tedious to program and all that boiler-plate code is really just "noise".
It doesn't have an explicit delegate keyword as C#, but you can achieve similar in Java 8 by using a functional interface (i.e. any interface with exactly one method) and lambda:
private interface SingleFunc {
void printMe();
}
public static void 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);
}
private static void delegate(SingleFunc f) {
f.printMe();
}
Every new object of type SingleFunc must implement printMe(), so it is safe to pass it to another method (e.g. delegate(SingleFunc)) to call the printMe() method.
With safety-mirror on the classpath you get something similar to C#'s delegates and events.
Examples from the project's README:
Delegates in Java!
Delegate.With1Param<String, String> greetingsDelegate = new Delegate.With1Param<>();
greetingsDelegate.add(str -> "Hello " + str);
greetingsDelegate.add(str -> "Goodbye " + str);
DelegateInvocationResult<String> invocationResult =
greetingsDelegate.invokeAndAggregateExceptions("Sir");
invocationResult.getFunctionInvocationResults().forEach(funInvRes ->
System.out.println(funInvRes.getResult()));
//prints: "Hello sir" and "Goodbye Sir"
Events
//Create a private Delegate. Make sure it is private so only *you* can invoke it.
private static Delegate.With0Params<String> trimDelegate = new Delegate.With0Params<>();
//Create a public Event using the delegate you just created.
public static Event.With0Params<String> trimEvent= new Event.With0Params<>(trimDelegate)
See also this SO answer.
While it is nowhere nearly as clean, but you could implement something like C# delegates using a Java Proxy.
No, but it has similar behavior, internally.
In C# delegates are used to creates a separate entry point and they work much like a function pointer.
In java there is no thing as function pointer (on a upper look) but internally Java needs to do the same thing in order to achieve these objectives.
For example, creating threads in Java requires a class extending Thread or implementing Runnable, because a class object variable can be used a memory location pointer.
No, Java doesn't have that amazing feature. But you could create it manually using the observer pattern. Here is an example:
Write C# delegate in java
The code described offers many of the advantages of C# delegates. Methods, either static or dynamic, can be treated in a uniform manner. The complexity in calling methods through reflection is reduced and the code is reusable, in the sense of requiring no additional classes in the user code. Note we are calling an alternate convenience version of invoke, where a method with one parameter can be called without creating an object array.Java code below:
class Class1 {
public void show(String s) { System.out.println(s); }
}
class Class2 {
public void display(String s) { System.out.println(s); }
}
// allows static method as well
class Class3 {
public static void staticDisplay(String s) { System.out.println(s); }
}
public class TestDelegate {
public static final Class[] OUTPUT_ARGS = { String.class };
public final Delegator DO_SHOW = new Delegator(OUTPUT_ARGS,Void.TYPE);
public void main(String[] args) {
Delegate[] items = new Delegate[3];
items[0] = DO_SHOW .build(new Class1(),"show,);
items[1] = DO_SHOW.build (new Class2(),"display");
items[2] = DO_SHOW.build(Class3.class, "staticDisplay");
for(int i = 0; i < items.length; i++) {
items[i].invoke("Hello World");
}
}
}
Java doesn't have delegates and is proud of it :). From what I read here I found in essence 2 ways to fake delegates:
1. reflection;
2. inner class
Reflections are slooooow! Inner class does not cover the simplest use-case: sort function. Do not want to go into details, but the solution with inner class basically is to create a wrapper class for an array of integers to be sorted in ascending order and an class for an array of integers to be sorted in descending order.

Categories

Resources