একক নাল আর্গুমেন্ট দিয়ে জাভা ভারার্গস পদ্ধতিটি কল করছেন?


97

যদি আমি একটি vararg জাভা পদ্ধতি আছে foo(Object ...arg)এবং আমি কল foo(null, null), আমি উভয় আছে arg[0]এবং arg[1]যেমন nullসে। কিন্তু যদি আমি ফোন foo(null), argনিজেই নাল হয়। ইহা কি জন্য ঘটিতেছে?

আমি কিভাবে কল করা উচিত fooযেমন যে foo.length == 1 && foo[0] == nullহয় true?

উত্তর:


95

সমস্যাটি হ'ল আপনি যখন আক্ষরিক নাল ব্যবহার করেন তখন জাভা জানেন না এটি কী ধরণের supposed এটি নাল অবজেক্ট হতে পারে, বা এটি নাল অবজেক্ট অ্যারে হতে পারে। একক যুক্তির জন্য এটি পরবর্তীটি ধরে নেয়।

আপনার দুটি পছন্দ আছে। দৃject়ভাবে টাইপ করা ভেরিয়েবলটি ব্যবহার করে অবজেক্টে বা কল করতে পদ্ধতিটিকে নাল স্পষ্টভাবে কাস্ট করুন। নীচের উদাহরণটি দেখুন:

public class Temp{
   public static void main(String[] args){
      foo("a", "b", "c");
      foo(null, null);
      foo((Object)null);
      Object bar = null;
      foo(bar);
   }

   private static void foo(Object...args) {
      System.out.println("foo called, args: " + asList(args));
   }
}

আউটপুট:

foo called, args: [a, b, c]
foo called, args: [null, null]
foo called, args: [null]
foo called, args: [null]

আপনি যদি asListনমুনায় পদ্ধতিটি এবং তার উদ্দেশ্য তালিকাভুক্ত করে থাকেন তবে অন্যদের পক্ষে সহায়ক হবে ।
অরুণ কুমার

5
@ আরুনকুমার ক্লাস asList()থেকে স্ট্যাটিক আমদানি java.util.Arrays। আমি কেবল ধরে নিলাম এটি সুস্পষ্ট ছিল। যদিও এখন আমি এটি সম্পর্কে চিন্তা করছি, আমার সম্ভবত এটি কেবলমাত্র ব্যবহার করা উচিত ছিল Arrays.toString()কারণ এটি একটি তালিকায় রূপান্তরিত হওয়ার একমাত্র কারণ এটি খুব সুন্দরভাবে মুদ্রণ করবে।
মাইক ডেক

24

আপনার এটিতে একটি স্পষ্ট কাস্ট দরকার Object:

foo((Object) null);

অন্যথায় আর্গুমেন্টটি পুরো অ্যারে হিসাবে ধরে নেওয়া হয় যা ভারারাগুলি প্রতিনিধিত্ব করে।


আসলেই নয়, আমার পোস্টটি দেখুন।
বুহাকে সিন্ধি

উফ, এখানেও একই ... দুঃখিত, মধ্যরাতের তেল।
বুহাকে সিন্ধি

6

এটি বর্ণনা করার জন্য একটি পরীক্ষার কেস:

ভারা-গ্রহণ পদ্ধতি পদ্ধতির ঘোষণার সাথে জাভা কোড (যা স্থির হয়ে থাকে):

public class JavaReceiver {
    public static String receive(String... x) {
        String res = ((x == null) ? "null" : ("an array of size " + x.length));
        return "received 'x' is " + res;
    }
}

এই জাভা কোড (একটি JUnit4 পরীক্ষার কেস) উপরের কল করে (আমরা পরীক্ষার কেসটি কিছু পরীক্ষা না করে কেবল কিছু আউটপুট উত্পন্ন করতে ব্যবহার করছি):

import org.junit.Test;

public class JavaSender {

    @Test
    public void sendNothing() {
        System.out.println("sendNothing(): " + JavaReceiver.receive());
    }

    @Test
    public void sendNullWithNoCast() {
        System.out.println("sendNullWithNoCast(): " + JavaReceiver.receive(null));
    }

    @Test
    public void sendNullWithCastToString() {
        System.out.println("sendNullWithCastToString(): " + JavaReceiver.receive((String)null));
    }

    @Test
    public void sendNullWithCastToArray() {
        System.out.println("sendNullWithCastToArray(): " + JavaReceiver.receive((String[])null));
    }

    @Test
    public void sendOneValue() {
        System.out.println("sendOneValue(): " + JavaReceiver.receive("a"));
    }

    @Test
    public void sendThreeValues() {
        System.out.println("sendThreeValues(): " + JavaReceiver.receive("a", "b", "c"));
    }

    @Test
    public void sendArray() {
        System.out.println("sendArray(): " + JavaReceiver.receive(new String[]{"a", "b", "c"}));
    }
}

এটি JUnit পরীক্ষার ফলন হিসাবে চালানো:

সেন্ডনথিং (): প্রাপ্ত 'x' হ'ল আকারের অ্যারে
সেন্ডনুলউইথনোকাস্ট (): প্রাপ্ত 'x' নাল is
সেন্ড নলউইথকাস্টটোস্ট্রিং (): প্রাপ্ত 'x' হ'ল আকারের একটি অ্যারে
সেন্ডনুলউইথকাস্টটোআররে (): প্রাপ্ত 'x' নাল
সেন্ডওয়েলু (): প্রাপ্ত 'x' হ'ল আকারের অ্যারে
সেন্ডভ্যালিজ (): প্রাপ্ত 'x' হ'ল আকারের একটি অ্যারে
সেন্ডআরে (): প্রাপ্ত 'x' হ'ল আকারের অ্যারে

এটি আরও আকর্ষণীয় করার জন্য, আসুন receive()গ্রোভি ২.১.২ থেকে ফাংশনটি কল করুন এবং দেখুন কী ঘটে। দেখা যাচ্ছে ফলাফল এক নয়! এটি যদিও বাগ হতে পারে।

import org.junit.Test

class GroovySender {

    @Test
    void sendNothing() {
        System.out << "sendNothing(): " << JavaReceiver.receive() << "\n"
    }

    @Test
    void sendNullWithNoCast() {
        System.out << "sendNullWithNoCast(): " << JavaReceiver.receive(null) << "\n"
    }

    @Test
    void sendNullWithCastToString() {
        System.out << "sendNullWithCastToString(): " << JavaReceiver.receive((String)null) << "\n"
    }

    @Test
    void sendNullWithCastToArray() {
        System.out << "sendNullWithCastToArray(): " << JavaReceiver.receive((String[])null) << "\n"
    }

    @Test
    void sendOneValue() {
        System.out << "sendOneValue(): " + JavaReceiver.receive("a") << "\n"
    }

    @Test
    void sendThreeValues() {
        System.out << "sendThreeValues(): " + JavaReceiver.receive("a", "b", "c") << "\n"
    }

    @Test
    void sendArray() {
        System.out << "sendArray(): " + JavaReceiver.receive( ["a", "b", "c"] as String[] ) << "\n"
    }

}

এটি JUnit পরীক্ষা হিসাবে চালানো জাভির পার্থক্যটি সাহসের সাথে হাইলাইট করে নীচের ফলাফল দেয়।

সেন্ডনথিং (): প্রাপ্ত 'x' হ'ল আকারের অ্যারে
সেন্ডনুলউইথনোকাস্ট (): প্রাপ্ত 'x' নাল is
সেন্ডনুলউইথকাস্টটোস্ট্রিং (): প্রাপ্ত 'x' নাল
সেন্ডনুলউইথকাস্টটোআররে (): প্রাপ্ত 'x' নাল
সেন্ডওয়েলু (): প্রাপ্ত 'x' হ'ল আকারের অ্যারে
সেন্ডভ্যালিজ (): প্রাপ্ত 'x' হ'ল আকারের একটি অ্যারে
সেন্ডআরে (): প্রাপ্ত 'x' হ'ল আকারের অ্যারে

এটি প্যারামিটার ছাড়াই বৈকল্পিক ফাংশনটিকে কল করার বিষয়টি বিবেচনা করে
bebbo

3

এটি কারণ একটি ভারার্গস পদ্ধতিটিকে অ্যারে উপাদানগুলির একটি সিরিজ না করে একটি আসল অ্যারে দিয়ে কল করা যেতে পারে। আপনি যখন দ্ব্যর্থক সঙ্গে এটি প্রদান nullনিজে, এটা অনুমান nullএকটি হল Object[]। কাস্টিং nullকরতে Objectএই ঠিক করবে।


1

আমি পছন্দ করি

foo(new Object[0]);

নাল পয়েন্টার ব্যতিক্রম এড়াতে।

আশা করি এটা সাহায্য করবে.


14
ঠিক আছে, যদি এটি একটি ভারার্গ পদ্ধতি হয় তবে কেন কেবল এটির মতো বলা হবে না foo()?
BrainStorm.exe ০১:০৫

@ BrainStorm.exe আপনার উত্তরটি উত্তর হিসাবে চিহ্নিত করা উচিত। ধন্যবাদ
এমডিপি

1

পদ্ধতির ওভারলোডিং রেজোলিউশনের ক্রমটি হল ( https://docs.oracle.com/javase/specs/jls/se11/html/jls-15.html#jls-15.12.2 ):

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

    এটি গ্যারান্টি দেয় যে জাভা এসই 5.0 এর আগে জাভা প্রোগ্রামিং ভাষায় বৈধ ছিল এমন কোনও কলগুলি ভেরিয়েবল আরটি পদ্ধতি, অন্তর্ভুক্ত বক্সিং এবং / অথবা আনবক্সিংয়ের প্রবর্তনের ফলাফল হিসাবে অস্পষ্ট হিসাবে বিবেচিত হবে না। যাইহোক, একটি পরিবর্তনশীল আরটি পদ্ধতির ঘোষণা (§8.4.1) প্রদত্ত পদ্ধতি পদ্ধতির জন্য প্রার্থনা অভিব্যক্তির জন্য নির্বাচিত পদ্ধতিটি পরিবর্তন করতে পারে, কারণ একটি ভেরিয়েবল আরটি পদ্ধতিটি প্রথম পর্যায়ে একটি স্থির আরাতি পদ্ধতি হিসাবে বিবেচিত হয়। উদাহরণস্বরূপ, এম (অবজেক্ট ...) শ্রেণিতে এম (অবজেক্ট ...) ঘোষণা করা যা এম (অবজেক্ট) ইতিমধ্যে এম (অবজেক্ট) হিসাবে ঘোষণা করে এম (অবজেক্ট) এর জন্য কিছু আহবান অভিব্যক্তির (যেমন এম (নাল)), এম হিসাবে বেছে নেওয়া হবে না (অবজেক্ট [] ) আরও নির্দিষ্ট।

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

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

  3. তৃতীয় ধাপ ওভারলোডিংকে ভেরিয়েবল আরটি পদ্ধতি, বক্সিং এবং আনবক্সিংয়ের সাথে একত্রিত করার অনুমতি দেয়।

foo(null)প্রথম পর্বের foo(Object... arg)সাথে মেলে arg = nullarg[0] = nullতৃতীয় পর্ব হতে হবে, যা কখনই ঘটে না।

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