Эта реализация 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
вообще. Вы только хотели иметь функцию здесь из-за вашего желания использовать эту неэффективную рекурсивную реализацию, но выражения лямбда не поддерживают доступ к самим себе. Они могут получить доступ только к полю , к которому хранился экземпляр, реализующий функциональный интерфейс, , если он был сохранен в поле, которое вы не хотите. При локальном выражении лямбда рекурсия невозможна.
С Прямодушными петлями, вы можете просто написать
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
.
Какая цель? Obfuscate ваш код? Есть много случаев, когда использование лямбда полезно, но это действительно не один из них. –
Пожалуйста, покажите, что вы пробовали, и объясните, с какими проблемами вы столкнулись. – shmosel
Я не согласен, я думаю, что после того, как вся ваша логика кода инкапсулируется внутри 1 метода, это гораздо более удобно поддерживать. – Benma