Статический членский класс - объявляет частный класс и частный на пакет участник класса?

Полагайте, что у Вас есть следующий класс

public class OuterClass {
    ...

    private static class InnerClass {
         int foo;
         int bar;
    }
}

Я думаю, что читал где-нибудь (но не официальное Учебное руководство по Java), что, если я объявил бы статические членские частные атрибуты классов, компилятор должен был генерировать своего рода методы доступа так, чтобы внешний класс мог на самом деле получить доступ к статическому членскому классу (который является эффективно частным на пакет высокоуровневым классом), атрибуты.

Какие-либо идеи об этом?

5
задан helpermethod 27 May 2010 в 10:26
поделиться

2 ответа

Да, это правда. По крайней мере, для Sun javac. Взгляните на следующий пример:

public class OuterClass {

    public static void main(String... args) {
        InnerClass.foo = 7;
        System.out.println(InnerClass.foo);
    }

    private static class InnerClass {
         private static int foo;
         private static int bar;
    }
}

$ javap -c OuterClass\$InnerClass
Compiled from "OuterClass.java"
class OuterClass$InnerClass extends java.lang.Object{
static int access$002(int);
  Code:
   0: iload_0
   1: dup
   2: putstatic #1; //Field foo:I
   5: ireturn

static int access$000();
  Code:
   0: getstatic #1; //Field foo:I
   3: ireturn

}

Он определяет статический доступ к int $ 002 (int) для установки значения и статический доступ к int $ 000 () для получения значения . Установщик также возвращает значение, предположительно для упрощения компиляции someVariable = InnerClass.foo = 5 .


$ javap -c OuterClass
Compiled from "OuterClass.java"
public class OuterClass extends java.lang.Object{
public OuterClass();
  Code:
   0: aload_0
   1: invokespecial #1; //Method java/lang/Object."<init>":()V
   4: return

public static void main(java.lang.String[]);
  Code:
   0: bipush 7
   2: invokestatic #2; //Method OuterClass$InnerClass.access$002:(I)I
   5: pop
   6: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
   9: invokestatic #4; //Method OuterClass$InnerClass.access$000:()I
   12: invokevirtual #5; //Method java/io/PrintStream.println:(I)V
   15: return

}

В строке 2 и строке 9 он вызывает установщик ( доступ к $ 002 ) и получатель ( доступ к $ 000 ) соответственно.


Обратите внимание, что эти методы доступа вводятся только в том случае, если они необходимы. Например, к полю bar никогда не обращались извне класса, поэтому компилятор только сгенерировал геттер / сеттер для поля foo .

4
ответ дан 14 December 2019 в 08:44
поделиться

Есть какие-нибудь идеи по этому поводу?

Ответ @ aioobe показывает, что вы были правы.

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

Это говорит о том, что нет смысла преждевременно «оптимизировать» код с помощью модификаторов доступа, которые говорят что-то отличное от того, что вы действительно хотите выразить.

3
ответ дан 14 December 2019 в 08:44
поделиться
Другие вопросы по тегам:

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