在Java-8中自动将属性名作为参数传递



我想有一个方法来验证字段类型

protected void validate(String field, String fieldName){
  if (field==null || field.isEmpty){
    throw new IllegalArgumentException("Parameter " + fieldName + " cannot be empty");
  }
}

并在我的类中使用,例如

class Foo {
  private String x;
  private String y;
  ...
  public void validateAll(){
    validate(x, "x");
    validate(y, "y");
  }
}

这样使用会很好

  public void validateAll(){
    validate(x);
    validate(y);
  }

,让编译器自动将变量名传递给validate(field, fieldName)方法

如何在Java-8中实现这个?

您可以在Java中通过放弃使用带有字段的Java类的想法来实现这一点,而是使用将Column对象映射为值的Map。从使用的角度来看,它大致如下所示:

public static final Column<String> X_COLUMN = new Column<>( "x", String.class );
public static final Column<String> Y_COLUMN = new Column<>( "y", String.class );
public static final Table FOO_TABLE = new Table( "Foo", X_COLUMN, Y_COLUMN, ... );
...
Row fooRow = new Row( FOO_TABLE );
fooRow.setFieldValue( X_COLUMN, "x" );
String x = fooRow.getFieldValue( X_COLUMN );
for( Column<?> column : fooRow.getTable().getColumns() )
    doSomethingWithField( fooRow, column );
private static <T> void doSomethingWithField( Row row, Column<T> column )
{
    T value = row.getFieldValue( column );
    ...do something with the field value...
}

由于作为参数传递给方法的值不包含有关其来源字段的信息,因此如果是从字段中读取的,则无法重构该信息。但是,由于您的目的是验证字段,因此在首先处理字段时,而不是处理它们所包含的值时,可以进行所需的操作:

class Foo {
    private String x;
    private String y;
    //...
    public void validateAll() {
        for(Field f: Foo.class.getDeclaredFields()) {
            if(!Modifier.isStatic(f.getModifiers()) && !f.getType().isPrimitive()) try {
                Object o=f.get(this);
                if(o==null || o.equals(""))
                    throw new IllegalArgumentException(f.getName()+" cannot be empty");
            } catch(ReflectiveOperationException ex) { throw new AssertionError(); }
        }
    }
}

这种方法的一般问题是,当validateAll()报告一个问题时,Foo实例已经包含非法状态。最好在试图为属性设置无效值时拒绝无效值。在这种情况下,方法的参数名称可能无法反射地使用,但是,当名为setX的方法抛出IllegalArgumentException时(正如堆栈跟踪所指示的那样),则不需要在消息中添加额外的元信息…

相关内容

  • 没有找到相关文章