سؤال

كيف أضرب 10 في Integer اعترض وارجع Integer هدف؟

أنا أبحث عن أفضل طريقة للقيام بذلك.

ربما سأفعل ذلك بهذه الطريقة:احصل على من Integer كائن، اضربه مع int الآخر وأنشئ كائنًا صحيحًا آخر بقيمة int هذه.

الكود سيكون مثل...

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

لكنني رأيت رمزًا حيث يقوم المؤلف بذلك بهذه الطريقة:احصل على ال String من Integer كائن، قم بتسلسل "0" في النهاية ثم احصل عليه Integer الكائن مرة أخرى باستخدام Integer.parseInt

الكود هو شيء من هذا القبيل:

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

هل هناك أي ميزة في القيام بذلك في كلتا الحالتين؟

وما هي الطريقة الأكثر كفاءة/الأحدث بشكل عام وفي هذه الحالة؟

هل كانت مفيدة؟

المحلول

مع جافا 5 com.autoboxing, ، يمكنك ببساطة القيام بما يلي:

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

نصائح أخرى

يعد أسلوب السلسلة أمرًا مسليًا، ولكنه بالتأكيد طريقة سيئة للقيام بذلك.

سيكون الحصول على قيمة int لعدد صحيح وإنشاء قيمة جديدة أمرًا سريعًا للغاية، بينما سيكون استدعاء parseInt مكلفًا إلى حد ما.

بشكل عام، أنا أتفق مع نهجك الأصلي (والذي، كما أشار الآخرون، يمكن القيام به دون الكثير من الفوضى إذا كان لديك autoboxing كما تم تقديمه في Java 5).

المشكلة في الطريقة الثانية هي طريقة التعامل مع السلاسل النصية في Java:

  • "0" يتم تحويله إلى كائن سلسلة ثابت في وقت الترجمة.
  • في كل مرة يتم استدعاء هذا الرمز، s تم إنشاؤه ككائن سلسلة جديد، و 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 غير قابل للتغيير.

راجع للشغل، autoboxing/unboxing داخليًا هو نفس الطريقة الأولى.

ابتعد عن الطريقة الثانية، أفضل رهان هو التشغيل التلقائي إذا كنت تستخدم Java 1.5، وأي شيء أقدم عليه سيكون المثال الأول هو الأفضل.

الحل باستخدام طريقة السلسلة ليس جيدًا لعدة أسباب.بعضها أسباب جمالية والبعض الآخر عملي.

على الصعيد العملي، يتم إنشاء المزيد من الكائنات بواسطة إصدار السلسلة مقارنة بالشكل العادي (كما عبرت عن ذلك في المثال الأول).

من الناحية الجمالية، أعتقد أن الإصدار الثاني يحجب القصد من الكود وهذا لا يقل أهمية عن جعله ينتج النتيجة التي تريدها.

إجابة مجموعة الأدوات أعلاه صحيحة وأفضل طريقة، لكنها لا تعطي تفسيرا كاملا لما يحدث.بافتراض 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'.وذلك لأن "أ" يتم إخراجه من الصندوق تلقائيًا من أجل إجراء الضرب، ومن ثم يتم وضع نتيجة الضرب في صندوق تلقائيًا وتعيينها إلى "أ".

عدد صحيح هو كائن غير قابل للتغيير.(جميع فئات المجمع غير قابلة للتغيير.)

خذ على سبيل المثال هذا الجزء من الكود:

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" يتغير (ستكون عناوين الذاكرة الخاصة بك مختلفة).

الآن لنجري اختبارًا صغيرًا مع الانعكاس، وأضف هذا إلى نهاية طريقة الاختبار () :

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