Let's say we have this class:
public abstract class A {
  int x;
  public int foo();
  public int foo(int x);
}
As we all know, A.class has a distinct advantage over Class.forName("A"): it will still work if the name of A is changed by refactoring or obfuscation.
However, there is no way to get this advantage with fields and methods. Have you ever wished that you could do this: (see a better proposed syntax in the edit below!)
Field xField = A.x.field;
Method fooMethod = A.foo().method;
Method fooIntMethod = A.foo(int).method;
Instead of this?
Field xField = A.getField("x");
Method fooMethod = A.getMethod("foo");
Method fooIntMethod = A.getMethod("foo", int.class);
So here's my question: does anyone know if this feature has been planned or discussed or if Sun/Oracle specifically decided against it for some reason?
EDIT: How about this syntax? It avoids problems people have mentioned:
Field xField = A..x;
Method fooMethod = A..foo();
Method fooIntMethod = A..foo(int);
Example use case
I recently created an AbstractTableModel class called EasyTableModel that allows you to define your own POJO row type.  Its getValueAt(...) and setValueAt(...) etc. use reflection to get/set the values of the fields in the POJO.
public class EasyTableModel<T> extends AbstractTableModel {
    private RowFormat<T>                prototypeFormat;
    private final ArrayList<T>          rows                = new ArrayList<T>();
    ...
    public static interface RowFormat<T> {
        Object getValueAt(T row, int columnIndex);
        void setValueAt(T row, Object value, int columnIndex);
        ...
    }
    ...
    public static class ReflectionRowFormat<T> implements RowFormat<T> {
        private Field[]             fields;
        ...
        public Object getValueAt(T row, int column) {
            try {
                return fields[column].get(row);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        public void setValueAt(T row, Object value, Field field) {
            if (!field.getDeclaringClass().isInstance(this)) {
                throw new IllegalArgumentException("field is not a member of this class");
            }
            setValueAt(row, value, getColumnIndex(field));
        }
        ...
    }
    ...
    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        return getRowFormat(rowIndex).getValueAt(rows.get(rowIndex), columnIndex);
    }
    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        getRowFormat(rowIndex).setValueAt(rows.get(rowIndex), aValue, columnIndex);
        fireTableRowsUpdated(rowIndex, rowIndex);
    }
    public void fireTableCellUpdated(T row, String columnName) {
        fireTableCellUpdated(row, indexOfColumn(columnName));
    }
    public void fireTableCellUpdated(T row, Field field) {
        fireTableCellUpdated(row, indexOfColumn(field));
    }
}
Using this base class, it's extremely easy to create your table:
public abstract class QuoteMonitorTableModel<R extends QuoteMonitorTableModel<R>.Row> extends EasyTableModel<R> {
    ...
    protected static final String   NUM_QUOTES_RECEIVED = "# Quotes Received";
    protected static final String   LAST_QUOTE_TIME     = "Last Quote Time";
    public class Row {
        public Row() {
        }
        @ColumnName(NUM_QUOTES_RECEIVED)
        private Integer numQuotesReceived;
        @ColumnName(LAST_QUOTE_TIME)
        private Long    lastQuoteTimeMillis;
        public Integer getNumQuotesReceived() {
            return numQuotesReceived;
        }
        public void setNumQuotesReceived(Integer numQuotesReceived) {
            this.numQuotesReceived = numQuotesReceived;
            fireTableCellUpdated((R) this, NUM_QUOTES_RECEIVED);
        }
        public Long getLastQuoteTimeMillis() {
            return lastQuoteTimeMillis;
        }
        public void setLastQuoteTimeMillis(Long lastQuoteTimeMillis) {
            this.lastQuoteTimeMillis = lastQuoteTimeMillis;
            fireTableCellUpdated((R) this, LAST_QUOTE_TIME);
        }
    }
}
What are the advantages of all this?
getValueAt(...) and setValueAt(...)
If you think this is an abuse of reflection, then you would consider many well-used libraries like Google GSON as an abuse of reflection as well.
Now, notice how the derived class indicates which field has changed when firing events by a String, rather than the Field:
    public void setNumQuotesReceived(Integer numQuotesReceived) {
        this.numQuotesReceived = numQuotesReceived;
        fireTableCellUpdated((R) this, NUM_QUOTES_RECEIVED);
    }
It would be nice if we could just use the fields. But doing it with getDeclaredField() would suck:
public void setNumQuotesReceived(Integer numQuotesReceived) {
    this.numQuotesReceived = numQuotesReceived;
    try {
        // what if obfuscation changes the name of the numQuotesReceived field?
        fireTableCellUpdated((R) this, getClass().getDeclaredField("numQuotesReceived"));
    } catch (NoSuchFieldException e) {
    }
}
However, with the feature I am proposing, it would be easy as cake:
public void setNumQuotesReceived(Integer numQuotesReceived) {
    this.numQuotesReceived = numQuotesReceived;
    // if obfuscation changes the name of the numQuotesReceived it will
    // not break the compiled form of this code
    fireTableCellUpdated((R) this, QuoteMonitorTableModel..numQuotesReceived);
}
If you think this feature wouldn't open up a world of possibilities for useful programming tools, you're lacking imagination ;)
Reflection is a feature in the Java programming language. It allows an executing Java program to examine or "introspect" upon itself, and manipulate internal properties of the program. For example, it's possible for a Java class to obtain the names of all its members and display them.
In order to reflect a Java class, we first need to create an object of Class . And, using the object we can call various methods to get information about methods, fields, and constructors present in a class. class Dog {...} // create object of Class // to reflect the Dog class Class a = Class.
Yes, you can use reserved words.
It would be difficult to introduce keywords in Java, however you can introduce new symbol combinations. For example in Java 8 you can write
 MyClass::myMethod
To get a Method Reference, something you can't do in Java 7.
You could do something similar with fields and there have been suggestions to support property references.
You can even write
 HashSet<String>::new
to get a reference to a constructor ALA new HashSet<String>()
You can turn a Method into a MethodHandle with MethodHandles.Lookup.unreflect(Method) and you can turn a Constructor into a MethodHandle with MethodHandles.Lookup.unreflectConstructor(Constructor)
Once you have a MethodHandle you can set an object for it to call on.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With