128 == 128 টি মিথ্যা তবে জাভাতে পূর্ণসংখ্যার মোড়কে তুলনা করার সময় 127 == 127 সত্য?


172
class D {
    public static void main(String args[]) {
        Integer b2=128;
        Integer b3=128;
        System.out.println(b2==b3);
    }
}

আউটপুট:

false

class D {
    public static void main(String args[]) {
        Integer b2=127;
        Integer b3=127;
        System.out.println(b2==b3);
    }
}

আউটপুট:

true

দ্রষ্টব্য: -128 এবং 127 এর মধ্যে নম্বরগুলি সত্য।


10
আপনি bexhuff.com/2006/11/java-1-5-autoboxing-wackyness তথ্যপূর্ণ খুঁজে পেতে পারেন
ডমিনিক রজার

1
আপনি এই প্রশ্নটি জিজ্ঞাসা করার বিন্দুতে কিভাবে পেলেন? এটি সত্যিই মজাদার, তবে "আসল বিশ্বে" এর মতো কিছু কখনই আসে না ... বা?
মেরে ইনফিনিটাস

উত্তর:


217

আপনি যখন জাভাতে একটি সংখ্যাটি আক্ষরিক সংকলন করেন এবং সংকলকটির দ্বারা এটি একটি পূর্ণসংখ্যার (মূলধন I) নির্ধারিত হয়:

Integer b2 =Integer.valueOf(127)

আপনি অটোবক্সিং ব্যবহার করার সময় কোডের এই লাইনটিও উত্পন্ন হয়।

valueOf এমনটি কার্যকর করা হয় যে নির্দিষ্ট সংখ্যাগুলি "পুল করা" হয় এবং এটি 128 এর চেয়ে কম মানের জন্য একই উদাহরণ দেয় returns

জাভা 1.6 উত্স কোড থেকে, লাইন 621:

public static Integer valueOf(int i) {
    if(i >= -128 && i <= IntegerCache.high)
        return IntegerCache.cache[i + 128];
    else
        return new Integer(i);
}

মান highকরতে পারেন অন্য মান করার জন্য কনফিগার করা, সিস্টেম সম্পত্তি সঙ্গে।

-Djava.lang.Integer.IntegerCache.high = 999

যদি আপনি সেই সিস্টেম সম্পত্তি দিয়ে আপনার প্রোগ্রামটি চালান, তবে এটি সত্য হয়ে যাবে!

সুস্পষ্ট উপসংহার: দু'টি রেফারেন্স অভিন্ন হিসাবে কখনও নির্ভর করবেন না, সর্বদা তাদেরকে .equals()পদ্ধতির সাথে তুলনা করুন ।

সুতরাং b2.equals(b3)বি 2, বি 3 এর সমস্ত যৌক্তিক সমান মানগুলির জন্য সত্য মুদ্রণ করা হবে।

নোট করুন যে Integerকার্য সম্পাদনের কারণে ক্যাশে নেই, বরং জেএলএস অনুসারে, বিভাগ 5.1.7 ; বস্তুর পরিচয় অবশ্যই -128 থেকে 127 সহ মানের জন্য দেওয়া উচিত।

পূর্ণসংখ্যা # মানওফ (ইনট্রি) এছাড়াও এই আচরণের দলিল করে:

এই পদ্ধতিটি প্রায়শই অনুরোধ করা মানগুলিকে ক্যাশে করে উল্লেখযোগ্যভাবে আরও ভাল জায়গা এবং সময় সম্পাদন করে। এই পদ্ধতিটি সর্বদা অন্তর্ভুক্ত সহ -128 থেকে 127 সীমাতে মানগুলিকে ক্যাশে করবে এবং এই ব্যাপ্তির বাইরের অন্যান্য মানকে ক্যাশে করতে পারে।


1
নোট করুন যে 127 এর চেয়ে ছোট মানগুলি জাভা দ্বারা উপেক্ষা করা হবে এবং পূর্ণসংখ্যার চেয়ে বড় মানগুলি MA MAX_VALUE-128 কে্যাপ করা হবে।
আন্দ্রেয় পিটারসন

পূর্ণসংখ্যাগুলি জাভা 5 এবং উচ্চতর বাইট মানগুলির জন্য ক্যাশে করা হয়, নতুন পূর্ণসংখ্যা (1) == নতুন পূর্ণসংখ্যা (1) তৈরি করে। তবে জাভা ১.৪ বা তার চেয়ে কম ক্ষেত্রে এটি নয়, তাই আপনার যদি অবশেষে সেই পরিবেশে অবনতি করতে হয় তবে সাবধান হন।
MetroidFan2002

11
না, এটা ভুল। নতুন পূর্ণসংখ্যা (1) == নতুন পূর্ণসংখ্যা (1) jvm নির্বিশেষে মিথ্যা। এএএএআইএফির কোনও সংকলক "নতুন" কীওয়ার্ডটি প্রতারণা করবে না। এটি সর্বদা একটি নতুন অবজেক্ট ইনস্ট্যান্ট করা আবশ্যক।
আন্দ্রেয় পিটারসন

1
@ হোলার আকর্ষণীয় পয়েন্ট তবে প্রযুক্তিগতভাবে জেডিকে থেকে একটি পূর্ণাঙ্গ ইমপ্লের সাথে পূর্ণসংখ্যা শ্রেণিটি প্রতিস্থাপন করা সম্ভব ... (কেন কেউ সেই পাগল হবে তা জিজ্ঞাসা করবেন না) - তবে এর পার্শ্ব প্রতিক্রিয়া থাকতে পারে যা অপ্টিমাইজ করার অনুমতি নেই
অ্যান্ড্রেস পিটারসন

1
নিবন্ধন করুন "সংকলক" এর অর্থ জেআইটি সংকলক, যা প্রকৃত বাস্তবায়ন ক্লাসটি সুনির্দিষ্টভাবে জানে এবং কেবলমাত্র অনুকূলিত করতে পারে, যদি নির্মাণকারীর কোনও পার্শ্ব প্রতিক্রিয়া না থাকে। বা কেবলমাত্র পার্শ্ব প্রতিক্রিয়া পুনরুত্পাদন করতে এক্সপ্রেশনটি অনুকূল করে নিন, তারপরে ব্যবহার করুন false। প্রকৃতপক্ষে, এটি ইতিমধ্যে আজ থেকেই ঘটতে পারে, এসেসপ এনালাইসিস এবং স্কেলার রিপ্লেসমেন্ট প্রয়োগের পার্শ্ব প্রতিক্রিয়া হিসাবে।
হোলার

24

অটোবক্সিং ক্যাশে -128 থেকে 127. এটি জেএলএসে বর্ণিত ( 5.1.7 )।

বাক্সবিন্যাসের মান পি যদি সত্য, মিথ্যা, বাইট, char u0000 থেকে 00 u007f পরিসরে একটি চর বা -128 এবং 127 এর মধ্যে একটি আন্ত বা সংক্ষিপ্ত সংখ্যা হয়, তবে আর 1 এবং আর 2 কোনও দুটি বক্সিং রূপান্তরগুলির ফলাফল হতে দিন পি। এটি সর্বদা ক্ষেত্রে r1 == আর 2 হয়।

অবজেক্টগুলির সাথে ডিল করার সময় মনে রাখার একটি সহজ নিয়ম হ'ল - .equalsআপনি দুটি বস্তু "সমান" কিনা তা পরীক্ষা ==করতে চাইলে ব্যবহার করুন, আপনি যখন দেখতে চান তা ব্যবহার করুন যখন তারা একই উদাহরণটিতে নির্দেশ করেছেন কিনা।


1
দ্রষ্টব্য: জাভা 9 এ জেএলএস পরিবর্তিত হয়েছে এটি এখন কেবল সময়ের ধ্রুবক এক্সপ্রেশনগুলির জন্য গ্যারান্টিযুক্ত ; গৃহীত উত্তরের আপডেট দেখুন।
স্টিফেন সি

9

আদিম উপাত্তের প্রকারগুলি, ints ব্যবহার করে উভয় ক্ষেত্রেই প্রত্যাশিত আউটপুট সত্য হয়।

তবে, যেহেতু আপনি পূর্ণসংখ্যক অবজেক্ট ব্যবহার করছেন == অপারেটরের আলাদা অর্থ রয়েছে।

বস্তুর প্রসঙ্গে, == ভেরিয়েবলগুলি একই বস্তুর রেফারেন্সকে উল্লেখ করে কিনা তা পরীক্ষা করে দেখুন।

অবজেক্টের মান তুলনা করতে আপনার সমান () পদ্ধতিটি ব্যবহার করা উচিত

 b2.equals(b1)

যা b2 b1 এর চেয়ে কম, এর চেয়ে বড় বা সমান (বিশদটির জন্য API টি দেখুন) কিনা তা নির্দেশ করবে


7

এটি জাভা সম্পর্কিত মেমরি অপ্টিমাইজেশন।

স্মৃতিতে সঞ্চয় করতে, জাভা সমস্ত মোড়কের বস্তুগুলির 'পুনরায় ব্যবহার' যার মান নিম্নলিখিত রেঞ্জগুলিতে পড়ে:

সমস্ত বুলিয়ান মান (সত্য এবং মিথ্যা)

সমস্ত বাইট মান

সমস্ত অক্ষরের মান \ u0000 থেকে \ u007f (দশমিকের মধ্যে 0 থেকে 127)

সমস্ত সংক্ষিপ্ত এবং পূর্ণসংখ্যার মান -128 থেকে 127 পর্যন্ত।


3

Integer.java কটাক্ষপাত আছে, যদি মান -128 এবং 127 মধ্যে, এটা ক্যাশে পুল, তাই ব্যবহার করা হবে (Integer) 1 == (Integer) 1যখন(Integer) 222 != (Integer) 222

 /**
 * Returns an {@code Integer} instance representing the specified
 * {@code int} value.  If a new {@code Integer} instance is not
 * required, this method should generally be used in preference to
 * the constructor {@link #Integer(int)}, as this method is likely
 * to yield significantly better space and time performance by
 * caching frequently requested values.
 *
 * This method will always cache values in the range -128 to 127,
 * inclusive, and may cache other values outside of this range.
 *
 * @param  i an {@code int} value.
 * @return an {@code Integer} instance representing {@code i}.
 * @since  1.5
 */
public static Integer valueOf(int i) {
    assert IntegerCache.high >= 127;
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}       

0

অন্যান্য উত্তরগুলি কেন পর্যবেক্ষিত প্রভাবগুলি পর্যবেক্ষণ করা যেতে পারে তা বর্ণনা করে তবে এটি প্রোগ্রামারদের জন্য সত্যই বিন্দুর পাশে (আকর্ষণীয়, অবশ্যই, তবে আসল কোড লেখার সময় আপনার কিছু ভুলে যাওয়া উচিত)।

সাম্যের জন্য পূর্ণসংখ্যার অবজেক্টগুলির তুলনা করতে, equalsপদ্ধতিটি ব্যবহার করুন ।

পরিচয় অপারেটর ব্যবহার করে সমতার জন্য পূর্ণসংখ্যার অবজেক্টগুলির তুলনা করার চেষ্টা করবেন না ==

এটি ঘটতে পারে যে কয়েকটি সমান মান হ'ল অভিন্ন বস্তু, তবে এটি এমন কিছু নয় যা সাধারণত নির্ভর করা উচিত।


-4

আমি নিম্নলিখিতটি লিখেছি কারণ এই সমস্যাটি কেবল পূর্ণসংখ্যার সাথে নির্দিষ্ট নয়। আমার উপসংহারটি হ'ল প্রায়শই না আপনি যদি API টি ভুলভাবে ব্যবহার করেন তবে আপনি ভুল আচরণটি দেখেন। এটি সঠিকভাবে ব্যবহার করুন এবং আপনার সঠিক আচরণটি দেখা উচিত:

public static void main (String[] args) {
    Byte b1=127;
    Byte b2=127;

    Short s1=127; //incorrect should use Byte
    Short s2=127; //incorrect should use Byte
    Short s3=128;
    Short s4=128;

    Integer i1=127; //incorrect should use Byte
    Integer i2=127; //incorrect should use Byte
    Integer i3=128;
    Integer i4=128;

    Integer i5=32767; //incorrect should use Short
    Integer i6=32767; //incorrect should use Short

    Long l1=127L;           //incorrect should use Byte
    Long l2=127L;           //incorrect should use Byte
    Long l3=13267L;         //incorrect should use Short
    Long l4=32767L;         //incorrect should use Short
    Long l5=2147483647L;    //incorrect should use Integer 
    Long l6=2147483647L;    //incorrect should use Integer
    Long l7=2147483648L;
    Long l8=2147483648L;

    System.out.print(b1==b2); //true  (incorrect) Used API correctly
    System.out.print(s1==s2); //true  (incorrect) Used API incorrectly
    System.out.print(i1==i2); //true  (incorrect) Used API incorrectly
    System.out.print(l1==l2); //true  (incorrect) Used API incorrectly

    System.out.print(s3==s4); //false (correct) Used API correctly
    System.out.print(i3==i4); //false (correct) Used API correctly
    System.out.print(i5==i6); //false (correct) Used API correctly
    System.out.print(l3==l4); //false (correct) Used API correctly
    System.out.print(l7==l8); //false (correct) Used API correctly
    System.out.print(l5==l6); //false (correct) Used API incorrectly

}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.