Как умножить 10 на объект «Целое число» в Java?

Как мне умножить 10 на объект Integer и вернуть объект Integer?

Я ищу самый изящный способ сделать это.

Я бы сделал это, наверное, так: Получите int из объекта Integer, умножьте его на другой int и создайте другой объект Integer с этим значением int.

Код будет примерно таким ...

integerObj = new Integer(integerObj.intValue() * 10);

Но я видел код, в котором автор делает это следующим образом: получить String из объекта Integer, объединить «0» в конце и затем вернуть объект Integer с помощью Integer.parseInt.

Код выглядит примерно так:

String s = integerObj + "0";
integerObj = Integer.parseInt(s);

Есть ли какая-то заслуга в том, чтобы делать это в любом случае?

И какой способ в целом и в данном случае был бы наиболее эффективным / изящным?

Я также посоветовал бы вам проверить, ДЕЙСТВИТЕЛЬНО ли необходимо использование Integer. Джошуа указал, что использование примитивов во много раз быстрее в Effective Java. Так что, если можете, придерживайтесь int.

Marcio Aguiar 05.09.2008 19:54

Использование Integer на самом деле является ограничением дизайна. Идея в том, что я получаю объект Integer, и мне нужно его обновить. Так что не могу с этим покончить :)

Jagmal 05.09.2008 21:40

<pedantry> Обновление существующего объекта Integer не произойдет без отражения вуду. (Целое число, как и другие типы примитивных оболочек, неизменяемо.) Лучшее, что вы можете разумно сделать - и то, что сделает любой разумный пример, - это заменить его другим объектом. Этого достаточно для большинства случаев, но означает, что void modifyInteger(Integer i) не сделает ничего стоящего.

cHao 15.04.2014 06:48
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
9
3
26 980
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Строковый подход забавен, но почти наверняка это плохой способ.

Получение значения int для Integer и создание нового будет очень быстрым, тогда как вызов parseInt будет довольно дорогостоящим.

В целом, я согласен с вашим первоначальным подходом (который, как отмечали другие, можно сделать без лишнего беспорядка, если у вас есть автобоксинг, представленный в Java 5).

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

С помощью Java 5 автобокс вы можете просто сделать:

Integer a = new Integer(2); // or even just Integer a = 2;
a *= 10;
System.out.println(a);

Не рекомендуется использовать конструктор Integer. Вместо этого используйте autoboxing или valueOf () ...

Steven Schlansker 29.01.2010 11:32

Держитесь подальше от второго подхода, лучше всего будет автобокс, если вы используете java 1.5, лучше всего подойдет все, что раньше, ваш первый пример.

Решение с использованием метода String не так хорошо по ряду причин. Некоторые из них являются эстетическими, другие - практичными.

На практике версия String создает больше объектов, чем более обычная форма (как вы выразились в своем первом примере).

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

Проблема со вторым способом заключается в том, как строки обрабатываются в Java:

  • "0" преобразуется в постоянный объект String во время компиляции.
  • Каждый раз, когда вызывается этот код, s создается как новый объект String, а javac преобразует этот код в String s = new StringBuilder().append(integerObj.toString()).append("0").toString() (StringBuffer для более старых версий). Даже если вы используете тот же integerObj, т.е.

    String s1 = integerObj + "0"; String s2 = integerObj + "0";

    (s1 == s2) будет false, а s1.equals(s2) будет true.

  • Integer.parseInt все равно внутренне вызывает new Integer(), потому что Integer неизменяемый.

Кстати, автобоксинг / распаковка внутренне такая же, как и у первого метода.

Integer.parseInt(...) не должен создавать целочисленный объект, он напрямую работает с примитивом int.

Paŭlo Ebermann 04.07.2011 17:41

Приведенный выше ответ инструментария является правильным и лучшим способом, но он не дает полного объяснения того, что происходит. Предполагая, что Java 5 или новее:

Integer a = new Integer(2); // or even just Integer a = 2;
a *= 10;
System.out.println(a); // will output 20

Что вам нужно знать, так это то, что это то же самое, что и:

Integer a = new Integer(2); // or even just Integer a = 2;
a = a.intValue() * 10;
System.out.println(a.intValue()); // will output 20

Выполняя операцию (в данном случае * =) над объектом 'a', вы не изменяете значение int внутри объекта 'a', а фактически присваиваете новый объект 'a'. Это связано с тем, что "a" автоматически распаковывается для выполнения умножения, а затем результат умножения автоматически упаковывается и присваивается "a".

Целое число - неизменяемый объект. (Все классы-оболочки неизменяемы.)

Возьмем, к примеру, этот фрагмент кода:

static void test() {
    Integer i = new Integer(10);
    System.out.println("StartingMemory: " + System.identityHashCode(i));
    changeInteger(i);
    System.out.println("Step1: " + i);
    changeInteger(++i);
    System.out.println("Step2: " + i.intValue());
    System.out.println("MiddleMemory: " + System.identityHashCode(i));
}

static void changeInteger(Integer i) {
    System.out.println("ChangeStartMemory: " + System.identityHashCode(i));
    System.out.println("ChangeStartValue: " + i);
    i++;
    System.out.println("ChangeEnd: " + i);
    System.out.println("ChangeEndMemory: " + System.identityHashCode(i));
}

Результатом будет:

StartingMemory: 1373539035
ChangeStartMemory: 1373539035
ChangeStartValue: 10
ChangeEnd: 11
ChangeEndMemory: 190331520
Step1: 10
ChangeStartMemory: 190331520
ChangeStartValue: 11
ChangeEnd: 12
ChangeEndMemory: 1298706257
Step2: 11
MiddleMemory: 190331520

Вы можете видеть, что адрес памяти для «i» меняется (ваши адреса памяти будут другими).

Теперь давайте проведем небольшой тест с отражением, добавим это в конец метода test ():

System.out.println("MiddleMemory: " + System.identityHashCode(i));
try {
    final Field f = i.getClass().getDeclaredField("value");
    f.setAccessible(true);
    f.setInt(i, 15);
    System.out.println("Step3: " + i.intValue());
    System.out.println("EndingMemory: " + System.identityHashCode(i));
} catch (final Exception e) {
    e.printStackTrace();
}

Дополнительный вывод будет:

MiddleMemory: 190331520
Step2: 15
MiddleMemory: 190331520

Вы можете видеть, что адрес памяти для 'i' не изменился, хотя мы изменили его значение с помощью отражения. (НЕ ИСПОЛЬЗУЙТЕ ОТРАЖЕНИЕ ТАК В РЕАЛЬНОЙ ЖИЗНИ !!)

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