কেন == পূর্ণসংখ্যার সাথে তুলনা করুন? মূল্য (স্ট্রিং) 127 এবং 128 এর জন্য আলাদা ফলাফল দেয়?


182

এই কোডগুলির লাইনগুলি বিভিন্ন মানটি কেন দেয় তা আমার কোনও ধারণা নেই:

System.out.println(Integer.valueOf("127")==Integer.valueOf("127"));
System.out.println(Integer.valueOf("128")==Integer.valueOf("128"));
System.out.println(Integer.parseInt("128")==Integer.valueOf("128"));

আউটপুটটি হ'ল:

true
false
true

প্রথমটি কেন trueআবার দ্বিতীয়টি ফিরে আসে false? এর মধ্যে কি আলাদা কিছু আছে যা আমি 127এবং এর মধ্যে জানি না 128? (অবশ্যই আমি জানি 127< 128।)

এছাড়াও, তৃতীয়টি কেন ফিরে আসে true?

আমি এই প্রশ্নের উত্তর পড়েছি , তবে এখনও এটি কীভাবে ফিরে আসতে পারে trueএবং দ্বিতীয় লাইনের কোড কেন দেয় তা আমি পাইনি false


6
পূর্ণসংখ্যা একটি বস্তু; আপনি যদি সাম্যের জন্য তুলনা করতে চান, ব্যবহার করুন .equals(), অন্যথায় সমস্ত বেট বন্ধ আছে।
কার্ল ডামগার্ড অসমুসেন

6
@ কার্লড্যামগার্ডএসমুসেন আসলে এখানে আমি সত্যই পরীক্ষা করতে চাই তারা যদি একই বস্তুর উল্লেখ হয় তবে প্রথমে আমি তা পাই না কেন 127 128 বিভিন্ন ফলাফল ফিরে আসে।
DnR

@ ডিএনআর যদি জাভা কোনও মানসম্মত স্পেসিফিকেশন সম্বলিত ভাষা হত তবে আমি মনে করব যে এটি এ জাতীয় বাস্তবায়ন বা এমনকি নির্ধারিত অপরিজ্ঞাত আচরণের অবধি এই বিষয়গুলিকে ছেড়ে দেয়।
কার্ল ডামগার্ড অসমুসেন

1
@ জাজম্মসকি: এই ক্যাশিং অংশ ছাড়াও এই প্রশ্নটির আরও অনেক কিছু রয়েছে । তদ্ব্যতীত, লিঙ্কযুক্ত উত্তরটি সর্বোপরি অসম্পূর্ণ - এটি কীভাবে ক্যাশ হয়েছে এবং কেন তা বিশদভাবে যায় না।
মাকোটো

1
এই আলোচনায় আরও অনুসরণের জন্য, দয়া করে এই মেটা পোস্টটি পড়ুন ।
জেরোইন ভেনেভেল

উত্তর:


191

এখানে একটি উল্লেখযোগ্য পার্থক্য আছে।

valueOfকোনও Integerবস্তুটি ফিরিয়ে দিচ্ছে, যার মান -128 এবং 127 এর মধ্যে ক্যাশ হয়ে থাকতে পারে This এই কারণেই প্রথম মানটি প্রদান করে true- এটি ক্যাশেড - এবং দ্বিতীয় মান ফেরত দেয় false- 128 কোনও ক্যাশেড মান নয়, সুতরাং আপনি দুটি পৃথক Integerদৃষ্টান্ত পাচ্ছেন ।

এটি লক্ষ করা গুরুত্বপূর্ণ যে আপনি রেফারেন্সগুলির সাথে তুলনা করছেন Integer#valueOf, এবং আপনি যদি ক্যাশে সমর্থন করে তার চেয়ে বড় যে কোনও মানের সাথে তুলনা করছেন , পার্স করা মান সমান (এমনকি পয়েন্টে ক্ষেত্রে )) এটি মূল্যায়ন করবে না । পরিবর্তে আপনার অবশ্যই ব্যবহার করা উচিতtrueInteger.valueOf(128) == Integer.valueOf(128)equals()

parseIntএকটি আদিম ফিরে আসছে int। এই কারণেই তৃতীয় মান ফেরত দেয় true- 128 == 128মূল্যায়ন করা হয় এবং অবশ্যই হয় true,।

এখন, তৃতীয় ফলাফলটি করার জন্য মোটামুটি কিছু ঘটে true:

  • আপনি যে সমতুল্য অপারেটরটি ব্যবহার করছেন এবং আপনার যে ডেটাটাইপগুলি রয়েছে - যেমন, intএবং একটি আনবক্সিং রূপান্তর ঘটেInteger । আপনি অবশ্যই ডান হাত Integerথেকে একটি পেয়ে যাচ্ছেন valueOf

  • রূপান্তর হওয়ার পরে, আপনি দুটি আদিম intমানের তুলনা করছেন । তুলনা আপনি, প্রিমিটিভের থেকে সম্মান সঙ্গে তা মানবে যাতে আপনি তুলনা গুটান হবে ঠিক যেমন ঘটে 128এবং 128


2
@ user3152527 আছে: একটি বৃহদাকার পার্থক্য - একটি একটি বস্তুর, যার মানে আপনি বিমূর্ত ডাটা স্ট্রাকচার এটা সাথে ইন্টারঅ্যাক্ট পদ্ধতি কল করতে পারেন এবং, মত বিবেচনা করা হয় List। অন্যটি একটি আদিম, যা কেবল একটি কাঁচা মূল্য।
মাকোটো

1
@ ব্যবহারকারী3152527 আপনি একটি দুর্দান্ত প্রশ্ন জিজ্ঞাসা করেছেন (এবং সবচেয়ে খারাপ কোনও বোবাও নয়)। তবে আপনি এটি .calals ব্যবহারের জন্য স্থির করেছেন, তাই না?
ব্যবহারকারী 2910265

3
আহ, এটি উপস্থিত হয় যা জাভাতে অন্তর্নিহিত সত্যটি প্রশ্নকারক বুঝতে পারেন নি: দুটি বস্তুর তুলনা করতে "==" ব্যবহার করার সময়, আপনি যদি পরীক্ষা করছেন যে তারা যদি একই বস্তুর সাথে সম্পর্কিত হয় তবে। "সমান ()" ব্যবহার করার সময়, আপনি যদি তাদের মান একই হয় কিনা তা পরীক্ষা করছেন। আদিমদের তুলনা করতে আপনি "সমান" ব্যবহার করতে পারবেন না।
জে

3
@ জায়ে না, আমি এটি বুঝতে পারি। তবে প্রথম যেটি আমাকে প্রথমে বিভ্রান্ত করে, সে কারণেই প্রথমটি সত্য এবং দ্বিতীয়টি একই তুলনা পদ্ধতিটি ব্যবহার করে মিথ্যা প্রত্যাবর্তন করে ==। যাইহোক, এখন এটি পরিষ্কার।
DnR

1
নীট: এটি কেবলমাত্র নয় যে -128 এবং 127 এর মধ্যে পূর্ণসংখ্যার "ক্যাচ" করা যেতে পারে J জেএলএস 5.1.7 অনুসারে এটি হওয়া আবশ্যক । এটি এই ব্যাপ্তির বাইরে ক্যাশে করা হতে পারে তবে এটি হতে হবে না (এবং প্রায়শই হয় না)।
ysavit

127

Integerবর্গ যে দোকানে 256 বিশেষ একটি স্ট্যাটিক ক্যাশে আছে, Integerমনের মধ্যে -128 এবং 127 যে সঙ্গে মাঝে প্রত্যেক মানের জন্য এক, এই তিনটি মধ্যে পার্থক্য বিবেচনা - বস্তু।

new Integer(123);

এটি (স্পষ্টতই) একেবারে নতুন Integerঅবজেক্ট তৈরি করে।

Integer.parseInt("123");

intপার্স করার পরে এটি একটি আদিম মান দেয় String

Integer.valueOf("123");

এটি অন্যদের চেয়ে জটিল। এটি পার্স করে শুরু হয় String। তারপরে, মানটি -128 এবং 127 এর মধ্যে হয় তবে এটি স্থিতি ক্যাশে থেকে সংশ্লিষ্ট বস্তুটি প্রদান করে। মানটি যদি এই ব্যাপ্তির বাইরে থাকে, তবে এটি new Integer()মানটিকে অনুরোধ করে এবং পাস করে, যাতে আপনি একটি নতুন অবজেক্ট পান।

এখন, প্রশ্নের তিনটি ভাবটি বিবেচনা করুন।

Integer.valueOf("127")==Integer.valueOf("127");

এটি সত্য প্রত্যাবর্তন করে, কারণ Integerযার মান 127 স্ট্যাটিক ক্যাশে থেকে দু'বার পুনরুদ্ধার করা হয়েছে এবং নিজের তুলনায়। কেবলমাত্র একটি Integerজিনিস জড়িত রয়েছে, তাই এটি ফিরে আসে true

Integer.valueOf("128")==Integer.valueOf("128");

এটি ফিরে আসে false, কারণ 128 স্থির ক্যাশে নেই। সুতরাং Integerসাম্যের প্রতিটি পক্ষের জন্য একটি নতুন তৈরি করা হয়। যেহেতু দুটি পৃথক পৃথক Integerবস্তু রয়েছে এবং উভয় পক্ষই হুবহু একই ==বস্তু হিসাবে কেবল অবজেক্টের জন্য ফেরত দেয় true, এটি হতে চলেছে false

Integer.parseInt("128")==Integer.valueOf("128");

এটি ডানদিকে intএকটি নতুন নির্মিত Integerবস্তুর সাথে বামদিকে আদিম মান 128 এর সাথে তুলনা করছে । কিন্তু কারণ এটি একটি তুলনা করতে অর্থে দেখা যায় না intএকটি থেকে Integer, জাভা স্বয়ংক্রিয় unbox হবে Integerতুলনা করছেন আগে; সুতরাং আপনি একটি intসঙ্গে একটি তুলনা শেষ int। যেহেতু আদিম 128 নিজের সমান, তাই এটি ফিরে আসে true


13

এই পদ্ধতিগুলি থেকে মূল্য ফিরিয়ে আনার যত্ন নিন। ValueOf পদ্ধতি ফেরৎ একটি পূর্ণসংখ্যা উদাহরণস্বরূপ:

public static Integer valueOf(int i)

ParseInt পূর্ণসংখ্যা মান (আদিম টাইপ) মেথড আয়:

public static int parseInt(String s) throws NumberFormatException

তুলনার জন্য ব্যাখ্যা:

স্মৃতি সংরক্ষণ করার জন্য, মোড়কের দুটি বস্তুর দুটি উদাহরণ সর্বদা == যখন তাদের আদিম মান একই থাকে:

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

যখন == একটি মোড়কের সাথে কোনও আদিম তুলনা করতে ব্যবহৃত হয়, তখন মোড়কটি মোড়ানো হবে এবং তুলনা আদিম থেকে আদিম হবে।

আপনার পরিস্থিতিতে (উপরের বিধি অনুসারে):

Integer.valueOf("127")==Integer.valueOf("127")

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

Integer.valueOf("128")==Integer.valueOf("128")

এই অভিব্যক্তিটি বিভিন্ন অবজেক্টের সাথে রেফারেন্সগুলির তুলনা করে কারণ সেগুলিতে <-128, 127> তে পূর্ণসংখ্যার মান নেই তাই এটি ফিরে আসে false

Integer.parseInt("128")==Integer.valueOf("128")

এই অভিব্যক্তিটি আদিম মানের (বাম হাতের দিকের) সাথে তুলনা করে এবং বস্তুর (ডান হাতের দিকের) রেফারেন্সকে তুলনা করে যাতে ডান হাতের অংশটি আবদ্ধ হবে এবং তার আদিম ধরণটি বামের সাথে তুলনা করা হবে যাতে এটি ফিরে আসে true


3
একই প্রশ্ন: stackoverflow.com/questions/9824053/...
piobab

আপনি কি উদ্ধৃতি উত্সের জন্য একটি URL সরবরাহ করতে পারেন?
ফিলজেন

"... মোড়কের বস্তুর দুটি উদাহরণ, সর্বদা == যখন তাদের আদিম মান একই হয় ..." - একেবারে মিথ্যা। আপনি যদি একই মান সহ দুটি মোড়কের বস্তু তৈরি করেন তবে তুলনা করার সময় সেগুলি সত্য হবে না ==কারণ তারা পৃথক বস্তু।
দাউদ ইবনে কেরেম

6

পূর্ণসংখ্যার 256 পূর্ণসংখ্যার -128 এবং 127 এর মধ্যে ক্যাশে অবজেক্ট

আপনার অবজেক্টের রেফারেন্সগুলি == বা ! = এর সাথে তুলনা করা উচিত নয় । আপনার ব্যবহার করা উচিত। পরিবর্তে সমান (..) , বা আরও ভাল - পূর্ণসংখ্যার চেয়ে আদিম অভ্যন্তর ব্যবহার করুন।

parseInt : একটি স্বাক্ষরিত দশমিক পূর্ণসংখ্য হিসাবে স্ট্রিং আর্গুমেন্টটিকে পার্স করে। স্ট্রিংয়ের অক্ষরগুলি অবশ্যই দশমিক অঙ্কের হতে হবে, কেবলমাত্র প্রথম অক্ষরটি একটি এএসসিআইআই বিয়োগ চিহ্ন '-' ('' u002D ') হতে পারে একটি নেতিবাচক মান নির্দেশ করতে। ফলস্বরূপ পূর্ণসংখ্যার মানটি প্রত্যাবর্তন করা হয় ঠিক যেমন পার্সেন্ট (java.lang.String, int) পদ্ধতিতে আর্গুমেন্ট এবং 10 মূলাঙ্গটি আর্গুমেন্ট হিসাবে দেওয়া হয়েছিল।

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

সমতুল্য

new Integer(Integer.parseInt(s, radix))

রেডিক্স - এর অর্থ ব্যাখ্যা করতে ব্যবহৃত Radix

সুতরাং আপনি যদি অভ্যন্তরের Integer.valueOf()মধ্যবর্তী সংখ্যার জন্য সমান হন

-128 থেকে 127 এটি আপনার অবস্থাতে সত্য ফিরে আসে

জন্য lesser than-128 এবং greater than127 এটা দেয়false


6

প্রদত্ত উত্তরগুলির পরিপূরক করতে নিম্নলিখিত নোটগুলিও নোট করুন:

public class Test { 
    public static void main(String... args) { 
        Integer a = new Integer(129);
        Integer b = new Integer(129);
        System.out.println(a == b);
    }
}

এই কোডটিও মুদ্রণ করবে: false

ব্যবহারকারী জে যেমন গ্রহণযোগ্য উত্তরের জন্য একটি মন্তব্যে দাবি করেছেন ==, অবজেক্টগুলিতে অপারেটর ব্যবহার করার সময় অবশ্যই যত্ন নেওয়া উচিত , এখানে আপনি উভয়ই রেফারেন্স একই রকম কিনা তা যাচাই করে দেখছেন, যদিও এগুলি ভিন্ন ভিন্ন আপত্তিদাতা, যদিও তারা খুব প্রতিনিধিত্ব করে একই মান। বস্তুর তুলনা করতে, equals পরিবর্তে আপনার পদ্ধতিটি ব্যবহার করা উচিত :

Integer a = new Integer(128);
Integer b = new Integer(128);
System.out.println(a.equals(b));

এটি মুদ্রণ করবে: true

আপনি জিজ্ঞাসা করতে পারেন, তবে তারপরে কেন প্রথম লাইনটি মুদ্রিত true? Integer.valueOfপদ্ধতির উত্স কোডটি পরীক্ষা করা , আপনি নিম্নলিখিতটি দেখতে পারেন:

public static Integer valueOf(String s) throws NumberFormatException {
    return Integer.valueOf(parseInt(s, 10));
}

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);
}

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

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