Hm. Funcito is less useless than I thought.
Needs a Bytecode-Generator like cglib and might not be fully error-proof.
This day I thought about a useful spec for @Closure.
Even though the feature will be useless as soon as Java8 comes around, the long adoption times in many projects might make an intermediate solution worthwhile.
Syntax:
@Closure(value=Class<T>)
Class must be an interface with exactly one abstract method.
Abstract classes aren't needed. Java8 also does not allow them for lamdbas)
Can be applied to static methods, methods, static fields and fields.
What it does:
It will create an instance of class with the following implementation for its abstract method.
Parameters:
- If the annotated element is an instance method or field, the first parameter is the object instance to which the field/method belongs
- If the annotated element is a function, all following parameters are applied as-is.
Returns
- If the annotated element is a method with a void type, then the return type is void
- If the annotated elment is a field or a method with a non-void return type, then this is the return type
Types
- Generic Types will be applied to the function and field types.
- Autoboxing to primitives applies in both directions, with the usual null-pointer exceptions if it fails.
- All other types must match exactly. So an String-Field cannot be used for a Closure-Type which returns a (non-generic) Object.
Exceptions
- If the annotated element is a method, then its throws-clause must be throwable by the closure class.
This restriction is not needed, but it might make the implementation easier.
Result:
The Result of the Function is a public static final Field of the value-Type of the annotation with the Name converted to UPPERCASE_UNDERSCORE-Notation based on the Camelcases AND the name of the closure-class.
So getName for a Function becomes GET_NAME_FUNCTION.
If the field exists, the javac should emit the error for a duplicate field.
Examples:
import static com.google.common.base.*;
class XType{
@Closure(Function.class)
private String name;
@Closure(Function.class)
public String getName();
@Closure(Predicate.class)
public static boolean calculate(int x);
@Closure(Comparator.class)
public int compareTo(String other);
@Closure(Supplier.class)
public static final int NAME_LENGTH;
@Closure(Callable.class)
public static InputStream open() throws IOException;
}
Results in:
class XType{
public static final Function<XType,String> NAME_FUNCTION = new Function<XType,String>(){ public String apply(XType input){
input.name);} };
private String name;
public static final Function<XType,String> GET_NAME_FUNCTION = new Function<XType,String>(){ public String apply(XType input){input.getName();} };
public String getName();
public static final Predicate<Integer> CALCULATE_PREDICATE = new Predicate<Integer>(){ public boolean apply(Integer input){calculate(input);} };
public static boolean calculate(int x);
public static final Comparator<String> COMPARE_TO_COMPARATOR = new Comparator(){ public int compare(Person o1, Person o2){o1.compareTo(o2); };
public int compareTo(Person other);
public static final Supplier<Integer> NAME_LENGTH_SUPPLIER = new Supplier<Integer>(){ public Integer get(){return NAME_LENGTH;} };
public static final int NAME_LENGTH;
public static final Callable<InputStream> OPEN_CALLABLE = new Callable<InputStream>(){public InputStream call() throws IOException{return open();} };
public static InputStream open() throws IOException;
}
Is such a transformation possible in a trivial to implement way?
While there are a lot of rules, most of them should be straight-forward.