বুলিয়ান.ভালিউওফ () কখনও কখনও নুলপয়েন্টার এক্সসেপশন উত্পাদন করে


115

আমার এই কোডটি রয়েছে:

package tests;

import java.util.Hashtable;

public class Tests {

    public static void main(String[] args) {

        Hashtable<String, Boolean> modifiedItems = new Hashtable<String, Boolean>();

        System.out.println("TEST 1");
        System.out.println(modifiedItems.get("item1")); // Prints null
        System.out.println("TEST 2");
        System.out.println(modifiedItems.get("item1") == null); // Prints true
        System.out.println("TEST 3");
        System.out.println(Boolean.valueOf(null)); // Prints false
        System.out.println("TEST 4");
        System.out.println(Boolean.valueOf(modifiedItems.get("item1"))); // Produces NullPointerException
        System.out.println("FINISHED!"); // Never executed
    }
}

আমার সমস্যাটি হ'ল আমি বুঝতে পারি না কেন টেস্ট 3 ঠিকঠাক কাজ করে (এটি মুদ্রণ করে falseএবং উত্পাদন করে না NullPointerException) এর মধ্যে টেস্ট 4 নিক্ষেপ করে NullPointerException। আপনি পরীক্ষায় দেখতে পারেন 1 এবং 2 , nullএবং modifiedItems.get("item1")সমান এবং হয় null

আচরণটি জাভা 7 এবং 8 এ একই রকম।


পরিবর্তিত আইটেম.জেট ("আইটেম 1") এটি নাল, আপনি এটি সম্পর্কে অবগত আছেন, তবে আপনি কি ধরে নিয়েছেন যে এটি কোনও মান থেকে পাস করলে কোনও এনপিই শেষ হবে না?
Stultuske

16
@ স্টলটাস্ক: এটি একটি বৈধ প্রশ্ন, প্রদত্ত উপরের মাত্র দুটি লাইন nullএকই ফাংশনটিতে আক্ষরিক পাস করার ফলে এনপিই তৈরি হয় না ! এটির জন্য একটি ভাল কারণ আছে, তবে এটি অবশ্যই প্রথম দর্শনে বিভ্রান্তিকর :-)
স্মরণিকা

25
আমি অভিভূত. আমি বছরের পর বছরগুলিতে এটি সবচেয়ে আকর্ষণীয় নাল পয়েন্টার ব্যতিক্রম প্রশ্ন।
candied_orange 21

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

উত্তর:


178

কোন ওভারলোডটি চাওয়া হচ্ছে তা সাবধানতার সাথে দেখতে হবে:

  • Boolean.valueOf(null)প্রার্থনা করছে Boolean.valueOf(String)NPEনাল প্যারামিটার সরবরাহ করা হলেও এটি একটি ছুঁড়ে না ।
  • Boolean.valueOf(modifiedItems.get("item1"))অনুরোধ করছে Boolean.valueOf(boolean), কারণ modifiedItemsএর মানগুলি ধরণের Boolean, যার জন্য একটি আনবক্সিং রূপান্তর প্রয়োজন। যেহেতু modifiedItems.get("item1")হয় null, এটা যে মূল্য আনবক্সিং হয় - না Boolean.valueOf(...)- যা NPE ছোঁড়ার।

কোন ওভারলোডটি আহ্বান করা হয়েছে তা নির্ধারণের নিয়মগুলি বেশ লোমশ , তবে সেগুলি মোটামুটি এভাবে চলে:

  • প্রথম পাসে, একটি পদ্ধতি ম্যাচ বক্সিং / আনবক্সিং (বা ভেরিয়েবল আর্টির পদ্ধতিগুলি) না দিয়ে অনুসন্ধান করা হয়।

    • কারণ nullএকটি জন্য একটি গ্রহণযোগ্য মান Stringকিন্তু boolean, Boolean.valueOf(null)সাথে মানানসই হয় Boolean.valueOf(String)এই পাস হয়;
    • Booleanপারেন একটি গ্রহণযোগ্য নয় Boolean.valueOf(String)বা Boolean.valueOf(boolean)কোন পদ্ধতির জন্য এই পাস মিলেছে তাই Boolean.valueOf(modifiedItems.get("item1"))
  • দ্বিতীয় পাসে, একটি পদ্ধতি ম্যাচ সন্ধান করা হয়, বক্সিং / আনবক্সিংকে অনুমতি দেয় (তবে এখনও ভেরিয়েবল আরটি পদ্ধতি নয়)।

    • একজন Booleanথেকে unboxed হতে পারে boolean, তাই Boolean.valueOf(boolean)জন্য মেলানো হয় Boolean.valueOf(modifiedItems.get("item1"))এই পাস হয়; তবে একটি অনুরোধ করার জন্য সংকলক দ্বারা একটি আনবক্সিং রূপান্তর sertedোকাতে হবে:Boolean.valueOf(modifiedItems.get("item1").booleanValue())
  • (এখানে তৃতীয় পাসটি ভেরিয়েবল আরটি পদ্ধতিগুলির জন্য অনুমতি দেয় তবে এটি এখানে প্রাসঙ্গিক নয়, কারণ প্রথম দুটি পাস এই ক্ষেত্রে মিলেছে)


3
Boolean.valueOf(modifiedItems.get("item1").booleanValue())কোডের পরিবর্তে যদি আমরা সোর্স কোড ব্যবহার করি তবে আরও স্পষ্ট হতে পারে Boolean.valueOf(modifiedItems.get("item1"))?
সপ্তাহে where

1
@ কেজিং আন্ডারফ্লোস যে কোনও জায়গায় সত্যই নয় - .booleanValue()অভিব্যক্তিটির মধ্যে এটি কবর দেওয়া সত্যিই কঠিন । দুটি পর্যবেক্ষণ: 1) অটো (আন) বক্সিং সিনট্যাকটিক ক্রাফট অপসারণ করার জন্য জাভাটির একটি ইচ্ছাকৃত বৈশিষ্ট্য; এটি নিজেই করা সম্ভব, তবে মূর্তিমান নয়; 2) এটি আপনাকে মোটেও সহায়তা করে না - সমস্যাটি হওয়া থেকে এটি অবশ্যই থামায় না, বা ব্যর্থতা দেখা দিলে এটি কোনও অতিরিক্ত তথ্য দেয় না (স্ট্যাক ট্রেসটি অভিন্ন হবে, কারণ মৃত্যুদন্ড কার্যকর কোডটি অভিন্ন)।
অ্যান্ডি টার্নার

@ কেজিংউন্ডারফ্লোস যেখানেই এই সমস্যাগুলি হাইলাইট করার জন্য টুলিং ব্যবহার করা ভাল, উদাহরণস্বরূপ ইন্টেলিজ আপনাকে এখানে সম্ভাব্য এনপিই সম্পর্কে উপার্জন করতে পারে।
অ্যান্ডি টার্নার 13

13

যেহেতু modifiedItems.getআয় একটি Boolean(যা না একটি থেকে castable String), স্বাক্ষর ব্যবহার করা হবে যে Boolean.valueOf(boolean), যেখানে Booleanএকটি আদিম থেকে outboxed হয় boolean। একবার nullসেখানে ফিরে গেলে আউটবক্সিং a এর সাথে ব্যর্থ হয় NullPointerException


11

পদ্ধতির স্বাক্ষর

পদ্ধতিতে Boolean.valueOf(...)দুটি স্বাক্ষর রয়েছে:

  1. public static Boolean valueOf(boolean b)
  2. public static Boolean valueOf(String s)

আপনার modifiedItemsমান Boolean। আপনি কাস্ট Booleanকরতে পারবেন না Stringফলস্বরূপ প্রথম স্বাক্ষরটি বেছে নেওয়া হবে

বুলিয়ান আনবক্সিং

আপনার বিবৃতিতে

Boolean.valueOf(modifiedItems.get("item1"))

যা হিসাবে পড়া যেতে পারে

Boolean.valueOf(modifiedItems.get("item1").booleanValue())   

যাইহোক, modifiedItems.get("item1")রিটার্ন nullযাতে আপনি মূলত পাবেন

null.booleanValue()

যা স্পষ্টতই একটি বাড়ে NullPointerException


ভুল শব্দবন্ধ, নির্দেশ এবং উত্তর দেওয়ার জন্য ধন্যবাদ আপনার প্রতিক্রিয়া অনুসরণ করে আপডেট করা হয়েছে। দুঃখিত, লেখার সময় আমি আপনার উত্তরটি দেখতে পাইনি এবং আমি দেখতে পেয়েছি যে আমার মতো আপনার মত দেখাচ্ছে। ওপির জন্য বিভ্রান্তি এড়াতে কি আমার উত্তর সরিয়ে নেওয়া উচিত?
আল-আন

4
এটি আমার অ্যাকাউন্টে মুছবেন না। মনে রাখবেন, এটি একটি শূন্য-সমষ্টি গেম নয়: লোকেরা একাধিক উত্তরকে উজ্জীবিত করতে পারে (এবং করতে পারে)।
অ্যান্ডি টার্নার

3

অ্যান্ডি ইতিমধ্যে খুব ভাল কারণটির বর্ণনা দিয়েছিল NullPointerException:

যা বুলিয়ান আন-বক্সিংয়ের কারণে:

Boolean.valueOf(modifiedItems.get("item1"))

রূপান্তর করা:

Boolean.valueOf(modifiedItems.get("item1").booleanValue())

রানটাইম এ এবং তারপরে নাল NullPointerExceptionহলে এটি নিক্ষেপ করে modifiedItems.get("item1")

এখন আমি এখানে আরও একটি বিষয় যুক্ত করতে চাই যে নীচের শ্রেণীর অন-বক্সিংটি তাদের নিজ নিজ আদিমদের সাথে অপ্রকাশিত হতে পারে NullPointerExceptionযদি তাদের সংশ্লিষ্ট ফেরত বস্তুগুলি শূন্য থাকে।

  1. বাইট - বাইট
  2. চর - চরিত্র
  3. ভাসা - ভাসা
  4. int - পূর্ণসংখ্যা
  5. দীর্ঘ দীর্ঘ
  6. সংক্ষিপ্ত - সংক্ষিপ্ত
  7. ডাবল - ডাবল

কোডটি এখানে:

    Hashtable<String, Boolean> modifiedItems1 = new Hashtable<String, Boolean>();
    System.out.println(Boolean.valueOf(modifiedItems1.get("item1")));//Exception in thread "main" java.lang.NullPointerException

    Hashtable<String, Byte> modifiedItems2 = new Hashtable<String, Byte>();
    System.out.println(Byte.valueOf(modifiedItems2.get("item1")));//Exception in thread "main" java.lang.NullPointerException

    Hashtable<String, Character> modifiedItems3 = new Hashtable<String, Character>();
    System.out.println(Character.valueOf(modifiedItems3.get("item1")));//Exception in thread "main" java.lang.NullPointerException

    Hashtable<String, Float> modifiedItems4 = new Hashtable<String, Float>();
    System.out.println(Float.valueOf(modifiedItems4.get("item1")));//Exception in thread "main" java.lang.NullPointerException

    Hashtable<String, Integer> modifiedItems5 = new Hashtable<String, Integer>();
    System.out.println(Integer.valueOf(modifiedItems5.get("item1")));//Exception in thread "main" java.lang.NullPointerException

    Hashtable<String, Long> modifiedItems6 = new Hashtable<String, Long>();
    System.out.println(Long.valueOf(modifiedItems6.get("item1")));//Exception in thread "main" java.lang.NullPointerException

    Hashtable<String, Short> modifiedItems7 = new Hashtable<String, Short>();
    System.out.println(Short.valueOf(modifiedItems7.get("item1")));//Exception in thread "main" java.lang.NullPointerException

    Hashtable<String, Double> modifiedItems8 = new Hashtable<String, Double>();
    System.out.println(Double.valueOf(modifiedItems8.get("item1")));//Exception in thread "main" java.lang.NullPointerException

1
"রানটাইমে ... এ রূপান্তরিত হয়েছে" এটি সংকলনের সময় রূপান্তরিত হয়েছে।
অ্যান্ডি টার্নার

0

এটি বোঝার একটি উপায় হ'ল যখন Boolean.valueOf(null)আহ্বান করা হয়, জাভা হ'ল শূন্যের মূল্যায়নের জন্য বলা হয়।

যাইহোক, যখন Boolean.valueOf(modifiedItems.get("item1"))আহ্বান করা হয় তখন জাভাটিকে বুলিয়ান অবজেক্ট টাইপের হ্যাশ টেবিলের কাছ থেকে একটি মান পেতে বলা হয়, তবে এটি বুলিয়ান প্রত্যাশিত সত্ত্বেও এটি বুলিয়ান টাইপটি খুঁজে পায় না এটি পরিবর্তে একটি মৃত প্রান্ত খুঁজে পায় (নাল)। নালপয়েন্টারএক্সেপশন ব্যতিক্রম ছুঁড়ে দেওয়া হয়েছে কারণ জাভা এই অংশটির নির্মাতারা সিদ্ধান্ত নিয়েছিলেন যে এই পরিস্থিতিটি প্রোগ্রামের এমন কোনও কিছু ভুল হওয়ার একটি উদাহরণ যা প্রোগ্রামারের মনোযোগের প্রয়োজন। (অনিচ্ছাকৃত কিছু ঘটেছে))

এক্ষেত্রে ইচ্ছাকৃতভাবে ঘোষণার মাধ্যমে আপনি নালকে সেখানে রেখেছিলেন এবং জাভা যে কোনও অবজেক্টের (নাল) কোনও অনুপস্থিত রেফারেন্স খুঁজে পাচ্ছেন যেখানে কোনও বস্তু সন্ধান করার উদ্দেশ্যে করা হয়েছিল তার মধ্যে আরও পার্থক্য is

এই উত্তরে নালপয়েন্টার ধারণা সম্পর্কে আরও তথ্য দেখুন: https://stackoverflow.com/a/25721181/4425643


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