Почему это превышает 65 535-байтовый предел в конструкторах Java и статических Инициализаторах?

Два возможных обходных пути:

  1. Переместить Object.assign в дочерний класс
  2. Создать фабрику, которая будет возвращать экземпляры классов:

    export interface Ctor<T> {
        new(...parts: Partial<T>[]): T;
    }

    export class Factory {
        public static Get<T extends object>(ctor: Ctor<T>, ...props: Partial<T>[]): T {
            const res = new ctor();
            Object.assign(res, ...props);
            return res;
        }
    }
9
задан Craig 28 April 2015 в 00:54
поделиться

6 ответов

Вот байт-код для инициализации массива {1000001, 1000002, 1000003}:

 5  iconst_3
 6  newarray int [10]
 8  dup
 9  iconst_0
10  ldc <Integer 1000001> [12]
12  iastore
13  dup
14  iconst_1
15  ldc <Integer 1000002> [13]
17  iastore
18  dup
19  iconst_2
20  ldc <Integer 1000003> [14]
22  iastore
23  putfield net.jstuber.test.TestArrayInitializingConstructor.data : int[] [15]

Таким образом, для этого небольшого массива каждому элементу требуется 5 байт байт-кода Java. Для вашего большего массива и индекс массива, и индекс в пуле констант будут использовать 3 байта для большинства элементов, что приводит к 8 байтам на элемент массива. Таким образом, для 10000 элементов вы должны ожидать около 80 КБ байтового кода.

Код для инициализации больших массивов с 16-битными индексами выглядит следующим образом:

2016  dup
2017  sipush 298
2020  ldc_w <Integer 100298> [310]
2023  iastore
2024  dup
2025  sipush 299
2028  ldc_w <Integer 100299> [311]
13
ответ дан 4 December 2019 в 11:08
поделиться

Литералы массива переводятся в байтовый код, который заполняет массив значениями, поэтому вам нужно еще несколько байтов для каждого числа.

Почему бы не переместить эти данные в ресурс, который вы загружаете во время загрузки класса в статический блок инициализатора? Это легко сделать с помощью MyClass.class.getClassLoader (). GetResourceAsStream () . Похоже, что это то, к чему он принадлежит, в любом случае.

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

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

Помимо значений целых чисел, конструктор и инициализатор должны содержать инструкции JVM для загрузки целых чисел в массив.

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

Гораздо более простой и практичный подход - хранить числа в файле, либо в двоичном формате, либо в виде текста.

Я не знаю, что инициализирует Java массивы таким образом,

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

Я думаю, что размер кода в символах превышает 65535. Не память, занятая 10000 целыми числами.

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

Я думаю, вполне возможно, что это объем памяти, необходимый для буквенного представления этих целых чисел. Я думаю, что этот предел может применяться к самому коду, поэтому каждое int, например: 1494512072, на самом деле занимает 10 байтов (по одному на цифру) вместо только 4 байтов, используемых для int32.

-4
ответ дан 4 December 2019 в 11:08
поделиться
Другие вопросы по тегам:

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