Создание объекта класса, кроме как через конструктор

В Java дано

Class c = ...

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

c.getConstructor().newInstance()

Это кажется простым и похоже на то, как все делается в исходном коде Java.

Но, что любопытно, в байт-коде JVM дела обстоят иначе. Там создание объекта выполняется в два этапа: new для фактического создания объекта, затем invokespecial для вызова соответствующего конструктора.

Есть ли способ обойти конструктор, когда у вас есть Class (с фактическим классом, который должен быть определен во время выполнения)? Если нет, то было ли когда-либо документировано обоснование разницы между тем, как это работает, и тем, как работает байт-код?

stackoverflow.com/questions/25447910/…
Sotirios Delimanolis 17.02.2023 16:02
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
1
53
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы хотите выделить неинициализированный объект.

Вы можете попробовать библиотеку под названием Objenesis.

В противном случае вы можете создать объект путем сериализации. Это широко используемый метод для создания неинициализированного объекта.

public class Serialization {

    static class TestSerialization  implements Serializable {
        int val = 0;
        public TestSerialization() {
            System.out.println("constructor");
            val = 1;
        }

        @Override
        public String toString() {
            return "val is " + val;
        }
    }


    public static void main(String[] args) throws IOException, ClassNotFoundException {
        TestSerialization testSerialization = new TestSerialization();

        // constructor
        // val is 1
        System.out.println(testSerialization);

        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(testSerialization);
        oos.close();

        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
        Object obj = ois.readObject();
        // val is 1
        System.out.println(obj);
    }
}

На шаг ближе вы можете использовать ReflectionFactory для создания пустого неинициализированного объекта.

public class Main {

    static class TestClass {
        public int val = 0;

        public TestClass() {
            val = 1;
        }

        @Override
        public String toString() {
            return "value is " + val;
        }
    }

    public static void main(String[] args) throws Exception {

        // by constructor
        TestClass obj = new TestClass();
        // value is 1
        System.out.println(obj);

        // by reflect
        Constructor<TestClass> constructor = TestClass.class.getConstructor();
        obj = constructor.newInstance();
        // value is 1
        System.out.println(obj);

        // by ReflectionFactory
        ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory();
        Constructor<Object> objectConstructor = Object.class.getDeclaredConstructor();
        Constructor<?> targetConstructor = reflectionFactory.newConstructorForSerialization(TestClass.class, objectConstructor);
        obj = (TestClass) targetConstructor.newInstance();
        // value is 0
        System.out.println(obj);
    }
}

Другие вопросы по теме