Rozjaśniłbym nieco czytelność wyrażeń, korzystając ze starych i dobrych praw logiki: :)
private final Criterion getOrRestrictions(final List<Criterion> crits, final int n)
{
if ((crits == null || crits.size() <= 2))
return null;
if (crits.size() == n + 2)
return Restrictions.or(crits.get(n), crits.get(n+1));
return Restrictions.or(crits.get(n), this.getOrRestrictions(crits, n+1));
}
Rozumiem, że metoda get(int n) jest przeciążona i ściąga od razu elementy z listy?
Bo używasz size(), więc musisz jakoś skracać listę, a ona jako argument idzie przez referencję, a nie przez wartość. A więc w pełnej długości trafia do każdej instancji tej metody.
Poza tym szepnąłbym jeszcze, że w obu wypadkach modyfikator final, to placebo. ;)
I jeszcze zastanowiłbym się czy nie wywoływać z (n-1) i (n) - bo wtedy wiedziałbym dokładnie, że jak n porównam z zerem, to nic już nie zostanie. A ty porównujesz z n + 2 - więc łatwo o pomyłkę w innej części kodu.