2017-02-19 108 views
1

我的目标是通过将其重写为匿名函数将getAllFields方法迁移到init中,我知道这很有可能使用函数式编程。Java 8,匿名递归嵌套方法

public void init(){ 

} 

public static Field[] getAllFields(Class klass) { 
    List<Field> fields = new ArrayList<Field>(); 
    fields.addAll(Arrays.asList(klass.getDeclaredFields())); 
    if (klass.getSuperclass() != null) { 
     fields.addAll(Arrays.asList(getAllFields(klass.getSuperclass()))); 
    } 
    return fields.toArray(new Field[] {}); 
} 

我试过使用函数也BiFunction但得到了丢失的技能。 任何人可以给如何实施这种情况下的片段?

+4

目标是什么?混淆你的代码?有很多情况下使用lambdas是有用的,但这实际上不是其中之一。 –

+0

请显示您尝试过的内容,并解释您遇到的问题。 – shmosel

+0

我不同意,我认为一旦你的整个代码逻辑被封装在1个方法中,它就更容易维护 – Benma

回答

1

getAllFields实施是非常低效率,创建多个ArrayList实例和数组,重复地在它们之间来回复制整个数据。值得庆幸的是,阶级层级很少深刻,这成为一个瓶颈。

不过,你可以用一个直接的循环,这是更简单,更高效的实现这一点:

public static Field[] getAllFields(Class<?> klass) { 
    List<Field> fields = new ArrayList<>(); 
    for(; klass!=null; klass=klass.getSuperclass()) 
     Collections.addAll(fields, klass.getDeclaredFields()); 
    return fields.toArray(new Field[0]); 
} 

没有从这里使用递归半点好处。

有了一个循环,你可以轻松地创建一个Function如果你真的想:

public void init(){ 
    Function<Class<?>,Field[]> f = klass -> { 
     List<Field> fields = new ArrayList<>(); 
     for(; klass!=null; klass=klass.getSuperclass()) 
      Collections.addAll(fields, klass.getDeclaredFields()); 
     return fields.toArray(new Field[0]); 
    }; 
    Field[] someFields = f.apply(SomeClass.class); 
} 

虽然,当然,竟然没有把环路成Function在所有的理由。由于希望使用低效的递归实现,因此您只想在此处有一个函数,但lambda表达式根本不支持访问它们。他们只能访问字段,实现功能接口的实例已存储到该实例中,如果存储在您不想要的字段中,那么它们就是。用本地lambda表达式,递归是不可能的。

有了直接的循环,你可以只写

public void init(){ 
    List<Field> fields = new ArrayList<>(); 
    for(Class<?> klass=SomeClass.class; klass!=null; klass=klass.getSuperclass()) 
     Collections.addAll(fields, klass.getDeclaredFields()); 
    Field[] someFields = fields.toArray(new Field[0]); 
} 

不过,实际上,很少有针对fields内容复制到阵列中的真正的原因,你可以只用List<Field>工作,而不是。这就是说,将循环封装到描述其目的的命名方法中,如getAllFields,实际上是一件好事。如果您不想公开它,请将其声明为private而不是public

+0

这个问题的归纳或递归方法并不是主题,尽管当然你对于使用递归方法获得一无所获当然是非常正确的&我完全接受这样一个事实,即归纳方式远比rec 1更合理,我像在javaScript中一样更关心函数式编程方法,它允许创建一个匿名方法,它不会创建引用,也不会创建方法引用,只会检索值一个本地方法的参考,希望能在java 8中看到这个。 – Benma

+0

lambda表达式就像一个anony mous方法(实际上,它们被编译为一个方法),但它不能递归地调用它自己。那么,方法调用语法需要一个方法名称...... – Holger

2

这还不是直接可能的。在Java中9,Stream类将有一个iterate方法,这使得实现这个如下:

Field[] allFields = Stream 
    .iterate((klass, Objects::nonNull, Class::getSuperclass) 
    .flatMap(c -> Stream.of(c.getDeclaredFields())) 
    .toArray(Field[]::new); 

然而,getAllFields方法,你已经是一个很好的,干净实现所需的功能,以及名称明确清除这个方法做什么。功能实现将更难以理解。