কেন কেউ অবজেক্টস.রেইওয়্যারননল () ব্যবহার করা উচিত?


213

আমি লক্ষ করেছি যে ওরাকল জেডিকে-তে অনেক জাভা 8 পদ্ধতি ব্যবহার করে Objects.requireNonNull(), যা NullPointerExceptionপ্রদত্ত বস্তু (যুক্তি) হলে অভ্যন্তরীণভাবে ছোঁড়ে null

public static <T> T requireNonNull(T obj) {
    if (obj == null)
        throw new NullPointerException();
    return obj;
}

তবে NullPointerExceptionকোনও nullবস্তুকে সম্মানিত করা হলে তা নিক্ষেপ করা হবে । সুতরাং, কেন এই অতিরিক্ত নাল চেক করা উচিত NullPointerException?

একটি সুস্পষ্ট উত্তর (বা সুবিধা) হ'ল এটি কোডকে আরও পঠনযোগ্য করে তোলে এবং আমি সম্মত। আমি Objects.requireNonNull()পদ্ধতির শুরুতে ব্যবহারের অন্য কোনও কারণ জানতে আগ্রহী ।




1
যুক্তি পরীক্ষার সেই পদ্ধতির সাহায্যে আপনি ইউনিট পরীক্ষাগুলি লেখার সময় প্রতারণা করতে পারেন। বসন্তেরও এর মতো ইউটিলিটি রয়েছে (দেখুন ডকস.স্প্রিং.আইও / স্প্রিং / ডকস / কর্নার / জাভাদোক- এপি / অর্গ / ))। আপনার যদি "যদি" থাকে এবং উচ্চ ইউনিট পরীক্ষার কভারেজ থাকতে চান তবে আপনাকে উভয় শাখা আবরণ করতে হবে: শর্তটি যখন পূরণ করা হয় এবং যখন শর্ত পূরণ হয় না। আপনি যদি ব্যবহার করেন তবে Objects.requireNonNullআপনার
কোডটির

উত্তর:


214

কারণ আপনি এটি করে বিষয়গুলিকে সুস্পষ্ট করতে পারেন। ভালো লেগেছে:

public class Foo {
  private final Bar bar;

  public Foo(Bar bar) {
    Objects.requireNonNull(bar, "bar must not be null");
    this.bar = bar;
  }

বা সংক্ষিপ্ত:

  this.bar = Objects.requireNonNull(bar, "bar must not be null");

এখন আপনি জানেন :

  • যখন একটি ফু অবজেক্ট সফলভাবে ব্যবহার করে তৈরি করা হয়েছিলnew()
  • তারপর তার দণ্ড ক্ষেত্র নিশ্চিত অ নাল হতে।

এর সাথে তুলনা করুন: আপনি আজ একটি ফু অবজেক্ট তৈরি করেন এবং আগামীকাল আপনি সেই পদ্ধতিটি ব্যবহার করেন যা সেই ক্ষেত্রটি ব্যবহার করে এবং ছুড়ে দেয়। সম্ভবত, আপনি আগামীকালই জানবেন না যে গতকাল কনস্ট্রাক্টরের কাছে পাস করার পরে কেন সেই রেফারেন্সটি বাতিল হয়েছিল !

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

প্রধান সুবিধা হ'ল:

  • যেমন বলা হয়েছে, নিয়ন্ত্রিত আচরণ
  • সহজ ডিবাগিং - কারণ আপনি অবজেক্ট তৈরির প্রসঙ্গে throw এমন সময়ে যেখানে আপনার একটি নির্দিষ্ট সুযোগ রয়েছে যে আপনার লগগুলি / ট্রেসগুলি আপনাকে কী ভুল হয়েছে তা বলে দেয়!
  • এবং উপরে যেমন দেখানো হয়েছে: এই ধারণার আসল শক্তি চূড়ান্ত ক্ষেত্রগুলির সাথে মিলিত হয় । কারণ এখন আপনার ক্লাসের অন্য কোনও কোড নিরাপদে ধরে নিতে পারে যে barএটি নাল নয় - এবং সুতরাং আপনাকে if (bar == null)অন্য জায়গায় কোনও চেকের দরকার নেই !

23
আপনি নিজের কোডটি আরও কমপ্যাক্ট করে লেখার মাধ্যমে তৈরি করতে পারেনthis.bar = Objects.requireNonNull(bar, "bar must not be null");
কিরিল রাখমান

3
@ কিরিলরখমান ঘোস্টগেটকে এমন কিছু শীতল শিক্ষা দিচ্ছেন যা সম্পর্কে আমি জানতাম না -> ঘোস্টগেটের আপটোট লটারিতে টিকিট জিততে হবে।
ঘোস্টটিক

1
আমি মনে করি এখানে মন্তব্য # 1 এর আসল উপকার Objects.requireNonNull(bar, "bar must not be null");। এই এক জন্য ধন্যবাদ।
কাও

1
কোনটি প্রথমে ছিল এবং "ভাষা" লোকেদের কিছু লাইব্রেরির লেখককে অনুসরণ করা উচিত কেন ?! কেন পেয়ারা জাভা ল্যাং আচরণ অনুসরণ করে না ?!
ঘোস্টটিক

1
this.bar = Objects.requireNonNull(bar, "bar must not be null");দুই বা ততোধিক ভেরিয়েবল একই পদ্ধতি সেট করা হয়, তাহলে কনস্ট্রাকটর মধ্যে ঠিক আছে, কিন্তু অন্যান্য পদ্ধতির এ সম্ভাব্য বিপজ্জনক। উদাহরণ: talkwards.com/2018/11/03/…
এর্ক

99

ব্যর্থ ফাস্ট

কোডটি যত তাড়াতাড়ি সম্ভব ক্র্যাশ করা উচিত। এটি অর্ধেক কাজ না করা উচিত এবং তারপরে নাল এবং ক্র্যাশটিকে কেবলমাত্র অবৈধ অবস্থায় রাখার ফলে কিছু কাজ অর্ধেক রেখে দেবে।

একে সাধারণত "ব্যর্থ তাড়াতাড়ি" বা "ব্যর্থ-দ্রুত" বলা হয়


40

নালপয়েন্টার এক্সসেপশনটি কোনও নাল অবজেক্টকে অবলম্বন করা হলে যাইহোক নিক্ষিপ্ত হবে। সুতরাং, কেন এই অতিরিক্ত নাল চেক করা উচিত এবং নালপয়েন্টারএক্সসেপশন নিক্ষেপ করা উচিত?

এর অর্থ আপনি তাত্ক্ষণিকভাবে এবং নির্ভরযোগ্যভাবে সমস্যাটি সনাক্ত করেন ।

বিবেচনা:

  • আপনার কোডটি ইতিমধ্যে কিছু পার্শ্ব প্রতিক্রিয়া সম্পাদন করার পরে পদ্ধতিটিতে রেফারেন্সটি ব্যবহার করা যাবে না
  • এই পদ্ধতিতে রেফারেন্সটি মোটেও অবহেলা করা যায় না
    • এটি সম্পূর্ণ ভিন্ন কোডে পাস করা যেতে পারে (উদাহরণস্বরূপ কারণ এবং ত্রুটি কোড স্পেসে অনেক দূরে)
    • এটি পরে ব্যবহার করা যেতে পারে (কারণ কারণ এবং ত্রুটি সময়ে অনেক দূরে)
  • এটি ব্যবহৃত কোথাও হতে পারে যে একটি নাল রেফারেন্স হয় বৈধ, কিন্তু একটি অনিচ্ছাকৃত প্রভাব রয়েছে

.NET এটিকে NullReferenceException("আপনি একটি নাল মানকে সম্মানিত করেছেন") থেকে আলাদা করে ("আপনার পক্ষে ArgumentNullExceptionযুক্তি হিসাবে নালাগুলি দেওয়া উচিত ছিল না - এবং এটি এই প্যারামিটারের জন্য ছিল ) I কাঙ্কা জাভাও একই কাজ করতেন, তবে এমনকি কেবলমাত্র NullPointerException, ত্রুটিটি প্রাথমিক পর্যায়ে ছুঁড়ে দেওয়া হয়েছে যেখানে এটি সনাক্ত করা যেতে পারে তবে কোড ঠিক করা আরও সহজ।


12

requireNonNull()কোনও পদ্ধতিতে প্রথম বিবৃতি হিসাবে ব্যবহার করা এখনই / দ্রুত ব্যতিক্রমের কারণ চিহ্নিত করার অনুমতি দেয়।
স্ট্যাকট্রেস স্পষ্টভাবে ইঙ্গিত করে যে পদ্ধতিটিতে প্রবেশের সাথে সাথে ব্যতিক্রমটি ছুঁড়ে ফেলা হয়েছিল কারণ কলার প্রয়োজনীয়তা / চুক্তিকে সম্মান করেননি। একটি পাসিং nullঅন্য পদ্ধতি থেকে বস্তুর পারে প্রকৃতপক্ষে একটি সময়ে একটি ব্যতিক্রম কিন্তু সমস্যার কারণ আরো বুঝতে যেমন ব্যতিক্রম একটি নির্দিষ্ট আবাহন নিক্ষিপ্ত হবে জটিল হতে পারে ঘটান nullবস্তু আরও অনেক হতে পারে।


এখানে একটি কংক্রিট এবং আসল উদাহরণ রয়েছে যা দেখায় যে কেন আমাদের সাধারণভাবে দ্রুত ব্যর্থ Object.requireNonNull()হতে হবে এবং বিশেষত ব্যবহার না করা বা না হওয়ার জন্য ডিজাইন করা প্যারামিটারগুলিতে কোনও নাল চেক করতে কোনও উপায় null

একটি ধরুন Dictionaryবর্গ করে একটি composes LookupServiceএবং Listএর Stringঅন্তর্ভুক্ত শব্দ উপস্থাপন করে। এই ক্ষেত্রগুলি হতে হবে ডিজাইন করা হয় nullএবং এই এক পাস করা হয়েছে Dictionary কন্সট্রাকটর।

এখন একটা 'খারাপ' বাস্তবায়ন অনুমান করা Dictionaryছাড়া nullপদ্ধতি এন্ট্রি (এখানে যে কন্সট্রাকটর হয়) মধ্যে চেক:

public class Dictionary {

    private final List<String> words;
    private final LookupService lookupService;

    public Dictionary(List<String> words) {
        this.words = this.words;
        this.lookupService = new LookupService(words);
    }

    public boolean isFirstElement(String userData) {
        return lookupService.isFirstElement(userData);
    }        
}


public class LookupService {

    List<String> words;

    public LookupService(List<String> words) {
        this.words = words;
    }

    public boolean isFirstElement(String userData) {
        return words.get(0).contains(userData);
    }
}

এখন, প্যারামিটারের জন্য Dictionaryএকটি nullরেফারেন্স সহ কনস্ট্রাক্টরকে অনুরোধ করব words:

Dictionary dictionary = new Dictionary(null); 

// exception thrown lately : only in the next statement
boolean isFirstElement = dictionary.isFirstElement("anyThing");

জেভিএম এই বিবৃতিতে এনপিই নিক্ষেপ করেছে:

return words.get(0).contains(userData); 
থ্রেড "মূল" java.lang. নালপয়েন্টারএক্সেপশন ব্যতিক্রম
    লুকআপ সার্ভিস.আইএস ফার্স্ট এলিমেটে (লুকআপ সার্ভিস.জভা ৫৫)
    ডিকশনারি.আইসফারস্টিমেটমেন্টে (অভিধান.জভা ১৫:১৫)
    ডিকশনারি.মেনে (অভিধান.জভা २२)

ব্যতিক্রমটি LookupServiceক্লাসে ট্রিগার করা হয়েছে যখন এর উত্সটি আগে ভাল ছিল ( Dictionaryকনস্ট্রাক্টর)। এটি সামগ্রিক ইস্যু বিশ্লেষণকে অনেক কম স্পষ্ট করে তোলে।
হয় words null? হয় words.get(0) null? দুটোই? কেন একজন, অন্য বা সম্ভবত দুজনেই null? এটি Dictionary(কনস্ট্রাক্টর? অনুরোধ পদ্ধতিতে) কোনও কোডিং ত্রুটি ? এটিতে কোডিং ত্রুটি রয়েছে LookupService? (কনস্ট্রাক্টর? চালিত পদ্ধতি?)?
শেষ অবধি, ত্রুটির উত্স খুঁজে পেতে আমাদের আরও কোড পরিদর্শন করতে হবে এবং আরও জটিল শ্রেণিতে সম্ভবত এটি কী ঘটেছিল তা আরও সহজে বুঝতে একটি ডিবাগার ব্যবহার করতে পারেন।
তবে কেন একটি সাধারণ জিনিস (নাল চেকের অভাব) জটিল সমস্যা হয়ে ওঠে?
কারণ আমরা নিম্ন উপাদানগুলিতে নির্দিষ্ট উপাদান ফুটোতে প্রারম্ভিক বাগ / অভাব চিহ্নিত করতে পেরেছি।
মনে করুন যে LookupServiceএটি কোনও স্থানীয় পরিষেবা নয় বরং একটি রিমোট সার্ভিস বা তৃতীয় পক্ষের একটি লাইব্রেরির সাথে কয়েকটি ডিবাগিং তথ্য ছিল বা ধারণা করুন যে nullসনাক্তকরণের আগে আপনার কাছে 2 স্তর ছাড়া 4 বা 5 স্তর অবজেক্টের অনুরোধ নেই ? সমস্যাটি বিশ্লেষণ করা আরও জটিল হবে।

তাই অনুগ্রহ করার উপায়:

public Dictionary(List<String> words) {
    this.words = Objects.requireNonNull(words);
    this.lookupService = new LookupService(words);
}

এইভাবে, কোনও মাথা ব্যথা নয়: এটি পাওয়ার সাথে সাথে আমরা ব্যতিক্রম ছুঁড়ে ফেলি:

// exception thrown early : in the constructor 
Dictionary dictionary = new Dictionary(null);

// we never arrive here
boolean isFirstElement = dictionary.isFirstElement("anyThing");
থ্রেড "মূল" java.lang. নালপয়েন্টারএক্সেপশন ব্যতিক্রম
    java.util.Objects.requireNonNull (অবজেক্টস.জভা ২০:০৩)
    com.D অভিধান এ। (অভিধান.জভা 15:15)
    com.D অভিধান.main (ডিকশনারি.জভা ২৪)

নোট করুন যে আমি এখানে একটি কনস্ট্রাক্টর দিয়ে সমস্যাটি বর্ণনা করেছি তবে একটি পদ্ধতিতে অনুরোধে একই নন চেক সীমাবদ্ধতা থাকতে পারে।


কি দারুন! দুর্দান্ত ব্যাখ্যা।
জোনাথাস ন্যাসিমেণ্টো

2

একটি পার্শ্ব নোট হিসাবে, এই ব্যর্থ দ্রুত Object#requireNotNullজাভা -9 এর আগে কিছু জের ক্লাসের ভিতরে তাদের কিছুটা আগে প্রয়োগ করা হয়েছিল। ধরুন কেস:

 Consumer<String> consumer = System.out::println;

জাভা -8 এ এটি (কেবলমাত্র প্রাসঙ্গিক অংশ) হিসাবে সংকলিত হয়

getstatic Field java/lang/System.out
invokevirtual java/lang/Object.getClass

মূলত একটি অপারেশন: yourReference.getClass- যা আপনার রেফারেন্স হয় ব্যর্থ হবে null

জিনিসগুলি jdk-9 এ পরিবর্তিত হয়েছে যেখানে একই কোডটি সংকলিত হয়

getstatic Field java/lang/System.out
invokestatic java/util/Objects.requireNonNull

বা মূলত Objects.requireNotNull (yourReference)


1

বেসিক ব্যবহারটি চেক করা এবং NullPointerExceptionতাত্ক্ষণিকভাবে নিক্ষেপ করা হচ্ছে।

একই প্রয়োজনীয়তাটি পূরণের জন্য আরও একটি ভাল বিকল্প (শর্টকাট) হ'ল লম্বোক দ্বারা নননুল টিকা।


1
টীকাগুলি অবজেক্ট পদ্ধতির প্রতিস্থাপন নয়, তারা একসাথে কাজ করে। আপনি @ নননল এক্স = জোরউইনল বলতে পারবেন না, আপনি @ নননল x = অবজেক্টস.রেকায়ারনননল (সম্ভবতব্বেনুল, "অনিবার্য!") বলবেন;
বিল কে

@ বিলক দুঃখিত, আমি আপনাকে পেয়ে যাব না
সুপুন বিজেরথনে

আমি কেবল বলছিলাম যে নননুল টিকাটি প্রয়োজনীয় ননল নিয়ে কাজ করে, এটি কোনও বিকল্প নয়, তবে তারা একসাথে বেশ ভালভাবে কাজ করেন।
বিল কে

ব্যর্থ দ্রুত প্রকৃতি বাস্তবায়ন, এটি একটি বিকল্প অধিকার? হ্যাঁ, আমি এটির জন্য এই নিয়োগের বিকল্প নয় agree
সুপুন উইজরাথনে

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

1

নাল পয়েন্টার ব্যতিক্রম নিক্ষেপ করা হয় যখন আপনি কোনও বস্তুর কোনও সদস্যকে অ্যাক্সেস করেন যা nullপরে বিন্দুতে থাকে। Objects.requireNonNull()তাত্ক্ষণিকভাবে মানটি পরীক্ষা করে এবং অগ্রসর না করে তাত্ক্ষণিকভাবে ব্যতিক্রম ছুঁড়ে দেয়।


0

আমি মনে করি এটি অনুলিপি নির্মাণকারী এবং ডিআই এর মতো আরও কিছু ক্ষেত্রে ব্যবহার করা উচিত যার ইনপুট প্যারামিটারটি কোনও বস্তু, আপনার প্যারামিটারটি নাল কিনা তা পরীক্ষা করা উচিত। এই পরিস্থিতিতে আপনি এই স্থিতিশীল পদ্ধতিটি সুবিধামত ব্যবহার করতে পারেন।


0

সংকলক এক্সটেনশনের প্রসঙ্গে যা নলিবিলিটি চেকিং (যেমন: উবার / নুলাওয়ে ) Objects.requireNonNullপ্রয়োগ করে, আপনার কোডের একটি নির্দিষ্ট পয়েন্টে যখন আপনার জানা ক্ষেত্রটি জেনে যায় যে কিছু ক্ষুদ্র হয় না এমন ক্ষেত্রে কিছুটা অল্প পরিমাণে ব্যবহার করা উচিত।

এইভাবে, দুটি প্রধান ব্যবহার রয়েছে:

  • ভ্যালিডেশন

    • ইতিমধ্যে এখানে অন্যান্য প্রতিক্রিয়া দ্বারা কভার
    • ওভারহেড এবং সম্ভাব্য এনপিই সহ রানটাইম চেক করুন
  • অযোগ্যতা চিহ্নিতকরণ (@ নুলাবল থেকে @ নননলে পরিবর্তিত)

    • সংকলন-সময় চেকিংয়ের পক্ষে রানটাইম চেকের সর্বনিম্ন ব্যবহার
    • টীকাগুলি সঠিক হলে কেবল কাজ করে (সংকলক দ্বারা প্রয়োগ)

নালাইবিলিটি চিহ্নিতকরণের ব্যবহারের উদাহরণ:

@Nullable
Foo getFoo(boolean getNull) { return getNull ? null : new Foo(); }

// Changes contract from Nullable to Nonnull without compiler error
@Nonnull Foo myFoo = Objects.requireNonNull(getFoo(false));
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.