Статический .lib требуется для компиляции библиотеки также требуется для пользователей библиотеки?

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

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

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

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);
            }
        }
    }
}
7
задан Tom Savage 2 July 2013 в 22:56
поделиться