как частный метод внутреннего класса в java доступен вне его класса? [Дубликат]

1/2) Индексы ускоряют определенные операции выбора, но замедляют другие операции, такие как вставка, обновление и удаление. Это может быть прекрасный баланс.

3) используйте полный текстовый индекс или, возможно, sphinx

27
задан Matthias 4 January 2013 в 13:40
поделиться

4 ответа

(Редактировать: расширен ответ на некоторые комментарии)

Компилятор берет внутренние классы и превращает их в классы верхнего уровня. Поскольку частные методы доступны только для внутреннего класса, компилятор должен добавить новые «синтетические» методы, которые имеют доступ к уровню пакета, чтобы классы верхнего уровня имели к нему доступ.

Что-то вроде этого (добавляются компилятором $):

class A 
{
    private void f() 
    {
        final B b;

        b = new B();

        // call changed by the compiler
        b.$g();
    }

    // method generated by the compiler - visible by classes in the same package
    void $f()
    {
        f();
    }
}

class B
{
    private void g() 
    {
        final A a;

        a = new A();

        // call changed by the compiler
        a.$f();
    }

    // method generated by the compiler - visible by classes in the same package
    void $g()
    {
        g();
    }
}

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

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

Компилятор берет внутренний класс и превращает его в класс верхнего уровня (таким образом, на уровне VM нет такой вещи, как внутренний класс). Затем компилятор должен сгенерировать новые методы «пересылки». Они создаются на уровне пакета (не общедоступны), чтобы обеспечить доступ к ним только для классов в одном пакете. Компилятор также обновил вызовы методов для частных методов для сгенерированных методов «пересылки».

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

Редактировать:

Да, вы можете вызвать сгенерированный (синтетический) метод, но НЕ ДЕЛАЙТЕ ЭТО !:

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class Main
{
    public static void main(final String[] argv)
        throws Exception
    {
        final Class<?> clazz;

        clazz = Class.forName("NotPrivate$A");        

        for(final Method method : clazz.getDeclaredMethods())
        {
            if(method.isSynthetic())
            {
                final Constructor constructor;
                final Object instance;

                constructor = clazz.getDeclaredConstructor(new Class[0]);
                constructor.setAccessible(true);
                instance = constructor.newInstance();
                method.setAccessible(true);
                method.invoke(null, instance);
            }
        }
    }
}
26
ответ дан TofuBeer 25 August 2018 в 08:02
поделиться

Я думаю, что эта цитата прекрасно комментирует это:

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

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

14
ответ дан Eric Petroelje 25 August 2018 в 08:02
поделиться

Требуется работать по заданию, т. е. Java Language Spec говорит так:

6.6.1 Определение доступности (по крайней мере, с JLS6)

"В противном случае, если член или конструктор объявлен приватным, доступ разрешен тогда и только тогда, когда он встречается внутри тела класса верхнего уровня (§7.6), который включает объявление члена или конструктора. "

Т.е. «область доступа» частного члена: везде в пределах лексических границ тела класса верхнего уровня.

Это означает: все частные члены, которые определены в классе-классе самого внешнего класса могут быть доступны во всем мире в этом классе.

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

0
ответ дан EternalBeginner 25 August 2018 в 08:02
поделиться

Java компилируется в специальных аксессуарах с $ в них. Таким образом, вы не можете писать Java, доступ к частным методам. Объясняется здесь:

http://www.retrologic.com/innerclasses.doc7.html

Существует еще одна категория компилятора - сгенерированных членов. Частный член m класса C может использоваться другим классом D, если один класс заключает другое, или если он заключен в общий класс. Поскольку виртуальная машина не знает об этой группировке, компилятор создает локальный протокол методов доступа на C, чтобы позволить D читать, писать или вызывать элемент m. Эти методы имеют имена формы доступа $ 0, доступ $ 1 и т. Д. Они никогда не являются общедоступными. Методы доступа уникальны тем, что они могут быть добавлены в классы, а не только внутренние классы.

3
ответ дан Lou Franco 25 August 2018 в 08:02
поделиться
Другие вопросы по тегам:

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