Кастинг Java представляет наверху? Почему?

Есть ли какие-либо издержки, когда мы бросаем объекты одного типа другому? Или компилятор просто разрешает все и нет никакой стоимости во время выполнения?

Действительно ли это - генерал вещи, или существуют различные случаи?

Например, предположите, что у нас есть массив Объекта [], где каждый элемент мог бы иметь другой тип. Но мы всегда знаем наверняка, что, скажем, элемент 0 является Двойным, элементом 1 является Строка. (Я знаю, что это - неправильный дизайн, но позвольте нам просто предположить, что я должен был сделать это.)

Информация о типе Java все еще имеется в наличии во время выполнения? Или обо всем забывают после компиляции, и если мы действительно (Удваиваем) элементы [0], мы будем просто следовать за указателем и интерпретировать те 8 байтов как двойное, независимо от того, что это?

Я очень неясен о том, как типы сделаны в Java. Если у Вас есть какая-либо рекомендация на книгах, или статья тогда благодарит, также.

95
задан Phil 31 January 2010 в 07:10
поделиться

4 ответа

Относительный виртуальный адрес - это смещение от адреса, по которому загружается файл. Наверное, самый простой способ получить идею на примере. Предположим, что имеется файл (например, DLL), загруженный по адресу 1000h. В этом файле имеется переменная RVA 200h. В этом случае VA этой переменной (после отображения DLL в память) составляет 1200 ч (т.е. 1000 ч базового адреса DLL плюс 200 ч RVA (смещение) к переменной.

-121--1090101-

gcc -c создаст файл .o, который является файлом объекта формата elf, в системе Linux. «ELF 32-разрядный LSB с возможностью перемещения, Intel 80386, версия 1 (SYSV)» - это то, как файл .o описывается командой file на моем компьютере.

-121--2702177-

Существует 2 типа литья:

Неявное литье, когда вы выполняете литье из типа в более широкий тип, которое выполняется автоматически и не накладывается накладные расходы:

String s = "Cast";
Object o = s; // implicit casting

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

Object o = someObject;
String s = (String) o; // explicit casting

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

Взято из JavaWorld: Стоимость кастинга

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

Операции Upcast (также называемые расширение преобразований в Java Языковая спецификация) преобразовать ссылка подкласса на предка ссылка на класс. Это литье работа, как правило, автоматическая, поскольку это всегда безопасно и может быть реализовано непосредственно компилятором.

Операции Downcast (также называемые сужение конверсий в Java Языковая спецификация) преобразовать ссылка класса-предка на подкласс ссылка. Эта операция литья создает накладные расходы на выполнение, поскольку Java требует, чтобы отливка была проверена на время выполнения, чтобы убедиться, что он действителен. Если ссылочный объект не является экземпляр либо целевого типа для приведение или подкласс этого типа, попытка приведения не разрешена и должен бросить java.lang. ClassCastException.

72
ответ дан 24 November 2019 в 05:52
поделиться

Например, предположим, что у нас есть массив объекта [], где каждый элемент может иметь другой тип. Но мы всегда знаем, что, скажем, элемент 0 - двойной, элемент 1 - это строка. (Я знаю, что это неверный дизайн, но давайте просто предполагаем, что я должен был сделать это.)

Компилятор не замечает типы отдельных элементов массива. Он просто проверяет, что тип каждого элемента экспрессии назначается типу элемента массива.

Является ли информация типа Java, все еще сохранена во время выполнения? Или все забыто после компиляции, и если мы сделаем (дважды) элементы [0], мы просто будем следовать указатель и интерпретировать эти 8 байтов в виде двойного, что бы то ни было?

Некоторая информация содержится во время выполнения , но не статические типы отдельных элементов. Вы можете сказать это от поиска формата файла класса.

Теоретически возможно, что компилятор JIT может использовать «анализ Escape», чтобы устранить ненужные проверки типа в некоторых заданиях. Тем не менее, делать это со степенью, которую вы предлагаете, будут за пределами реалистической оптимизации. Выплата анализа типов отдельных элементов будет слишком маленьким.

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

7
ответ дан 24 November 2019 в 05:52
поделиться

Я не могу использовать конструктор «int length» для StringBuilder , так как длина CLOB превышает int и ему необходимо значение long .

Если длина CLOB больше, чем соответствует int, данные CLOB также не будут помещаться в последовательность. Для обработки такого количества XML-данных необходимо использовать потоковый подход.

Если фактическая длина CLOB меньше Integer.MAX _ VALUE , просто переместите long в int , поставив перед ним (int) .

-121--1203229-

Вместо выполнения файла .reg необходимо внести изменения в реестр с помощью функциональных возможностей, предусмотренных в пространстве имен Microsoft.Win32 .

Довольно просто создать раздел реестра с помощью этого API:

RegistryKey key = Registry.CurrentUser.CreateSubKey("Names");
key.SetValue("Name", "Isabella");
key.Close();

Если не требуется создать массовую загрузку новых ключей, я считаю, что API является более масштабируемым и поддерживаемым подходом. Если в какой-то момент необходимо сделать необязательным запись параметров настройки в системную или пользовательскую ветвь реестра, большая часть кода будет повторно использоваться в обоих случаях. Просто выберите другой ключ, чтобы сделать изменения.

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

-121--1325901-

Для разумной реализации Java:

Каждый объект имеет заголовок, содержащий, среди прочего, указатель на тип среды выполнения (например, Double или Последовательностей , но никогда не может быть CharSequence или AbstractList ). Предполагая, что компилятор среды выполнения (как правило, HotSpot в случае Sun) не может определить тип статически, некоторая проверка должна быть выполнена сгенерированным машинным кодом.

Сначала необходимо прочитать указатель на тип среды выполнения. Это в любом случае необходимо для вызова виртуального метода в подобной ситуации.

Для приведения к типу класса точно известно, сколько суперклассов существует, пока вы не нажмете java.lang.Object , так что тип может быть считан с постоянным смещением от указателя типа (фактически первые восемь в HotSpot). Опять же, это аналогично считыванию указателя метода для виртуального метода.

Тогда считанное значение просто требует сравнения с ожидаемым статическим типом приведения. В зависимости от архитектуры набора команд другая команда должна перейти (или выйти из строя) на неправильную ветвь. ISA, такие как 32-разрядные ARM, имеют условную инструкцию и могут иметь возможность прохождения печального пути через счастливый путь.

Интерфейсы являются более сложными из-за множественного наследования интерфейса. Как правило, последние две операции с интерфейсами кэшируются во время выполнения. В САМЫЕ ранние дни (более десяти лет назад),интерфейсы были немного медленными, но это уже не актуально.

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

43
ответ дан 24 November 2019 в 05:52
поделиться

Инструкция по байтому коду для выполнения кастинга во время выполнения называется Checkcast . Вы можете разобрать код Java с использованием Javap , чтобы увидеть, какие инструкции генерируются.

Для массивов Java хранит информацию во время выполнения. Большую часть времени компилятор будет для вас ошибок типа, но есть случаи, когда вы столкнетесь с ArrayStoreexception при попытке хранить объект в массиве, но тип не совпадает (и Компилятор не поймал его). SPEC Java Language Spec дает следующий пример:

class Point { int x, y; }
class ColoredPoint extends Point { int color; }
class Test {
    public static void main(String[] args) {
        ColoredPoint[] cpa = new ColoredPoint[10];
        Point[] pa = cpa;
        System.out.println(pa[1] == null);
        try {
            pa[0] = new Point();
        } catch (ArrayStoreException e) {
            System.out.println(e);
        }
    }
}

точка [] PA = CPA действительна с окрашенной точки - это подкласс точки, но PA [0 ] = Новая точка () недействительна.

Это противостоит универсальным типам, где нет информации о типах, хранящихся во время выполнения. Компилятор вставки Checkcast Инструкции, где это необходимо.

Эта разница в печати для общих типов и массивов делает его часто неподходящими для смешивания массивов и универсальных типов.

5
ответ дан 24 November 2019 в 05:52
поделиться
Другие вопросы по тегам:

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