কেন এটি নালপয়েন্টার এক্সসেপশন নিক্ষেপ করছে না?


89

নিম্নলিখিত কোডের জন্য সুস্পষ্ট ব্যাখ্যা:

StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample.append("B");
System.out.println(sample);

এটি মুদ্রণ করবে Bযাতে প্রমাণ sampleএবং referToSampleঅবজেক্ট একই মেমরি রেফারেন্স উল্লেখ করে।

StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
sample.append("A");
referToSample.append("B");
System.out.println(referToSample);

এটি মুদ্রণ করবে ABযা একই প্রমাণ করে।

StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample = null;
referToSample.append("A");
System.out.println(sample);

স্পষ্টতই এটি ফেলে দেবে NullPointerExceptionকারণ আমি appendনাল রেফারেন্সের জন্য কল করার চেষ্টা করছি ।

StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample = null;
sample.append("A");
System.out.println(sample);

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


31
sampleএখনও sample। আপনি কেবল পরিবর্তন করেছেন referToSample
ডেভ নিউটন

25
উজ্জ্বল / তারকাচিহ্নিত! খুব মৌলিক প্রশ্ন, কিন্তু এই আপনার সমস্যা ব্যাখ্যা একটি সুন্দর উদাহরণ এবং প্রশ্ন ভাল জিজ্ঞাসা করছিলেন।
রায়ান র্যানসফোর্ড

15
আপনার প্রশ্নের পরিভাষাটির একটি বিন্দু: আপনি অবজেক্ট হিসাবে উল্লেখ sampleএবং অবিরত রাখেন তবে সেগুলি বস্তু নয়, তারা ভেরিয়েবল। একটি ভেরিয়েবল কোনও বস্তুর রেফারেন্স ধরে রাখতে পারে তবে এটি নিজেই কোনও বস্তু নয়। এটি একটি সূক্ষ্ম পার্থক্য, তবে এটি মূলত আপনার বিভ্রান্তির মূল বিষয়। referToSample
ড্যানিয়েল প্রাইডেন

4
এটি কেবল পয়েন্টার হিসাবে অবজেক্ট ভেরিয়েবলগুলি ভাবতে সহায়তা করে। কোন অপারেটর যা পরিবর্তনশীল উপর কাজ করে ( volatile, final, =, ==...) একটি বস্তুর পরিবর্তনশীল প্রয়োগ যখন প্রভাবিত পয়েন্টার না বস্তুর এটা বোঝায়।
মাইকএফহে

4
@ আরপিট আমি শ্রদ্ধার সাথে একমত নই। এই প্রশ্নে একটি বৃহত্তর ধারণা লুকিয়ে আছে, এবং তা হল, কোনও বস্তুর মধ্যে পার্থক্য এবং object বস্তুর রেফারেন্স । বেশিরভাগ সময়, আমাদের এই পার্থক্য সম্পর্কে সচেতন হওয়ার প্রয়োজন নেই (বা চাই না) এবং ভাষা ডিজাইনাররা এটিকে আমাদের থেকে আড়াল করতে কঠোর পরিশ্রম করেন। উদাহরণস্বরূপ কেবল সি ++ এ পাস-বাই-রেফারেন্স যুক্তিগুলির কথা ভাবেন। সুতরাং আমার কাছে অবাক হওয়ার মতো বিষয় নয় যে সমস্ত যাদুতে বিভ্রান্ত হয়ে পড়েছে!
Gyom

উত্তর:


89

nullঅ্যাসাইনমেন্টগুলি বিশ্বব্যাপী সেই অবজেক্টটি ধ্বংস করে মান পরিবর্তন করে না । এই জাতীয় আচরণটি হার্ড-টু-ট্র্যাক বাগ এবং পাল্টা আচরণের দিকে পরিচালিত করে। তারা কেবলমাত্র সেই নির্দিষ্ট রেফারেন্সটিই ভেঙে দেয় ।

সরলতার জন্য, আসুন আমরা sample12345 ঠিকানার কথা বলি This এটি সম্ভবত ঠিকানা নয় এবং কেবল এখানে জিনিসগুলি সহজ করতে ব্যবহৃত হয়। ঠিকানাটি সাধারণত দেওয়া অদ্ভুত হেক্সাডেসিমালের সাথে উপস্থাপিত হয় Object#hashCode()তবে এটি বাস্তবায়ন নির্ভর।

StringBuilder sample = new StringBuilder(); //sample refers to 
//StringBuilder at 12345 

StringBuilder referToSample = sample; //referToSample refers to 
//the same StringBuilder at 12345 
//SEE DIAGRAM 1

referToSample = null; //referToSample NOW refers to 00000, 
//so accessing it will throw a NPE. 
//The other reference is not affected.
//SEE DIAGRAM 2

sample.append("A"); //sample STILL refers to the same StringBuilder at 12345 
System.out.println(sample);

লাইনগুলি থেকে সেই See diagramসময়ে বস্তুর ডায়াগ্রাম চিহ্নিত করা হয়েছে:

চিত্র 1:

[StringBuilder sample]    -----------------> [java.lang.StringBuilder@00012345]
                                                      ↑
[StringBuilder referToSample] ------------------------/

চিত্র 2:

[StringBuilder sample]    -----------------> [java.lang.StringBuilder@00012345]

[StringBuilder referToSample] ---->> [null pointer]

ডায়াগ্রাম 2 দেখায় যে অ্যানুল্লিং এ স্ট্রিংবিল্ডারের referToSampleরেফারেন্সটি ভঙ্গ করে না ।sample00012345

1 জিসি বিবেচনাগুলি এটিকে অবর্ণনীয় করে তোলে।


@ কমিট, যদি এটি আপনার প্রশ্নের উত্তর দেয়, দয়া করে উপরের পাঠ্যের বামদিকে ভোট তীরের নীচে টিকটি ক্লিক করুন।
রে ব্রিটন

@ রায়ব্রিটন আমি খুব পছন্দ করি যে মানুষ কীভাবে ধরে নিয়েছে যে সর্বাধিক ভোট দেওয়া উত্তরটিই সেই প্রশ্নের উত্তরটি সম্ভবত জবাব দেয়। যদিও সেই গণনা গুরুত্বপূর্ণ, এটি কেবলমাত্র মেট্রিক নয়; -1 এবং -2 উত্তরগুলি কেবলমাত্র ওপিকে সবচেয়ে বেশি সহায়তা করেছে বলেই গ্রহণ করা যেতে পারে।
ন্যানোফারাড

11
hashCode()হয় না মেমরি অ্যাড্রেস একই জিনিস
কেভিন Panko

6
সনাক্তকরণের হ্যাশকোডটি প্রথমে প্রথমে ডাকার পরে অবজেক্টের মেমরির অবস্থান থেকে নেওয়া হয়। এরপরে সেই হ্যাশকোডটি স্থির হয়ে যায় এবং স্মরণ করা হয় এমনকি মেমরি পরিচালক যদি অবজেক্টটিকে অন্য মেমরির স্থানে স্থানান্তরিত করার সিদ্ধান্ত নেন।
হলগার

4
ওভাররাইড করে এমন ক্লাসগুলি hashCodeসাধারণত এমন কোনও মান ফেরতের জন্য সংজ্ঞায়িত করে যার মেমরির ঠিকানাগুলির সাথে কোনও সম্পর্ক নেই। আমি মনে করি আপনি অবজেক্ট রেফারেন্স বনাম অবজেক্ট সম্পর্কে উল্লেখ না করে আপনার বক্তব্যটি তৈরি করতে পারেন hashCode। কীভাবে মেমরি ঠিকানা পাওয়া যায় তার সূক্ষ্ম পয়েন্টগুলি অন্য এক দিনের জন্য রেখে দেওয়া যেতে পারে।
কেভিন প্যাঙ্কো

62

প্রথমদিকে যেমনটি আপনি বলেছিলেন নীচে প্রদর্শিত হিসাবে referToSampleউল্লেখ করা sampleহয়েছে:

1. পরিস্থিতি 1:

রেফারটোসাম্পল নমুনা বোঝায়

২ পরিস্থিতি 1 (অবিরত):

রেফটোসাম্পল.অ্যাপেন্ড ("বি")

  • এখানে যেমন referToSampleউল্লেখ করা হচ্ছে sample, সুতরাং এটি আপনি লেখার সময় "বি" যুক্ত করেছেন

    referToSample.append("B")

পরিস্থিতি 2 তে একই জিনিস

তবে, ৩. পরিস্থিতি3: হেক্সাফ্রাকশন যেমন বলেছিল,

যখন আপনি নির্ধারণ nullকরতে referToSampleযখন এটি উল্লেখ ছিল sampleএটা পরিবর্তন না মান পরিবর্তে এটি শুধু ভঙ্গ রেফারেন্স থেকে sample, এবং এখন এটা পয়েন্ট কোথাও না । নিচে দেখানো হয়েছে:

রেফারোটোসাম্পল = নাল

এখন, referToSampleপয়েন্ট হিসাবে কোথাও নেই , সুতরাং আপনার referToSample.append("A");এটির কোনও মান বা রেফারেন্স থাকবে না যেখানে এটি এ যুক্ত করতে পারে তাই, এটি নিক্ষেপ করবে NullPointerException

কিন্তু sampleএখনও একই হিসাবে আপনি এটি দিয়ে সক্রিয়া করেছিলেন

StringBuilder sample = new StringBuilder(); সুতরাং এটি উদ্ভাবিত হয়েছে, এখন এটি এ সংযোজন করতে পারে, এবং নিক্ষেপ করবে না NullPointerException


4
চমৎকার চিত্র। এটি চিত্রিত করতে সহায়তা করে।
ন্যানোফারাড

সুন্দর চিত্র, তবে নীচের নোটটি হওয়া উচিত 'এখন রেফারফটসাম্পলটি "" "উল্লেখ করা হয় না কারণ আপনি যখন referToSample = sample;নমুনার কথা উল্লেখ করছেন, আপনি কেবল যা উল্লেখ করেছেন তার ঠিকানাটি অনুলিপি করছেন
খালেদ.কে.

17

সংক্ষেপে: আপনি কোনও রেফারেন্স ভেরিয়েবলকে নাল বরাদ্দ করেন, কোনও বস্তুর কাছে নয়।

একটি উদাহরণে আপনি দুটি রেফারেন্স ভেরিয়েবল দ্বারা উল্লেখ করা একটি অবজেক্টের অবস্থা পরিবর্তন করেন। যখন এটি ঘটে, উভয় রেফারেন্স ভেরিয়েবলগুলি পরিবর্তনটি প্রতিফলিত করবে।

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


সুতরাং আপনার নির্দিষ্ট "বিধি" হিসাবে:

যদি দুটি বস্তু একই বস্তুর উল্লেখ করে তবে আমরা যদি কোনও মান পরিবর্তন করি তবে তা অন্যের প্রতিও প্রতিফলিত হবে কারণ উভয়ই একই স্মৃতি রেফারেন্সের দিকে নির্দেশ করছে।

আবার, আপনি উভয় ভেরিয়েবল উল্লেখ করে যে একটি বস্তুর অবস্থা পরিবর্তন করতে উল্লেখ করুন।

তাহলে কেন সেই বিধি এখানে প্রয়োগ হচ্ছে না? যদি আমি রেফারটোসাম্পলকে নাল বরাদ্দ করি তবে নমুনাটিও নাল হওয়া উচিত এবং এটি নালপয়েন্টারএক্সেপশন নিক্ষেপ করা উচিত তবে এটি নিক্ষেপ করছে না, কেন?

আবার, আপনি একটি ভেরিয়েবলের রেফারেন্স পরিবর্তন করেন যা অন্য ভেরিয়েবলের রেফারেন্সের উপর পুরোপুরি কোনও প্রভাব ফেলে না ।

এটি দুটি সম্পূর্ণ ভিন্ন ক্রিয়া এবং এর ফলে দুটি সম্পূর্ণ ভিন্ন ফলাফল হবে।


4
@ কমিট: এটি একটি মৌলিক তবে সমালোচনা ধারণা যা জাভা সমস্তকেই অন্তর্নিহিত করে এবং এটি একবার দেখলে আপনি কখনই ভুলতে পারবেন না।
ইওলস অফ হওলক্রাফ্ট

8

এই সাধারণ চিত্রটি দেখুন:

চিত্র

আপনি যখন কোনও পদ্ধতি কল করেন referToSample, তারপরে [your object]আপডেট করা হয়, সুতরাং এটি sampleখুব বেশি প্রভাব ফেলে । তবে যখন আপনি বলবেন referToSample = null, তখন আপনি কেবল যা পরিবর্তন করছেন তা referToSample বোঝাচ্ছেন


3

এখানে 'নমুনা' এবং 'রেফারটোসাম্পল' একই বস্তুটিকে উল্লেখ করছে hat একই মেমরির অবস্থানটিতে অ্যাক্সেস করার জন্য বিভিন্ন পয়েন্টারের ধারণা। সুতরাং নালকে একটি রেফারেন্স ভেরিয়েবল নির্ধারণ করা বস্তুটিকে ধ্বংস করে না।

   referToSample = null;

মানে 'রেফারটোসাম্পল' কেবল নালার দিকে ইঙ্গিত করে, অবজেক্টটি একই থাকে এবং অন্যান্য রেফারেন্স ভেরিয়েবল ঠিকঠাক কাজ করে। সুতরাং 'নমুনা' এর জন্য যা নালার দিকে নির্দেশ করে না এবং একটি বৈধ অবজেক্ট রয়েছে

   sample.append("A");

ঠিকভাবে কাজ করে. তবে আমরা যদি 'রেফারোটো নমুনা' -তে নাল সংযোজন করার চেষ্টা করি তবে এটি নালপয়েন্টেক্সপশনটি দেখায়। এটাই,

   referToSample .append("A");-------> NullPointerException

এজন্য আপনি নিজের তৃতীয় কোড স্নিপেটে নালপয়েন্টার এক্সসেপশন পেয়েছেন।


0

যখনই কোনও নতুন কীওয়ার্ড ব্যবহৃত হয় তখন এটি হ্যাপ এ একটি অবজেক্ট তৈরি করে

1) স্ট্রিংবিল্ডার নমুনা = নতুন স্ট্রিংবিল্ডার ();

2) স্ট্রিংবিল্ডার রেফারটোসাম্পল = নমুনা;

2) রেফারসম্পেলের রেফারেন্স একই বস্তুর নমুনায় তৈরি করা হয়

এইভাবে রেফারটোসামাল = নাল; কেবলমাত্র রেফারসাম্পল রেফারেন্স নালিং করছে যে নমুনাকে কোনও প্রভাব দিচ্ছে না কেন আপনি নুল পয়েন্টার ব্যতিক্রম পাচ্ছেন না জাভা'র আবর্জনা সংগ্রহের জন্য ধন্যবাদ


0

কেবল সহজ, জাভা রেফারেন্স দ্বারা পাস না, এটি কেবল বস্তুর রেফারেন্স পাস করে।


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