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

StackOverflow https://stackoverflow.com/questions/45964

  •  09-06-2019
  •  | 
  •  

Вопрос

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

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

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

Код будет что-то вроде...

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

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

Код примерно такой:

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

Есть ли смысл делать это в любом случае?

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

Это было полезно?

Решение

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

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

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

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

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

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

Проблема второго способа заключается в том, как строки обрабатываются в 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 является неизменным.

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

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

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

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

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

Ответ инструментария выше правильный и лучший способ, но он не дает полного объяснения того, что происходит.Предполагая 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».Это связано с тем, что «а» автоматически распаковывается для выполнения умножения, а затем результат умножения автоматически распаковывается и присваивается «а».

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

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

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» не изменился, хотя мы изменили его значение с помощью отражения.
(НЕ ИСПОЛЬЗУЙТЕ ОТРАЖЕНИЕ ТАКИМ СПОСОБОМ В РЕАЛЬНОЙ ЖИЗНИ!!)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top