code: private void analyze() {
          if (requiredLists != null && requiredObjects != null) {
              return;
          }
  
          requiredLists = required.stream()
                  .filter(this::isList)
                  .map(f -> new RequiredList<>(f, view))
                  .filter(l -> Element.class.isAssignableFrom(l.genericType()) ||
                          View.class.isAssignableFrom(l.genericType()) ||
                          Findable.class.isAssignableFrom(l.genericType()))
                  .collect(Collectors.toList());
  
          requiredObjects = required.stream()
                  .filter(f -> !isList(f))
                  .map(this::fieldToObject)
                  .collect(Collectors.toList());
  
          if (requiredLists.isEmpty() && requiredObjects.isEmpty()) {
              throw new NoRequiredElementsException(view);
          }
      }
docs: Reflectively examine the view, gathering, filtering, and sorting fields. The results are
  assigned to {@link #requiredLists} and {@link #requiredObjects}; fields that are lists and
  objects of fields that are not lists, respectively. This method is idempotent; subsequent
  calls after the first have no effect (fields need only be analyzed once).
  
  <p>Fields cannot be analyzed before they are assigned, which is why this analyze is delayed
  until needed. This way you can instantiate an Analyzer in a constructor or {@code <init>}
  without worrying about whether your class or subclass fields are assigned yet.