জাভা: পূর্ণসংখ্যা বনাম == সমান


152

জাভা 1.5 হিসাবে, আপনি অনেক পরিস্থিতিতে অনেক Integerসঙ্গে বিনিময় করতে পারেন int

তবে আমি আমার কোডে একটি সম্ভাব্য ত্রুটি পেয়েছি যা আমাকে খানিকটা অবাক করেছে।

নিম্নলিখিত কোড:

Integer cdiCt = ...;
Integer cdsCt = ...;
...
if (cdiCt != null && cdsCt != null && cdiCt != cdsCt)
    mismatch = true;

মানগুলি সমান হয়ে গেলে ভুলভাবে অমিল স্থাপন করতে দেখা গেছে, যদিও আমি কোন পরিস্থিতিতে নির্ধারণ করতে পারি না। আমি Eclipse এ একটি ব্রেকপয়েন্ট স্থাপন করেছি এবং দেখেছি যে Integerমানগুলি 137 ছিল এবং আমি বুলিয়ান অভিব্যক্তিটি পরীক্ষা করেছিলাম এবং এটি বলেছিল যে এটি মিথ্যা ছিল, কিন্তু যখন আমি এটির উপরে পদার্পণ করেছি, তখন এটি সত্যের সাথে মিল রেখেছিল।

শর্তসাপেক্ষে পরিবর্তন করা:

if (cdiCt != null && cdsCt != null && !cdiCt.equals(cdsCt))

সমস্যা সমাধান।

কেন এমনটা হয়েছে এ সম্পর্কে কেউ কিছু আলোকপাত করতে পারেন? এখনও অবধি আমি আমার পিসিতে লোকালহোস্টে কেবল আচরণটি দেখেছি। এই বিশেষ ক্ষেত্রে, কোডটি সফলভাবে প্রায় 20 টি তুলনা করে এটি পেরেছিল, তবে 2 এ ব্যর্থ হয়েছিল consistent সমস্যাটি ধারাবাহিকভাবে পুনরুত্পাদনযোগ্য ছিল।

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

এটি এখনও ==দুটি Integerমান তুলনা করতে বৈধ নয় ?

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

সংকলক / জেভিএম কেন কেবল অটোবক্সিংকে "কেবলমাত্র কাজ" করতে পারে না?

উত্তর:


238

JVM পূর্ণসংখ্যা মানগুলি ক্যাশে করছে। == কেবলমাত্র -128 এবং 127 এর মধ্যে সংখ্যার জন্য কাজ করে http://www.owasp.org/index.php/ জাভা_গোটচস # আইটেমিটেবল_অবজেক্ট_২ এফ_আপনার_ক্লাস_চক্রিং


1
ধন্যবাদ, এটি অবশ্যই ব্যাখ্যা করে যে কেন 137 ব্যর্থ হয়! এবং এটি আমার প্রশ্নটিরও উত্তর দেয় কেন এটি কেন একটি বিরাজমান সমস্যা নয়, 95% ক্ষেত্রে আমি যে মুখোমুখি হতে চলেছি তার মান 127 এর নিচে হবে। এখন এটি ধরা ভাল যদিও 5% যেখানে এটি নেই।
জেরেমি গুডেল

1
মজাদার দিকের নোট: কয়েক সপ্তাহ আগে অবধি, সিডিসিটি এবং সিডিএসসিটি উভয় ইন্ট ছিল তাই এটি ভাল ছিল, তবে নাল পরিস্থিতি যা অন্যভাবে পরিচালিত হয় তা পরীক্ষা করার জন্য আমাকে তাদের পূর্ণসংখ্যার তৈরি করতে হয়েছিল ...
জেরেমি গুডেল

3
@ জেরেমি হ্যাঁ, এটি একটি অস্পষ্ট সমস্যা, তবে সাধারণ নিয়ম হিসাবে আপনি অবজেক্টের জন্য .equals () এবং আদিমদের জন্য == ব্যবহার করেন। সমতা পরীক্ষার জন্য আপনি স্বতঃবক্সিংয়ের উপর নির্ভর করতে পারবেন না।
অ্যাডাম

1
Lol, চেক চিহ্ন আপনি আবার ফিরে! দেখে মনে হচ্ছে কলিনের ইতিমধ্যে যাইহোক যথেষ্ট পয়েন্ট রয়েছে।
জেরেমি গুডেল

2
নোট করুন যে নতুন পূর্ণসংখ্যা (1)! = নতুন পূর্ণসংখ্যা (1) এছাড়াও। নতুন সবসময় একটি নতুন ঠিকানা ফেরত দেয়। অটোবক্সিং একটি ক্যাশেড সংস্করণ ব্যবহার করে। অন্যান্য উপায়ে যে পূর্ণসংখ্যার (তাদের নতুন করে না দিয়ে) ফিরে আসে সম্ভবত ক্যাশেড মানটিও ফিরে আসে।
বিল কে

77

আপনি দু'টি তুলনায় তুলতে পারবেন না তারা Integerসাধারণ ==বস্তু তাই বেশিরভাগ সময়সূত্রগুলি একই রকম হয় না।

একটি কৌশল আছে, Integer-128 এবং 127 এর মধ্যে উল্লেখগুলি অটোবক্সিং ব্যবহারের মতো হবে Integer.valueOf()যা ছোট পূর্ণসংখ্যাকে ক্যাশে করে।

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


সংস্থানসমূহ:

একই বিষয়ে:


1
জেএলএস থেকে গ্যারান্টিটি নাকি কেবল ওরাকল জেভিএমের জন্য?
থরবজর্ন রাভন অ্যান্ডারসন

উদ্ধৃত অংশটি জেএলএসের, সুতরাং এটি জেএলএসের একটি গ্যারান্টি
কলিন হেবার্ট

পুনঃ গ্যারান্টি আমি তখনও খুব বেশি নির্ভর করি না। new Integer(1) == new Integer(1)এখনও মিথ্যা।
থিলো

@Thilo new ... == new ...সর্বদা false
এমসি সম্রাট

2
@ থিলো সত্য, equals()বস্তুগুলির সাথে লেনদেন করার সময় সর্বদা ব্যবহার করুন । জাভা শেখার সময় এটি জানা উচিত প্রথম বিষয়গুলির মধ্যে একটি। যাইহোক, আমি অনুমান করতে পারতাম যে এর নির্মাণকারীটি Integerব্যক্তিগত ছিল, অর্থাৎ উদাহরণগুলি সর্বদা valueOf()পদ্ধতিটির মাধ্যমে তৈরি হয়েছিল । তবে আমি দেখতে পাচ্ছি যে কনস্ট্রাক্টরটি সর্বজনীন।
এমসির সম্রাট

5

সমস্যাটি হ'ল আপনার দুটি পূর্ণসংখ্যার অবজেক্টগুলি কেবল এটিই objects এগুলি মেলে না কারণ আপনি আপনার দুটি অবজেক্টের রেফারেন্সের সাথে তুলনা করছেন, এর মধ্যে মানগুলি নয়। স্পষ্টতই .equalsকোনও বস্তুর রেফারেন্স তুলনার বিপরীতে মান তুলনা সরবরাহ করতে ওভাররাইড করা হয়।


ভাল উত্তর, তবে কেন এটি কেবল 137 এর জন্য ব্যর্থ হচ্ছে তা ব্যাখ্যা করে না
জেরেমি গোডেল

4

Integerরেফারেন্সকে বোঝায়, অর্থাত্, রেফারেন্সগুলির সাথে তুলনা করার সময় আপনি তুলনা করছেন যদি তারা একই বস্তুকে দেখায়, মান না। অতএব, আপনি যে সমস্যাটি দেখছেন এটি সরল intপ্রকারের সাথে এত ভাল কাজ করার কারণটি এটি এর দ্বারা থাকা মানটিকে আনবক্স করে Integer

আমি যুক্ত করতে পারি যে আপনি যা করছেন তা যদি করেন তবে ifবিবৃতি কেন শুরু করা উচিত?

mismatch = ( cdiCt != null && cdsCt != null && !cdiCt.equals( cdsCt ) );

4

"==" সর্বদা মানগুলির মেমরি অবস্থান বা অবজেক্টের রেফারেন্সের তুলনা করুন। সমান পদ্ধতি সর্বদা মানগুলির তুলনা করে। তবে সমানও অপ্রত্যক্ষভাবে মানগুলি তুলনা করতে অপারেটরটিকে "==" অপারেটর ব্যবহার করে।

পূর্ণসংখ্যা -128 থেকে +127 পর্যন্ত মানগুলি সংরক্ষণ করতে পূর্ণসংখ্যা ক্যাশে ব্যবহার করে। যদি == অপারেটর -128 থেকে 127 এর মধ্যে কোনও মান পরীক্ষা করতে ব্যবহৃত হয় তবে এটি সত্য হয় returns এই মানগুলি বাদে এটি মিথ্যা প্রত্যাবর্তন করে।

পড়ুন লিংক কিছু অতিরিক্ত তথ্যের জন্য


0

এই প্রদত্ত দুর্দান্ত উত্তরগুলি ছাড়াও, আমি যা শিখেছি তা হ'ল:

আপনি কখনই তাদের রেফারেন্সের সাথে তুলনা করার ইচ্ছে না করলে অবজেক্টগুলিকে == এর সাথে তুলনা করুন না।


0

ব্যবহারের নির্ভুলতার জন্য ==আপনি তুলনা Integerকরার আগে তুলনামূলক মানগুলির মধ্যে একটি আনবক্স করতে পারেন ==, যেমন:

if ( firstInteger.intValue() == secondInteger ) {..

দ্বিতীয়টি অটো আনবক্স করা হবে (অবশ্যই আপনাকে nullপ্রথমে এটি পরীক্ষা করতে হবে )।

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