পরামিতিগুলিতে জাভা ধরণের প্রচার


20

আমি এই স্নিপেটকে হোঁচট খেয়েছি:

public class ParamTest {
    public static void printSum(int a, double b) {
        System.out.println("In intDBL " + (a + b));
    }

    public static void printSum(long a, long b) {
        System.out.println("In long " + (a + b));
    }

    public static void printSum(double a, long b) {
        System.out.println("In doubleLONG " + (a + b));
    }

    public static void main(String[] args) {
        printSum(1, 2);
    }
}

এটি একটি সংকলন ত্রুটির ফলস্বরূপ:

ত্রুটি: (15, 9) জাভা: প্রিন্টসামের রেফারেন্সটি প্যারাম টেস্টে দুটি পদ্ধতি মুদ্রণসাম (ইনট, ডাবল) এবং প্যারামটেষ্ট ম্যাচে পদ্ধতি প্রিন্টসাম (দীর্ঘ, দীর্ঘ)

এই অস্পষ্টতা কেমন? প্রথম প্যারামিটারটি ইতিমধ্যে কোনও ইনট হিসাবে এই ক্ষেত্রে কেবল দ্বিতীয় প্যারামিটারটি প্রচার করা উচিত নয়? এক্ষেত্রে প্রথম পরমকে পদোন্নতি দেওয়া উচিত নয়?

আমি অন্য পদ্ধতি যুক্ত করার জন্য কোডটি আপডেট করলে সংকলনটি সফল হয়:

public static void printSum(int a, long b) {
    System.out.println(String.format("%s, %s ", a, b));
}

আমাকে কেবল স্পষ্ট করতে প্রসারিত করুন। নীচের কোডটি অস্পষ্টতার ফলস্বরূপ:

public class ParamTest {

    public static void printSum(int a, double b) {
        System.out.println("In intDBL " + (a + b));
    }

    public static void printSum(long a, long b) {
        System.out.println("In long " + (a + b));
    }

    public static void main(String[] args) {
        printSum(1, 2);
    }
}

তারপর এই কোড নিচে এছাড়াও অস্পষ্টতা ফলাফল:

public class ParamTest {

    public static void printSum(int a, double b) {
        System.out.println("In intDBL " + (a + b));
    }

    public static void printSum(double a, long b) {
        System.out.println("In doubleLONG " + (a + b));
    }

    public static void main(String[] args) {
        printSum(1, 2);
    }
}

তবে এটির দ্ব্যর্থতার ফলে আসে না :

public class ParamTest {

    public static void printSum(int a, double b) {
        System.out.println("In intDBL " + (a + b));
    }

    public static void printSum(long a, double b) {
        System.out.println("In longDBL " + (a + b));
    }

    public static void main(String[] args) {
        printSum(1, 2);
    }
}

2
সংকলকটি আপনার কল প্রিন্টসামকে মানচিত্র করতে পারে (1, 2); যে কোনও প্রিন্টসাম (দীর্ঘ ক, দীর্ঘ খ) বা প্রিন্টসাম (ইন্ট এ, ডাবল বি) তাই এটি অস্পষ্ট। আপনাকে সংকলককে স্পষ্টভাবে এই ধরণের ধরণের মাধ্যমে প্রকারের মধ্যে চয়ন করতে সহায়তা করতে হবে: প্রিন্টসাম (1, 2 ডি)
রবীন্দ্র রণওয়ালা

6
আপনি ত্রুটি বার্তাকে ভুলভাবে চিহ্নিত করেছেন এবং পার্থক্যটি খুব গুরুত্বপূর্ণ। প্রকৃত ত্রুটি বার্তাটি হ'ল: Error:(15, 9) java: reference to printSum is ambiguous both method printSum(int,double) in ParamTest and method printSum(long,long) in ParamTest match- এটি যে পদ্ধতিটি দ্ব্যর্থক তা নয়, এটি সেই পদ্ধতির কল যা অস্পষ্ট।
এরউইন বলউইড্ট

1
@ ইরভিনবোল্ট ত্রুটি বার্তাটি গ্রহন থেকে এসেছে দুঃখিত আমি সেখানে ভুল বোধ করেছি। যাইহোক, আমি এখনও এটি বুঝতে পারি না কারণ প্রিন্টসাম যুক্ত করা (int a, দীর্ঘ খ) ত্রুটি বার্তাটিকে সরিয়ে দেয়।
riruzen

2
JLS-5.3 => যদি আলগা প্রার্থনার প্রসঙ্গে অনুমতিপ্রাপ্ত রূপান্তর দ্বারা অভিব্যক্তির ধরণটিকে প্যারামিটারের ধরণে রূপান্তর করা যায় না, তবে একটি সংকলন-সময় ত্রুটি ঘটে। প্রসঙ্গে প্রযোজ্য বলে মনে হচ্ছে, তবে কীভাবে তা নির্ধারণ করা সত্যিকারের সোজা নয়। +1
নামান

1
আমরা স্পষ্টভাবে জন্য এটি একটি ক্যানোনিকাল প্রশ্ন প্রয়োজন stackoverflow.com/... "।
Marco13

উত্তর:


17

আমি মনে করি জেএলএসের সুনির্দিষ্ট নিয়মের সাথে এর 15.12.2.5 এর কিছু সম্পর্ক রয়েছে। সর্বাধিক নির্দিষ্ট পদ্ধতি নির্বাচন করা । এতে বলা হয়েছে:

যদি একাধিক সদস্য পদ্ধতি উভয়ই অ্যাক্সেসযোগ্য এবং কোনও পদ্ধতিতে প্রার্থনার জন্য প্রযোজ্য হয় তবে রান-টাইম পদ্ধতি প্রেরণের জন্য বর্ণনাকারী সরবরাহ করার জন্য একজনকে বেছে নেওয়া প্রয়োজন। জাভা প্রোগ্রামিং ল্যাঙ্গুয়েজটি সুনির্দিষ্ট পদ্ধতিটি বেছে নেওয়ার নিয়মটি ব্যবহার করে।

জাভা কীভাবে সুনির্দিষ্ট পদ্ধতি চয়ন করে তা পাঠ্যের মাধ্যমে আরও ব্যাখ্যা করা হয়:

অনানুষ্ঠানিক স্বজ্ঞাততা হ'ল প্রথম পদ্ধতির দ্বারা পরিচালিত যে কোনও অনুরোধ একটি সংকলন-সময় ত্রুটি ছাড়াই অন্য একটিতে প্রেরণ করা যেতে পারে তার একটি পদ্ধতি অন্যর চেয়ে বেশি নির্দিষ্ট। স্পষ্টত টাইপিত ল্যাম্বডা এক্সপ্রেশন আর্গুমেন্ট (§15.27.1) বা ভেরিয়েবল আরটি ডাকে (§15.12.2.4) এর মতো ক্ষেত্রে কিছু স্বাচ্ছন্দ্যের সাথে একটি স্বাক্ষরের অপরটির সাথে মানিয়ে নিতে অনুমোদিত হয়।

আপনার উদাহরণের ক্ষেত্রে, সমস্ত পদ্ধতি অ্যাক্সেসযোগ্য এবং পদ্ধতিটি অনুরোধের জন্য প্রযোজ্য, অতএব, জাভা তাদের মধ্যে কোনটি সুনির্দিষ্ট নির্দিষ্ট করা দরকার

এই পদ্ধতির জন্য, কোনওটিই সুনির্দিষ্টভাবে নির্ধারিত হতে পারে না:

public static void printSum(int a, double b) {
    System.out.println("In intDBL " + (a + b));
} // int, double cannot be passed to long, long or double, long without error

public static void printSum(long a, long b) {
    System.out.println("In long " + (a + b));
} // long , long cannot be passed to int, double or double, long without error

public static void printSum(double a, long b) {
    System.out.println("In doubleLONG " + (a + b));
} // double, long cannot be passed to int, double or long, long without error

চতুর্থ পদ্ধতিটি অস্পষ্টতাকে স্পষ্টভাবে পরিষ্কার করে কারণ এটি সুনির্দিষ্ট হওয়ার জন্য প্রয়োজনীয় শর্তটি পূরণ করে ।

public static void printSum(int a, long b) {
    System.out.println(String.format("%s, %s ", a, b));
}

এটি হ'ল, (ইনট, লং) সংকলন ত্রুটি ছাড়াই (ইনট, ডাবল), (দীর্ঘ, দীর্ঘ), বা (ডাবল, দীর্ঘ) এ পাস করা যেতে পারে।


2
সুতরাং সংক্ষেপে, যদি সমস্ত পদ্ধতি কল দ্বারা অ্যাক্সেসযোগ্য হয়, তবে জাভা পদ্ধতিটি চিহ্নিত করুন, যা সংকলন সময়ের ত্রুটি ছাড়া অন্য পদ্ধতিতে কল করা যেতে পারে, যদি পাওয়া যায় তবে একে সুনির্দিষ্ট হিসাবে ব্যবহার করুন এবং অন্যথায় অস্পষ্টতার ত্রুটি হিসাবে কল করুন? আমি মনে করি, এটির একটি উত্তর @ রিরুজন।
সন্দীপ কোকতে

ধন্যবাদ! আমি এটি (ডাবল, ইনট) বনাম (ডাবল, লম্বা) দিয়ে চেষ্টা করেছি এবং এটি সত্যই অস্পষ্টতা পরিষ্কার করেছে, তখন (ডাবল, ইনট) বনাম (দীর্ঘ, ডাবল) প্রত্যাশা অনুযায়ী অস্পষ্ট ছিল।
riruzen

7

এটি সত্যিই একটি খুব আকর্ষণীয় প্রশ্ন। যাক জাভা ল্যাঙ্গুয়েজ স্পেসিফিকেশন ধাপে ধাপে।

  1. সংকলক যখন সম্ভাব্য প্রযোজ্য পদ্ধতিগুলি সনাক্ত করার চেষ্টা করছে, তখন এটি প্রথমে স্ট্রাইক ইনভোকেশন দ্বারা প্রযোজ্য পদ্ধতির সেরিং করা হয়

  2. আপনার ক্ষেত্রে এ জাতীয় কোনও পদ্ধতি নেই, সুতরাং পরবর্তী পদক্ষেপটি আলগা আমন্ত্রণ দ্বারা প্রযোজ্য পদ্ধতিগুলি সন্ধান করা

  3. এই মুহুর্তে সমস্ত পদ্ধতি মেলে, তাই সবচেয়ে নির্দিষ্ট পদ্ধতি ( §15.12.2.5 ) looseিলেভাবে অনুরোধ দ্বারা প্রযোজ্য পদ্ধতিগুলির মধ্যে চয়ন করা হয়।

এটি একটি মূল মুহূর্ত, সুতরাং আসুন এটি ঘনিষ্ঠভাবে দেখুন।

একটি প্রয়োগযোগ্য পদ্ধতি এম 1 অন্য প্রযোজ্য পদ্ধতি এম 2 এর চেয়ে আরও সুনির্দিষ্ট, আর্গুমেন্ট এক্সপ্রেশন E1, ..., এক সাথে অনুরোধের জন্য, নিম্নলিখিতগুলির মধ্যে যদি সত্য হয়:

(আমরা কেবল নিম্নলিখিত ক্ষেত্রে আগ্রহী):

  • এম 2 জেনেরিক নয়, এবং এম 1 এবং এম 2 কঠোর বা আলগা অনুরোধের দ্বারা প্রযোজ্য, এবং যেখানে এম 1 এর ফর্মাল প্যারামিটার ধরণের এস 1, ..., এসএন এবং এম 2 এর ফর্মাল প্যারামিটারের টি 1, ..., টিএন, সি টাইপ বেশি হয় সমস্ত i এর জন্য আর্গুমেন্ট ii এর জন্য টিয়ের চেয়ে নির্দিষ্ট (1 ≤ i ≤ n, n = কে)।

সহজ কথায় বলতে গেলে, কোনও পদ্ধতি তার সমস্ত পরামিতিগুলির প্রকারগুলি আরও সুনির্দিষ্ট হলে আরও নির্দিষ্ট । এবং

S <: T ( .4.10 ) যদি কোনও এক্সপ্রেশনের জন্য একটি টাইপ এস টাইপ টির চেয়ে বেশি নির্দিষ্ট ।

এক্সপ্রেশন S <: Tমানে এটি Sএকটি সাব টাইপ T। আদিমদের জন্য আমাদের নীচের সম্পর্ক রয়েছে:

double > float > long > int

সুতরাং আসুন আপনার পদ্ধতিগুলি দেখুন এবং দেখুন যে কোনটি অন্যের চেয়ে বেশি নির্দিষ্ট।

public static void printSum(int a, double b) {  // method 1
    System.out.println("In intDBL " + (a + b));
}

public static void printSum(double a, long b) { // method 2
    System.out.println("In doubleLONG " + (a + b));
}

এই উদাহরণে পদ্ধতির 1 এর প্রথম পরামিতিটি 2 পদ্ধতির প্রথম পরামিতির চেয়ে স্পষ্টতই বেশি নির্দিষ্ট (যদি আপনি তাদের পূর্ণসংখ্যার মান সহ কল ​​করেন printSum(1, 2):)। তবে দ্বিতীয় প্যারামিটারটি পদ্ধতি 2 এর জন্য আরও নির্দিষ্ট , কারণ long < double। সুতরাং এই পদ্ধতির কোনওটিই অন্যটির চেয়ে বেশি নির্দিষ্ট নয়। এজন্য আপনার এখানে দ্বিধাদ্বন্দ্ব রয়েছে।

নিম্নলিখিত উদাহরণে:

public static void printSum(int a, double b) { // method 1
    System.out.println("In intDBL " + (a + b));
}

public static void printSum(long a, double b) { // method 2
    System.out.println("In longDBL " + (a + b));
}

পদ্ধতির 1 এর প্রথম প্যারামিটার ধরণটি 2 পদ্ধতিতে একটির চেয়ে বেশি নির্দিষ্ট, কারণ int < longদ্বিতীয় পরামিতি প্রকারটি উভয়ের ক্ষেত্রেই একই, কারণ এই পদ্ধতিটি 1 বেছে নেওয়া হয়েছে।


আমি আপনার উত্তরটিকে নিম্নচলিত করি নি, তবে (উত্তর, ডাবল) কেন (দীর্ঘ, দীর্ঘ) নিয়ে দ্বিধাগ্রস্থ, এই স্পষ্টতই (পূর্ববর্তী, দ্বিগুণ) প্রথম প্যারামিটারের ক্ষেত্রে আরও নির্দিষ্ট হওয়া উচিত বলে এই উত্তরটি ব্যাখ্যা করে না।
riruzen

3
@ রিরুজেন এটি ব্যাখ্যা করেছেন: এর doubleচেয়ে বেশি নির্দিষ্ট নয় long। এবং পদ্ধতিটি বেছে নেওয়ার জন্য সমস্ত প্রকারের পরামিতিগুলি আরও সুনির্দিষ্ট হতে হবে: সমস্ত i এর জন্য আর্গুমেন্ট ei এর জন্য টাই টাই বেশি বেশি নির্দিষ্ট (1 ≤ i ≤ n, n = কে)
কিরিল সিমোনভ

এটি +1 আপ হওয়া উচিত
চা

0

কারণ int মানটি জাভাতেও দ্বিগুণ হিসাবে বিবেচিত হতে পারে। মানে double a = 3বৈধ এবং দীর্ঘের সাথে একই long b = 3তাই এটি একটি দ্বিধাগ্রস্থতা তৈরি করছে। আপনি ডাকুন

printSum(1, 2);

তিনটি পদ্ধতির জন্যই বিভ্রান্তিকর, কারণ এই তিনটিই বৈধ:

int a = 1;
double b =1;
long c = 1;

এটির দীর্ঘ মূল্য উল্লেখ করার জন্য আপনি শেষে এল রাখতে পারেন। উদাহরণ স্বরূপ:

printSum(1L, 2L);

দ্বিগুণ জন্য আপনাকে এটি রূপান্তর করতে হবে:

printSum((double)1, 2L);

এছাড়াও @ ইরভিন বলউইড্টের মন্তব্য পড়ুন


হ্যাঁ সংকলকটি 3 টি পদ্ধতির জন্য বিভ্রান্ত হয়ে পড়েছে, প্রথম সংকলকটি সঠিক ধরণের জন্য অনুসন্ধান করে এবং যদি এটি কোনও না পাওয়া যায় তবে সুসংগত প্রকারটি সন্ধান করার চেষ্টা করুন এবং এই ক্ষেত্রে সমস্ত সামঞ্জস্যপূর্ণ।
অন্য কোডার

2
যদি 3 এর পরিবর্তে আমার 4 পদ্ধতির ঘোষণা থাকে তবে দ্ব্যর্থহীনতাটি চলে আসে: পাবলিক স্ট্যাটিক শূন্য প্রিন্টসাম (ইনট্রি, ডাবল বি) পাবলিক স্ট্যাটিক শূন্য প্রিন্টসাম (ইনট্রি, লং খ) পাবলিক স্ট্যাটিক শূন্য প্রিন্টসাম (দীর্ঘ ক, দীর্ঘ বি) পাবলিক স্ট্যাটিক অকার্যকর প্রিন্টসাম (ডাবল এ, দীর্ঘ বি) তাই আমি যখন আপনার উত্তরটির সাথে একমত হই, তবুও এটি প্রশ্নের উত্তর দেয় না। সঠিক ভুল যদি আমি ভুল না হয়ে থাকি তবে জাভা স্বয়ংক্রিয় প্রকারের প্রচার করে। আমি কেন বুঝতে পারছি না যে এটি 3 এর সাথে কেন অস্পষ্ট হয়ে যায়
riruzen
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.