জাভাতে অদ্ভুত পূর্ণসংখ্যার বক্সিং


114

আমি সবেমাত্র এর সাথে কোড দেখতে পেয়েছি:

public class Scratch
{
    public static void main(String[] args)
    {
        Integer a = 1000, b = 1000;
        System.out.println(a == b);

        Integer c = 100, d = 100;
        System.out.println(c == d);
    }
}

রান করার সময়, কোডের এই ব্লকটি মুদ্রণ করবে:

false
true

আমি বুঝতে পারি কেন প্রথমটি false: কারণ দুটি বস্তু পৃথক বস্তু, তাই ==রেফারেন্সগুলির সাথে তুলনা করে। তবে আমি বুঝতে পারি না, দ্বিতীয় বিবৃতি কেন ফিরছে true? একটি পূর্ণসংখ্যার মান একটি নির্দিষ্ট পরিসরে থাকে তখন এমন কোনও অদ্ভুত অটোবক্সিং বিধি রয়েছে যা লাথি মারে? এখানে কি হচ্ছে?


1
একটি প্রতারিত মত দেখায় stackoverflow.com/questions/1514910/...

3
@ আরসি - বেশিরভাগ ধাপ নয়, তবে একই রকম পরিস্থিতি নিয়ে আলোচনা করা হয়েছে। যদিও রেফারেন্সের জন্য ধন্যবাদ।
জোয়েল

2
এটা ভয়াবহ। এই কারণেই আমি কখনই সেই পুরো আদিম এর বিন্দুটি বুঝতে পারি নি, তবে বস্তুটি কিন্তু উভয়ই, তবে স্বয়ংক্রিয়ভাবে বাক্সযুক্ত, তবে নির্ভর করে তবে আআআআআআআআআআআআআআআআআআআআআ।
njzk2

1
@ রাজিব: "অটোবক্সিং" শব্দটি কোনও কোড নয়, সুতরাং এটি এটিকে বিন্যাস করবেন না।
টম

উত্তর:


102

trueলাইন আসলে ভাষা স্পেসিফিকেশন দ্বারা নিশ্চিত করা হয়। বিভাগ 5.1.7 থেকে :

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

আলোচনাটি এগিয়ে যায়, পরামর্শ দিয়েছিল যে আপনার দ্বিতীয় লাইনের আউটপুট গ্যারান্টিযুক্ত হলেও প্রথমটি নয় (নীচে উদ্ধৃত শেষ অনুচ্ছেদটি দেখুন):

আদর্শভাবে, একটি প্রদত্ত আদিম মান পি বক্সিং করা সর্বদা একটি অভিন্ন রেফারেন্স দেয়। অনুশীলনে, বিদ্যমান বাস্তবায়ন কৌশল ব্যবহার করে এটি সম্ভবত ব্যবহার্য হবে না। উপরোক্ত বিধিগুলি একটি বাস্তববাদী সমঝোতা। উপরের চূড়ান্ত ধারাটিতে নির্দিষ্ট কিছু সাধারণ মান সর্বদা অবিচ্ছেদ্য বস্তুগুলিতে বক্স করা উচিত be প্রয়োগটি অলসভাবে বা আগ্রহের সাথে এগুলি ক্যাশে করতে পারে।

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

এটি নিশ্চিত করে যে বেশিরভাগ সাধারণ ক্ষেত্রে, বিশেষত ছোট ডিভাইসগুলিতে অযৌক্তিক পারফরম্যান্স জরিমানা আরোপ না করে আচরণটি পছন্দসই হবে। কম মেমোরি-সীমাবদ্ধ বাস্তবায়নগুলি উদাহরণস্বরূপ, সমস্ত অক্ষর এবং শর্টসকে ক্যাশে করতে পারে, সেইসাথে পূর্ণসংখ্যা এবং দীর্ঘ -32 কে - + 32 কে এর মধ্যে রয়েছে long


17
এটি লক্ষণীয়ও হতে পারে যে অটোবক্সিং আসলে valueOfবক্স ক্লাসের পদ্ধতিটি পছন্দ করার জন্য (যেমন Integer.valueOf(int)) কল্পনা করার জন্য কেবলমাত্র সিনট্যাকটিক চিনি । আকর্ষণীয় বিষয় যে জেএলএস হ'ল আনবক্সিং ডিজুগারিং - intValue()এট আল ব্যবহার করে - তবে বক্সিং ডিজুয়ারিংয়ের মতো নয় def
গুস্টাফসি

@ গুস্টাফসি Integerঅফিসিয়াল publicএপিআই এর মাধ্যমে আনবক্স করার অন্য কোনও উপায় নেই , অর্থাৎ কলিং intValue()। তবে মানটির Integerজন্য উদাহরণ পাওয়ার অন্যান্য সম্ভাব্য উপায়গুলিও রয়েছে int, উদাহরণস্বরূপ একটি সংকলক কোড তৈরি করা এবং পূর্বে তৈরি করা Integerদৃষ্টান্তগুলি পুনরায় ব্যবহার করতে পারে ।
হোলার

31
public class Scratch
{
   public static void main(String[] args)
    {
        Integer a = 1000, b = 1000;  //1
        System.out.println(a == b);

        Integer c = 100, d = 100;  //2
        System.out.println(c == d);
   }
}

আউটপুট:

false
true

হ্যাঁ প্রথম আউটপুট রেফারেন্স তুলনা জন্য উত্পাদিত হয়; 'a' এবং 'b' - এ দুটি আলাদা রেফারেন্স। পয়েন্ট 1 এ, আসলে দুটি রেফারেন্স তৈরি করা হয়েছে যা এর মতো -

Integer a = new Integer(1000);
Integer b = new Integer(1000);

দ্বিতীয় আউটপুট উত্পাদিত হয় কারণ JVMমেমরিটি সংরক্ষণের চেষ্টা করে যখন Integerএকটি পরিসরে পড়ে (-128 থেকে 127)। বিন্দু 2 এ 'd' এর জন্য পূর্ণসংখ্যার ধরণের কোনও নতুন রেফারেন্স তৈরি হয় না। পূর্ণসংখ্যার ধরণের রেফারেন্স ভেরিয়েবল 'ডি' এর জন্য একটি নতুন অবজেক্ট তৈরি করার পরিবর্তে এটি কেবল 'সি' দ্বারা রেফারেন্স করা পূর্বে নির্মিত বস্তুর সাথে নির্ধারিত হয়েছিল। এই সমস্ত দ্বারা সম্পন্ন করা হয় JVM

এই মেমরি সংরক্ষণের নিয়মগুলি কেবলমাত্র পূর্ণসংখ্যার জন্য নয়। মেমোরি সাশ্রয়ী উদ্দেশ্যে, নিম্নলিখিত র‌্যাপার বস্তুর দুটি উদাহরণ (বক্সিংয়ের মাধ্যমে তৈরি করা হয়েছে) সর্বদা == থাকবে যেখানে তাদের আদিম মানগুলি একই -

  • বুলিয়ান
  • সংবাদের একক
  • থেকে ক্যারেক্টার \ u0000 করতে\u007f (7f দশমিক মধ্যে 127 হয়)
  • -128 থেকে 127 পর্যন্ত সংক্ষিপ্ত এবং পূর্ণসংখ্যা

2
Longএছাড়াও একই পরিসীমা সঙ্গে ক্যাশে আছে Integer
এরিক ওয়াং

8

কিছু পরিসরে পূর্ণসংখ্যার অবজেক্টস (আমার মনে হয় -128 এর মাধ্যমে 127) ক্যাশে হয়ে যায় এবং পুনরায় ব্যবহৃত হয়। এই ব্যাপ্তির বাইরের সংখ্যাগুলি প্রতিবার একটি নতুন অবজেক্ট পায়।


1
এই ব্যাপ্তিটি java.lang.Integer.IntegerCache.highসম্পত্তি ব্যবহার করে বাড়ানো যেতে পারে । মজার বিষয় হচ্ছে লংয়ের কাছে সেই বিকল্প নেই।
আলেকসান্দ্র ক্রেভেটস

5

হ্যাঁ, একটি অদ্ভুত অটোবক্সিং নিয়ম রয়েছে যা মানগুলি একটি নির্দিষ্ট ব্যাপ্তিতে থাকে k আপনি যখন কোনও অবজেক্ট ভেরিয়েবলকে একটি ধ্রুবক নিযুক্ত করেন, ভাষার সংজ্ঞাতে কিছুই বলে না যে একটি নতুন অবজেক্ট তৈরি করা আবশ্যক । এটি ক্যাশে থেকে কোনও বিদ্যমান বস্তুর পুনরায় ব্যবহার করতে পারে।

প্রকৃতপক্ষে, জেভিএম সাধারণত এই উদ্দেশ্যে ছোট ইন্টিজারগুলির একটি ক্যাশে, পাশাপাশি বুলিয়ান। টিআরইউ এবং বুলিয়ান F ফ্যালসির মতো মান সংরক্ষণ করে।


4

আমার অনুমান যে জাভা ছোট ছোট পূর্ণসংখ্যার একটি ক্যাশে রাখে যা ইতিমধ্যে 'বাক্সযুক্ত' রয়েছে কারণ এগুলি খুব সাধারণ এবং এটি একটি নতুন তৈরির পরিবর্তে বিদ্যমান অবজেক্টটিকে পুনরায় ব্যবহার করতে অনেক সময় ব্যয় করে।


4

এটি একটি আকর্ষণীয় বিষয়। কার্যকর জাভা বইটিতে সর্বদা আপনার নিজের শ্রেণীর জন্য সমানকে ওভাররাইড করার পরামর্শ দেয়। এছাড়াও, জাভা শ্রেণীর দুটি বস্তুর উদাহরণের জন্য সমতা পরীক্ষা করতে সর্বদা সমান পদ্ধতিটি ব্যবহার করে।

public class Scratch
{
    public static void main(String[] args)
    {
        Integer a = 1000, b = 1000;
        System.out.println(a.equals(b));

        Integer c = 100, d = 100;
        System.out.println(c.equals(d));
    }
}

আয়:

true
true

@ জোয়েল খুব অন্যান্য বিষয়ের জন্য জিজ্ঞাসা করেছিল, পূর্ণসংখ্যার সমতা নয় বরং রানটাইম আচরণের বিষয়টি বলে।
ইলিয়া কুজনেটসভ

3

জাভাতে বক্সিং একটি পূর্ণসংখ্যার জন্য -128 এবং 127 এর মধ্যে সীমাতে কাজ করে। আপনি যখন এই ব্যাপ্তিতে নম্বর ব্যবহার করছেন আপনি এটি == অপারেটরের সাথে তুলনা করতে পারেন। সীমার বাইরে পূর্ণসংখ্যার অবজেক্টগুলির জন্য আপনাকে সমান ব্যবহার করতে হবে।


3

কোনও পূর্ণসংখ্যার রেফারেন্সের জন্য কোনও int আক্ষরিকের সরাসরি অ্যাসাইনমেন্ট হ'ল অটো-বক্সিংয়ের একটি উদাহরণ, যেখানে রূপান্তর কোডের জন্য বস্তুর মান সংকলক দ্বারা পরিচালনা করা হয় hand

তাই সংকলনের সময় সংকলক রূপান্তর Integer a = 1000, b = 1000;করে Integer a = Integer.valueOf(1000), b = Integer.valueOf(1000);

সুতরাং এটি এমন Integer.valueOf()পদ্ধতি যা প্রকৃতপক্ষে আমাদের পূর্ণসংখ্যার অবজেক্টগুলি দেয় এবং যদি আমরা Integer.valueOf()পদ্ধতির উত্স কোডটি লক্ষ্য করি তবে আমরা পরিষ্কারভাবে দেখতে পাচ্ছি পদ্ধতিটি -128 থেকে 127 (অন্তর্ভুক্ত) সীমাতে পূর্ণসংখ্যার বিষয়গুলিকে ক্যাশে করে।

/**
 *
 * 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) {
     if (i >= IntegerCache.low && i <= IntegerCache.high)
         return IntegerCache.cache[i + (-IntegerCache.low)];
     return new Integer(i);
 }

সুতরাং নতুন পূর্ণসংখ্যার অবজেক্ট তৈরি এবং ফিরে না আসার পরিবর্তে পাসটি ইন্ট আক্ষরিক -128 এর চেয়ে বেশি এবং 127 এর চেয়ে কম Integer.valueOf()হলে পদ্ধতিটি অভ্যন্তরীণ থেকে পূর্ণসংখ্যার অবজেক্টগুলি প্রদান করে IntegerCache

জাভা এই পূর্ণসংখ্যার অবজেক্টগুলিকে ক্যাশে করে কারণ দৈনিক প্রোগ্রামিংয়ে এই পরিসংখ্যানগুলির পরিসীমা প্রচুর ব্যবহৃত হয় যা পরোক্ষভাবে কিছু স্মৃতি সঞ্চয় করে memory

স্ট্যাটিক ব্লকের কারণে ক্লাস মেমরিতে লোড হয়ে যাওয়ার পরে ক্যাশে প্রথম ব্যবহারের মাধ্যমে শুরু করা হয়। ক্যাশের সর্বাধিক পরিসরটি -XX:AutoBoxCacheMaxজেভিএম বিকল্প দ্বারা নিয়ন্ত্রণ করা যায় ।

পূর্ণসংখ্যা অবজেক্টের জন্য শুধুমাত্র Integer.IntegerCache আমরা তাদের মতই এই ক্যাশে আচরণ প্রযোজ্য নয় ByteCache, ShortCache, LongCache, CharacterCacheজন্য Byte, Short, Long, Characterযথাক্রমে।

আপনি আমার নিবন্ধ জাভা ইন্টিজার ক্যাশে আরও পড়তে পারেন - কেন পূর্ণসংখ্যা.ভালিউওফ (127) == পূর্ণসংখ্যা.ভালিউঅফ (127) সত্য


0

জাভা 5-এ, পূর্ণসংখ্যার ধরণের অবজেক্ট হ্যান্ডলিংয়ের স্মৃতিশক্তি বাঁচাতে এবং কর্মক্ষমতা উন্নত করার জন্য একটি নতুন বৈশিষ্ট্য চালু করা হয়েছিল। পূর্ণসংখ্যার অবজেক্টগুলি অভ্যন্তরীণভাবে ক্যাশে হয় এবং একই রেফারেন্সযুক্ত বস্তুর মাধ্যমে পুনরায় ব্যবহৃত হয়।

  1. এটি –127 থেকে +127 (সর্বাধিক পূর্ণসংখ্যার মান) এর মধ্যে পরিসরের পূর্ণসংখ্যার মানগুলির জন্য প্রযোজ্য।

  2. এই পূর্ণসংখ্যার ক্যাচিংটি কেবল অটোবক্সিংয়ে কাজ করে। পূর্ণসংখ্যার অবজেক্টগুলি কনস্ট্রাক্টর ব্যবহার করে নির্মিত হলে ক্যাশে হবে না।

আরও তথ্যের জন্য দয়া করে নীচের লিঙ্কটি দিয়ে যান:

বিশদে পূর্ণসংখ্যার ক্যাশে


0

যদি আমরা Integerঅবজেক্টের উত্স কোডটি পরীক্ষা করে দেখি তবে আমরা valueOfপদ্ধতির উত্সটি ঠিক এর মতোই পেয়ে যাব :

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

যা অটোবক্সিংয়ের সময় Integer-128 ( Integer.low) থেকে 127 ( Integer.high) অবধি যে অবজেক্টগুলি একই রেফারেন্সড অবজেক্টগুলি তা ব্যাখ্যা করতে পারে । এবং আমরা দেখতে পাচ্ছি এখানে একটি শ্রেণি ক্যাশে অ্যারের IntegerCacheযত্ন নেয় Integer, যা শ্রেণীর একটি ব্যক্তিগত স্ট্যাটিক অভ্যন্তর Integerশ্রেণি।

আরও একটি আকর্ষণীয় উদাহরণ রয়েছে যা আমাদের এই অদ্ভুত পরিস্থিতিটি বুঝতে সাহায্য করতে পারে:

public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {

      Class cache = Integer.class.getDeclaredClasses()[0]; 
      Field myCache = cache.getDeclaredField("cache"); 
      myCache.setAccessible(true);

      Integer[] newCache = (Integer[]) myCache.get(cache); 
      newCache[132] = newCache[133]; 

      Integer a = 2;
      Integer b = a + a;
      System.out.printf("%d + %d = %d", a, a, b); //The output is: 2 + 2 = 5    

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