Java/SpotBugs, что такое "именованный статический внутренний класс", если он объявлен в интерфейсе?

Я унаследовал кодовую базу, которая использует MyBatis. SpotBugs говорит мне, что это SubjectRepositoryQueriescould be refactored into a named _static_ inner class. Я никогда не сталкивался с этим термином, я надеялся, что кто-нибудь сможет объяснить, что именно он просит меня сделать лучше. Казалось бы, что SubjectRepositoryQueries на самом деле называется (это не аноним), и это уже статично. SubjectRepositoryQueries не может быть объявлено закрытым, потому что оно внутри интерфейса.

@Mapper
public interface SubjectRepositoryService {
  @SelectProvider(type = SubjectRepositoryQueries.class, method = "search")
  List<Subject> search(SubjectSearch subjectSearch);

  static final class SubjectRepositoryQueries {
    public String search(final SubjectSearch subjectSearch) {
      ... some string generation
    }
  }
}

Спасибо!

2 ответа

Решение

Непонятно, что означает конкретное предупреждение. Если ваша единственная цель - удалить предупреждение, то, учитывая, что ваш внутренний класс не реализует интерфейс, вы можете просто преобразовать его в статический метод.

@Mapper
public interface SubjectRepositoryService {
    //...

    static String search(final SubjectSearch subjectSearch) {
        //... some string generation
    }
}

Когда вы объявляете внутренний класс

class Outer {
    class Inner {
    }
}

даже если вы не объявили никаких полей во Inner, компилятор java автоматически вставит синтетическое поле, которое содержит ссылку на внешний класс, обычно называемое чем-то вроде этого $0. Так что, если вы запустите javap во внутреннем классе, вы увидите это.

Идея состоит в том, что во многих случаях наличие этой ссылочной переменной является пустой тратой пространства и, что более важно, приводит к тому, что такие вещи, как сериализация, вызывают непредвиденные проблемы.

Представьте, что во внешнем классе были все виды полей, и он был массивным. Теперь представьте, что вы хотите сериализовать только внутренний класс, если вы попытаетесь это сделать, вы будете удивлены, обнаружив, что весь внутренний и внешний экземпляр будут сериализованы, что приведет к гораздо более медленному и большему опыту.

Декорируя внутренний класс с помощью "static", вы удаляете эту синтетическую ссылку на поле внешнего класса и не допускаете этого.

Есть и другие вещи, которые вызывает нормальный внутренний класс. Например, вы не можете создать экземпляр внутреннего класса, не создавая внешний класс, который вызывает действительно загадочный синтаксис, такой как

Outer.Inner i = new Outer().new Inner();
Другие вопросы по тегам