PROPOSAL: Method and Field Literals (original) (raw)

Frédéric Martini frederic.martini at gmail.com
Thu Mar 12 03:41:54 PDT 2009


Hello,

Before to start, sorry for my poor english. This is not my spoken language :(

My advice for this proposal : this is a must-have : this will allow to use secure-code with reflection !

But I want to extends this proposal with the support of beans' property. In fact, access to field is very limited due to visibility : there are more often protected or private... For example: we cannot use Exception#message or Exception#cause :(

It will be more interresting to use the beans' property notion, by exemple with a Property's class like this (this is a scratch exemple, with RuntimeException to be replaced by a more precise unchecked exception...) :


/**

Class propertyClass, String propertyName) { try { for (PropertyDescriptor descriptor : Introspector.getBeanInfo(beanClass).getPropertyDescriptors() ) { if (descriptor.getName().equals(propertyName) && propertyClass.equals(descriptor.getPropertyType())) { return new Property<B,T>(descriptor.getName(), descriptor.getReadMethod(), descriptor.getWriteMethod()); } } } catch (IntrospectionException e) { throw new RuntimeException("Property not found : " + propertyName, e); } throw new RuntimeException("Property not found : " + propertyName); }

/**
 * Get a read/write property
 * @param <B> The Bean's type
 * @param <T> The property's type
 * @param beanClass The Bean's type
 * @param propertyClass The property's type
 * @param propertyName The property's name
 * @return A Property for the specified beans-property, with get/set method
 * @throws RuntimeException if the property cannot be found, or is not writable
 */
public static <B,T> Property<B,T> getWritableProperty(Class<B>

beanClass, Class propertyClass, String propertyName) { Property<B,T> property = findProperty(beanClass, propertyClass, propertyName); if (!property.isWritable()) { throw new RuntimeException("Non-writable property : " + propertyName); } return property; }

/**
 * Get a read-only property.
 * The return type is Property<B,? extends T> in order to forbid the

use of the set() method * @param The Bean's type * @param The property's type * @param beanClass The Bean's type * @param propertyClass The property's type * @param propertyName The property's name * @return A Property for the specified beans-property, with only get method * @throws RuntimeException if the property cannot be found */ public static <B,T> Property<B,? extends T> getReadableProperty(Class beanClass, Class propertyClass, String propertyName) { return findProperty(beanClass, propertyClass, propertyName); } }


Property.getWritableProperty() return a property with read/write access, and Property.getReadableProperty() return a property with read-only access, declared as Property<B,? extends T> in order to have compile-time error if the set method is used...

Exemple of use :


public class MyObject {

private final String name;
private int value;

public MyObject(String name) {
    this.name = name;
}

public String getName() {
    return name;
}
public int getValue() {
    return value;
}
public void setValue(int value) {
    this.value = value;
}


public static void main(String[] args) {
    MyObject beans = new MyObject("name");

    Property<MyObject, Integer> valueProperty =

Property.getWritableProperty(MyObject.class, int.class, "value"); int value = valueProperty.get(beans); // OK valueProperty.set(beans, 100); // OK

    Property<MyObject, ? extends String> nameProperty =

Property.getReadableProperty(MyObject.class, String.class, "name"); String name = nameProperty.get(beans); // OK nameProperty.set(beans, "hello"); // Compile error (is not applicable...) } }


My proposal is to use a literal in order to replace the static method call (unsafe because based on a String) with a checked literral :

So this :


Property<MyObject, Integer> valueProperty = Property.getWritableProperty(MyObject.class, int.class, "value"); Property<MyObject, ? extends String> nameProperty = Property.getReadableProperty(MyObject.class, String.class, "name");

May be remplaced with something like (or equivalent) :

Property<MyObject, Integer> value = MyObject#value; Property<MyObject, ? extends String> name = MyObject#name;

(We can use the same notation that the Field literral, based on context, or any other syntaxe...)

MyObject#value is matched to Property<MyObject, Integer> because the MyObject's class have a property called "value", with a getter (getValue()) and a setter (setValue()). MyObject#name is matched to Property<MyObject, ? extends String> because the name's property only have a getter and no-setter !

Of course the literral MyObject#value will be checked at compile time, to produce compile-time error on bad usage.

This will allow the literral to be more useful and usable with almost all classes :

Field message = Throwable#message; // ERROR : message don't exist or is private :( Property<Throwable, ? extends String> message = Throwable#message; // OK

What do you think about this ?

Thanks for reading ;)

Fred,



More information about the coin-dev mailing list