Image

Imageunix_junkie wrote in Imageru_java

Как в JDK 1.6 реализован SQLException.iterator() и как это можно упростить

Начиная с 1.6, SQLException реализует Iterable; подробности здесь.
    public Iterator<Throwable> iterator() {

       return new Iterator<Throwable>() {

           SQLException firstException = SQLException.this;
           SQLException nextException =
               firstException.getNextException();
           Throwable cause = firstException.getCause();

           public boolean hasNext() {
               if(firstException != null || nextException != null
                       || cause != null)
                   return true;
               return false;
           }

           public Throwable next() {
               Throwable throwable = null;
               if(firstException != null){
                   throwable = firstException;
                   firstException = null;
               }
               else if(cause != null){
                   throwable = cause;
                   cause = cause.getCause();
               }
               else if(nextException != null){
                   throwable = nextException;
                   cause = nextException.getCause();
                   nextException = nextException.getNextException();
               }
               else
                   throw new NoSuchElementException();
               return throwable;
           }

           public void remove() {
               throw new UnsupportedOperationException();
           }

       };

    }
  • Во-первых, метод hasNext() реализован по-идиотски.
    if (<булевское выражение>) then return true; else return false; --
    признаться, я давно такого не видел. Они б ещё return <булевское выражение> ? true : false ? true : false; написали.

  • Во-вторых, одно поле (firstException) и одну локальную переменную (throwable в next()) можно к чертям выкинуть. Изменённый код медленнее понимается новичками (которые всё равно чужого кода не читают), но зато самую малость элегантнее.

От нас потребуется изменить инициализацию полей с вот такой:
SQLException firstException = SQLException.this;
SQLException nextException = firstException.getNextException();
Throwable cause = firstException.getCause();

на вот такую:
SQLException nextException = SQLException.this;
Throwable cause = null;

и переписать метод next() в виде:
public Throwable next() {
        if (!this.hasNext()) {
                throw new NoSuchElementException();
        }

        final boolean causeNull = this.cause == null;

        try {
                return causeNull ? this.nextException : this.cause;
        } finally {
                this.cause = (causeNull
                                ? this.nextException
                                : this.cause).getCause();
                if (causeNull) {
                        this.nextException =
                                this.nextException.getNextException();
                }
        }
}

Разумеется, переписанный hasNext() будет выглядеть след. образом:
public boolean hasNext() {
        return this.nextException != null || this.cause != null;
}


Собственно, вот и все дела.