Являются ли методы, вызываемые на объекте Proxy в Java, статическими?

Ответ

Нет, методы, вызываемые на объекте, созданном с помощью java.lang.reflect.Proxy, не являются статическими. Proxy создает динамическую реализацию интерфейса во время выполнения, и все вызовы методов на этом прокси-объекте перенаправляются в InvocationHandler. Эти вызовы — это обычные вызовы методов экземпляра.

Как это работает:

  1. Создается прокси-объект, реализующий указанный набор интерфейсов.
  2. При вызове любого метода на этом прокси срабатывает метод invoke() у связанного InvocationHandler.
  3. InvocationHandler решает, как обработать вызов (например, делегировать реальному объекту, добавить логирование).

Пример создания и использования Proxy:

import java.lang.reflect.*;

interface Service {
    String performAction();
}

Service realService = () -> "Real Action";

Service proxyInstance = (Service) Proxy.newProxyInstance(
    Service.class.getClassLoader(),
    new Class[]{Service.class},
    new InvocationHandler() {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("Proxy: Before method '" + method.getName() + "'");
            // Делегируем вызов реальному объекту
            Object result = method.invoke(realService, args);
            System.out.println("Proxy: After method '" + method.getName() + "'");
            return result;
        }
    }
);

// Вызов метода на прокси-объекте (не статический!)
String result = proxyInstance.performAction();
System.out.println(result); // Вывод: Proxy: Before... Real Action Proxy: After...

Ключевой вывод: Прокси — это обертка над экземпляром объекта (или логикой), а не механизм для вызова статических методов.

Ответ 18+ 🔞

А, слушай, вот эта тема с проксями в Java — это вообще отдельная песня, блядь. Многие думают, что раз Proxy из пакета reflect, то там какая-то магия статики, вуду и вызовы прямо из воздуха. Ан нет, ёпта!

Этот java.lang.reflect.Proxy — он не статику делает, он, сука, динамическую обёртку на лету лепит. Берёт интерфейс, берёт твой хендлер и создаёт такой объект-фантом, который все вызовы ловит и пихает прямиком в твой InvocationHandler. И все эти вызовы — они самые что ни на есть обычные, экземплярные. Никакой статики, блядь!

Как эта штука, блядь, работает, если по-простому:

  1. Ты говоришь: «Хочу проксю для вот этих интерфейсов». JVM, блядь, в ответ: «Ща, родим».
  2. Получается объект-пустышка, который умеет делать вид, что он реализует твои интерфейсы.
  3. Ты на нём вызываешь любой метод — хоть performAction(), хоть наебниМнеКофе().
  4. А система, сука, сразу перехватывает этот вызов и несёт его, как на блюдечке, в метод invoke() твоего хендлера. Всё, дальше твоя воля: что хочешь, то и делай.

Вот, смотри, как это выглядит в коде, чтоб совсем понятно было:

import java.lang.reflect.*;

// Интерфейс, который будем притворять
interface Service {
    String performAction();
}

// Реальный объект, который мы будем оборачивать (ну или не будем, хуй его знает)
Service realService = () -> "Real Action, блядь!";

// А вот и наша хитрая жопа — прокся!
Service proxyInstance = (Service) Proxy.newProxyInstance(
    Service.class.getClassLoader(),
    new Class[]{Service.class}, // Говорим, какие интерфейсы имитировать
    new InvocationHandler() {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // Сюда прилетает ВСЁ, что вызывают на проксе
            System.out.println("Прокся: Ща буду вызывать метод '" + method.getName() + "'. Волнение ебать!");
            // Делегируем вызов реальной железке
            Object result = method.invoke(realService, args);
            System.out.println("Прокся: Всё, отъебались. Метод '" + method.getName() + "' отработал.");
            return result;
        }
    }
);

// И вот самый момент истины! Вызываем метод НА ПРОКСИ-ОБЪЕКТЕ.
// Это не статический вызов, ёпта! Это вызов метода у конкретного экземпляра `proxyInstance`.
String result = proxyInstance.performAction();
System.out.println("Результат: " + result);

И что на выходе, блядь?

Прокся: Ща буду вызывать метод 'performAction'. Волнение ебать!
Прокся: Всё, отъебались. Метод 'performAction' отработал.
Результат: Real Action, блядь!

Так что запомни раз и навсегда: Прокся от Proxy — это как подставной актёр, который выглядит в точности как нужный тебе объект, но всю свою работу согласовывает с режиссёром-хендлером. И работает он только с экземплярами, а не со статикой. Статические методы он просто, блядь, не увидит и не перехватит — они же не привязаны к объекту! Вот такая, сука, матчасть.