Можно ли сделать анонимные внутренние классы в Java статическими?

В Java вложенные классы могут быть либо static, либо нет. Если они static, они не содержат ссылку на указатель содержащего экземпляра (они также больше не называются внутренними классами, они называются вложенными классами).

Если забыть создать вложенный класс static, когда ему не нужна эта ссылка, это может привести к проблемам со сборкой мусора или анализом escape.

Можно ли также создать анонимный внутренний класс static? Или компилятор выяснит это автоматически (что могло бы быть, потому что не может быть никаких подклассов)?

Например, если я создаю анонимный компаратор, мне почти никогда не нужна ссылка на внешнюю страницу:

  Collections.sort(list, new Comparator<String>(){
       int compare(String a, String b){
          return a.toUpperCase().compareTo(b.toUpperCase());
       }
  }
114 голосов | спросил Thilo 17 AMpFri, 17 Apr 2009 04:23:57 +040023Friday 2009, 04:23:57

6 ответов


0

Нет, вы не можете, и нет, компилятор не может понять это. Вот почему FindBugs всегда предлагает заменить анонимные внутренние классы именованными static вложенными классами, если они не используют свои неявные this ссылка.

Правка . Том Хоутин: Тэклайн говорит, что если анонимный класс создается в статическом контексте (например, в main), анонимный класс фактически является static. Но JLS не согласен :

  

Анонимный класс никогда не является abstract (§8.1.1.1). Анонимный класс всегда является внутренним классом (§8.1.3); это никогда не static (§8.1.1, §8.5.1). Анонимный класс всегда неявно final (§8.1.1.2).

Java-словарь Роди Грина говорит, что тот факт, что анонимные классы разрешены в статическом контексте зависит от реализации:

  

Если вы хотите сбить с толку тех, кто поддерживает ваш код, виги обнаружили, что javac.exe разрешит анонимные классы внутри static код инициализации и методы static, несмотря на то, что спецификация языка говорит, что анонимный классы никогда не являются static. Эти анонимные классы, конечно, не имеют доступа к полям экземпляра объекта. Я не рекомендую делать это. функция может быть отключена в любое время.

Правка 2: JLS на самом деле более подробно описывает статические контексты в §15.9.2 :

  

Пусть C будет экземпляром создаваемого класса, а i будет создаваемым экземпляром. Если C является внутренним классом, то i может иметь непосредственно включающий экземпляр. Непосредственно включенный экземпляр i (§8.1.3) определяется следующим образом.

     
  • Если C является анонимным классом, то:      
    • Если выражение создания экземпляра класса происходит в статическом контексте (§8.1.3), то i не имеет немедленно включающего экземпляра.
    •   
    • В противном случае немедленно включающий экземпляр i будет this.
    •   
  •   

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

ответил Michael Myers 17 AMpFri, 17 Apr 2009 04:43:56 +040043Friday 2009, 04:43:56
0

Вид. Анонимный внутренний класс, созданный в статическом методе, очевидно, будет эффективно статическим, потому что нет никакого источника для внешнего this.

Есть некоторые технические различия между внутренними классами в статических контекстах и ​​статическими вложенными классами. Если вам интересно, прочитайте JLS 3rd Ed.

ответил Tom Hawtin - tackline 17 PMpFri, 17 Apr 2009 14:18:59 +040018Friday 2009, 14:18:59
0

Я думаю, что здесь есть некоторая путаница в номенклатуре, которая, по общему признанию, слишком глупа и запутана.

Как бы вы их ни называли, эти шаблоны (и несколько вариантов с разной видимостью) являются всеми возможными, нормальными, легальными Java:

public class MyClass {
  class MyClassInside {
  }
}

public class MyClass {
  public static class MyClassInside {
  }
}

public class MyClass {
  public void method() {
    JComponent jc = new JComponent() {
      ...
    }
  }
}

public class MyClass {
  public static void myStaticMethod() {
    JComponent jc = new JComponent() {
      ...
    }
  }
}

Они учитываются в спецификации языка (если вы действительно обеспокоены этим, см. раздел 15.9.5.1, посвященный статическому методу).

Но эта цитата просто неверна :

  

javac.exe разрешит анонимный доступ   классы внутри статического кода инициализации и   статические методы, хотя   спецификация языка говорит чем аноним   классы никогда не бывают статичными

Я думаю, что цитируемый автор путает статическое ключевое слово со статическим context . (Следует признать, что JLS также немного запутан в этом отношении.)

Честно говоря, все вышеперечисленные шаблоны в порядке (все, что вы называете "вложенными", "внутренними", "анонимными", как угодно ...). Действительно, никто не собирается внезапно удалять эту функциональность в следующем выпуске Java. Честно!

ответил Neil Coffey 17 PMpFri, 17 Apr 2009 19:13:32 +040013Friday 2009, 19:13:32
0

Внутренние классы не могут быть статичными - статический вложенный класс не является внутренним классом. Об этом рассказывается в руководстве по Java . р>

ответил Andrew Duffy 17 AMpFri, 17 Apr 2009 04:43:15 +040043Friday 2009, 04:43:15
0

анонимные внутренние классы никогда не являются статическими (они не могут объявлять статические методы или неконечные статические поля), но если они определены в статическом контексте (статический метод или статическое поле), они ведут себя как статические в том смысле, что они не может получить доступ к нестатическим (то есть экземплярам) членам включающего класса (как и все остальное из статического контекста)

ответил Luca 2 FebruaryEurope/MoscowbTue, 02 Feb 2016 14:19:59 +0300000000pmTue, 02 Feb 2016 14:19:59 +030016 2016, 14:19:59
0

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

Это на самом деле не удаляет ссылку. Вы можете проверить это, попытавшись сериализовать анонимный класс и не делая сериализуемый класс включения

.
ответил Terra Caines 21 MaramMon, 21 Mar 2011 03:51:06 +03002011-03-21T03:51:06+03:0003 2011, 03:51:06

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132