<এর মধ্যে পার্থক্য কী? বেস> এবং <টি বেস বাড়ায়>?


29

এই উদাহরণে:

import java.util.*;

public class Example {
    static void doesntCompile(Map<Integer, List<? extends Number>> map) {}
    static <T extends Number> void compiles(Map<Integer, List<T>> map) {}

    static void function(List<? extends Number> outer)
    {
        doesntCompile(new HashMap<Integer, List<Integer>>());
        compiles(new HashMap<Integer, List<Integer>>());
    }
}

doesntCompile() সংকলন করতে ব্যর্থ:

Example.java:9: error: incompatible types: HashMap<Integer,List<Integer>> cannot be converted to Map<Integer,List<? extends Number>>
        doesntCompile(new HashMap<Integer, List<Integer>>());
                      ^

যখন compiles()কম্পাইলার দ্বারা গ্রহণ করা হয়।

এই উত্তরটি ব্যাখ্যা করে যে একমাত্র পার্থক্য হ'ল বিপরীতভাবে <? ...>, <T ...>আপনাকে পরে প্রকারটি উল্লেখ করতে দেয়, যা মনে হয় না।

কি মধ্যে পার্থক্য <? extends Number>এবং <T extends Number>এই ক্ষেত্রে কি কারনে চাইছি প্রথম কম্পাইল না?


মন্তব্যগুলি বর্ধিত আলোচনার জন্য নয়; এই কথোপকথন চ্যাটে সরানো হয়েছে ।
স্যামুয়েল লিউ

[1] জাভা জেনেরিক ধরণ: তালিকা <এর মধ্যে পার্থক্য? সংখ্যা বিস্তৃত> এবং তালিকা <টি বিস্তৃত সংখ্যা> একই প্রশ্ন জিজ্ঞাসা করছে বলে মনে হচ্ছে, তবে এটি আগ্রহী হলেও এটি কোনও সদৃশ নয়। [২] যদিও এটি একটি ভাল প্রশ্ন, শিরোনাম চূড়ান্ত বাক্যে জিজ্ঞাসা করা নির্দিষ্ট প্রশ্নটি সঠিকভাবে প্রতিফলিত করে না।
স্কোমিসা

এটি ইতিমধ্যে এখানে উত্তর দেওয়া হয়েছে জাভা জেনেরিক তালিকা <তালিকা <? সংখ্যা প্রসারিত >>
M Qunh Quyết Nguyễn

এখানে ব্যাখ্যা সম্পর্কে কীভাবে ?
21

উত্তর:


14

নিম্নলিখিত স্বাক্ষর দিয়ে পদ্ধতিটি সংজ্ঞায়িত করে:

static <T extends Number> void compiles(Map<Integer, List<T>> map) {}

এবং এটি অনুরোধ:

compiles(new HashMap<Integer, List<Integer>>());

জেএসএস -8.1.2-এ আমরা দেখতে পেলাম যে (আমার দ্বারা আকর্ষণীয় অংশটি সাহসী হয়েছে):

জেনেরিক ক্লাস ডিক্লেয়ারেশন প্যারামিটারাইজড টাইপগুলির একটি সেট (§4.5) সংজ্ঞায়িত করে, টাইপ প্যারামিটার বিভাগের প্রতিটি সম্ভাব্য অনুরোধের জন্য টাইপ যুক্তি দ্বারা । এই সমস্ত প্যারামিটারাইজড ধরণের সময় একই সময়ে একই শ্রেণি ভাগ করে।

অন্য কথায়, টাইপটি Tইনপুট টাইপের সাথে মিলে যায় এবং নির্ধারিত হয় Integer। স্বাক্ষর কার্যকরভাবে হয়ে যাবে static void compiles(Map<Integer, List<Integer>> map)

যখন doesntCompileপদ্ধতিতে আসে , jls সাব টাইপিংয়ের নিয়ম সংজ্ঞায়িত করে ( §4.5.1 , আমার দ্বারা সাহসী):

একটি টাইপ আর্গুমেন্ট টি 1 টি অন্য ধরণের আর্গুমেন্ট টি 2 থাকে, টি 2 টি <= টি 1 লিখিত থাকে, যদি টি 2 দ্বারা নির্দেশিত প্রকারের সেটটি সম্ভবত নিম্নলিখিত বিধিগুলির প্রতিচ্ছবি এবং ট্রানজিটিভ বন্ধের অধীনে টি 1 দ্বারা চিহ্নিত ধরণের সংকলনের একটি উপসেট হিসাবে প্রমাণিত হয় ( যেখানে <: সাব টাইপিং (.4.10) বোঝায়:

  • ? টি <=? এস প্রসারিত করে যদি টি <: এস হয়

  • ? টি <=?

  • ? সুপার টি <=? সুপার এস যদি এস <: টি

  • ? সুপার টি <=?

  • ? সুপার টি <=? অবজেক্ট অব প্রজেক্ট

  • টি <= টি

  • টি <=? টি প্রসারিত

  • টি <=? সুপার টি

এর মানে হল, যে ? extends Numberপ্রকৃতপক্ষে রয়েছে Integerবা এমনকি List<? extends Number>ধারণ করে List<Integer>, কিন্তু এটি কেনার ক্ষেত্রে নয় Map<Integer, List<? extends Number>>এবং Map<Integer, List<Integer>>। এই বিষয়ের উপর আরও এই এস থ্রেডে পাওয়া যাবে । আপনি এখনও ?ঘোষণা করে ওয়াইল্ডকার্ড কাজের সাথে সংস্করণটি তৈরি করতে পারেন, যেটির একটি সাব টাইপ আপনি আশা করছেন List<? extends Number>:

public class Example {
    // now it compiles
    static void doesntCompile(Map<Integer, ? extends List<? extends Number>> map) {}
    static <T extends Number> void compiles(Map<Integer, List<T>> map) {}

    public static void main(String[] args) {
        doesntCompile(new HashMap<Integer, List<Integer>>());
        compiles(new HashMap<Integer, List<Integer>>());
    }
}

[1] আমি মনে করি আপনি এর ? extends Numberচেয়ে বরং বোঝাতে চেয়েছিলেন ? extends Numeric। [2] "তালিকা <? << প্রসারিত সংখ্যা> এবং তালিকা <Inger>> এর ক্ষেত্রে এটি ঠিক নয়" বলে আপনার দাবি ভুল। যেহেতু @ ভিনসেমিই ইতিমধ্যে নির্দেশ করেছে, আপনি একটি পদ্ধতি তৈরি করতে পারেন static void demo(List<? extends Number> lst) { }এবং এটিকে এটি demo(new ArrayList<Integer>());বা এটির মতো কল করতে পারেন demo(new ArrayList<Float>());এবং কোডটি সংকলন করে ঠিক আছে। অথবা আপনি সম্ভবত যা বলেছি তা আমি সম্ভবত ভুল ব্যাখ্যা করছি বা ভুল বোঝাবুঝি করছি?
স্কোমিসা

@ আপনি উভয় ক্ষেত্রেই ঠিক আছেন। যখন এটি আপনার দ্বিতীয় পয়েন্টে আসে, আমি এটি বিভ্রান্তিমূলকভাবে লিখেছিলাম। আমি List<? extends Number>পুরো মানচিত্রের একধরণের প্যারামিটার হিসাবে বোঝানো হয়েছিল, নিজেই নয়। মন্তব্য করার জন্য আপনাকে অনেক ধন্যবাদ।
অ্যান্ড্রোনিকাস

একই কারণে @ এস্কোমিসা List<Number>এতে নেই List<Integer>। ধরুন আপনার কোনও ফাংশন আছে static void check(List<Number> numbers) {}check(new ArrayList<Integer>());এটির সাথে অনুরোধ করার সময় সংকলন হয় না, আপনাকে অবশ্যই পদ্ধতিটি সংজ্ঞায়িত করতে হবে static void check(List<? extends Number> numbers) {}। মানচিত্রের সাথে এটি একই তবে আরও বাসা বাঁধে।
অ্যান্ড্রোনিকাস

1
@ স্পোমিসা ঠিক তেমন তালিকার একধরণের Numberপ্যারামিটার এবং আপনাকে এটিকে সমবায় বানানোর জন্য যুক্ত ? extendsকরতে হবে এটি List<? extends Number>একটি প্রকারের প্যারামিটার Mapএবং এর সাথে ? extendscovariance প্রয়োজন।
অ্যান্ড্রোনিকাস

1
ঠিক আছে. যেহেতু আপনি একটি বহু স্তরের ওয়াইল্ডকার্ড (ওরফে "নেস্টেড ওয়াইল্ডকার্ড" ?) এর সমাধান সরবরাহ করেছেন এবং সম্পর্কিত জেএলএস রেফারেন্সের সাথে লিঙ্ক করেছেন, অনুগ্রহ করে।
স্কোমিসা

6

কলটিতে:

compiles(new HashMap<Integer, List<Integer>>());

টি পূর্ণসংখ্যা সাথে মানানসই হয়, তাই যুক্তি ধরনের একটি হল Map<Integer,List<Integer>>। এটি পদ্ধতির ক্ষেত্রে নয় doesntCompile: আর্গুমেন্টের ধরণ Map<Integer, List<? extends Number>>কলটিতে আসল যুক্তি যাই হোক না কেন থাকে ; এবং এটি থেকে বরাদ্দযোগ্য নয় HashMap<Integer, List<Integer>>

হালনাগাদ

ইন doesntCompileপদ্ধতি, কিছুই আপনি ভালো কিছু করতে বাধা দেয়:

static void doesntCompile(Map<Integer, List<? extends Number>> map) {
    map.put(1, new ArrayList<Double>());
}

সুতরাং স্পষ্টতই, এটি একটি HashMap<Integer, List<Integer>>আর্গুমেন্ট হিসাবে গ্রহণ করতে পারে না ।


একটি বৈধ কল কি হতে doesntCompileহবে, তাহলে? সে সম্পর্কে শুধু কৌতূহল।
এক্সট্রিম বাইকার

1
@ এক্সট্রিম বাইকার doesntCompile(new HashMap<Integer, List<? extends Number>>());যেমন কাজ করবে তেমন কাজ করবে doesntCompile(new HashMap<>());
স্কোমিসা

@ এক্সট্রিমবিকার, এমনকি এটি কাজ করবে, মানচিত্র <পূর্ণসংখ্যা, তালিকা <? সংখ্যা প্রসারিত >> মানচিত্র = নতুন হাশম্যাপ <পূর্ণসংখ্যা, তালিকা <? প্রসারিত সংখ্যা >> (); map.put (নাল, নতুন অ্যারেলিস্ট <Integer> ()); doesntCompile (MAP);
মোঙ্কি

"যেটি HashMap<Integer, List<Integer>>থেকে এটি যোগ্য নয়" আপনি কি দয়া করে এটির থেকে কার্যনির্বাহযোগ্য নয় তা বিশদভাবে বর্ণনা করতে পারেন?
দেব নুল

@ দেভনুল আমার উপরের আপডেটটি দেখুন
মরিস পেরি

2

বিক্ষোভের সহজ উদাহরণ। একই উদাহরণ নীচের মত চাক্ষুষ করা যেতে পারে।

static void demo(List<Pair<? extends Number>> lst) {} // doesn't work
static void demo(List<? extends Pair<? extends Number>> lst) {} // works
demo(new ArrayList<Pair<Integer>()); // works
demo(new ArrayList<SubPair<Integer>()); // works for subtype too

public static class Pair<T> {}
public static class SubPair<T> extends Pair<T> {}

List<Pair<? extends Number>> এটি একটি বহু-স্তরের ওয়াইল্ডকার্ডের ধরণ List<? extends Number> মানক ওয়াইল্ডকার্ড প্রকার।

ওয়াইল্ড কার্ডের ধরণের বৈধ কংক্রিট তাত্পর্য List<? extends Number>অন্তর্ভুক্ত Numberএবং Numberএর ক্ষেত্রে যে কোনও উপ- টাইপ রয়েছেList<Pair<? extends Number>> যেমন টাইপ আর্গুমেন্টের একটি ধরণের যুক্তি এবং নিজেই জেনেরিক ধরণের একটি কংক্রিট ইনস্ট্যান্টেশন রয়েছে।

জেনেরিকস অবিস্রষ্ট তাই Pair<? extends Number>ওয়াইল্ড কার্ডের ধরণটি কেবল গ্রহণ করতে পারে Pair<? extends Number>>। অভ্যন্তর প্রকার ? extends Numberইতিমধ্যে সমবায়। সম্প্রদায়কে অনুমতি দেওয়ার জন্য আপনাকে ঘেরের ধরণটি সমবায়িক হিসাবে তৈরি করতে হবে।


এটি কীভাবে <Pair<Integer>>কাজ করে না <Pair<? extends Number>>তবে কাজ করে <T extends Number> <Pair<T>>?
jaco0646

@ jaco0646 আপনি মূলত ওপি হিসাবে একই প্রশ্ন জিজ্ঞাসা করছেন, এবং অ্যান্ড্রোনিকাসের উত্তর গৃহীত হয়েছে। উত্তরটিতে কোড উদাহরণটি দেখুন।
স্কোমিসা

@ স্পোমিসা, হ্যাঁ, আমি বেশ কয়েকটি কারণে একই প্রশ্নটি জিজ্ঞাসা করছি: একটি হ'ল এই উত্তরটি আসলে ওপি-র প্রশ্নের সমাধান করে বলে মনে হচ্ছে না; তবে দুটি হ'ল আমি এই উত্তরটি উপলব্ধি করা সহজ। আমি অ্যান্ড্রোনিকাসের কাছ থেকে উত্তর কোনওভাবেই অনুসরণ করতে পারি না যা আমাকে নেস্টেড বনাম অ-নেস্টেড জেনেরিকগুলি এমনকি Tবনাম বোঝার দিকে পরিচালিত করে ?। সমস্যার একটি অংশ হ'ল অ্যান্ড্রোনিকাস যখন তার ব্যাখ্যাটির গুরুত্বপূর্ণ বিন্দুতে পৌঁছে, তখন তিনি অন্য একটি থ্রেডে পিছিয়ে যান যা কেবলমাত্র তুচ্ছ উদাহরণ ব্যবহার করে। আমি এখানে আরও পরিষ্কার এবং আরও সম্পূর্ণ উত্তর পাওয়ার আশা করছিলাম।
jaco0646

1
@ jaco0646 ঠিক আছে। অ্যাঞ্জেলিকা ল্যাঙ্গারের "জাভা জেনেরিক্স এফএকিউস - টাইপ আর্গুমেন্টস" ডকুমেন্টটিতে মাল্টি-লেভেল (অর্থাত্ নেস্টেড) ওয়াইল্ডকার্ডসের অর্থ কী? । ওপি-র প্রশ্নের উত্থাপিত বিষয়গুলি ব্যাখ্যা করার জন্য এটিই আমার সেরা উত্স। নেস্টেড ওয়াইল্ডকার্ডগুলির নিয়মগুলি সোজাসাপ্টা বা স্বজ্ঞাত নয়।
স্কোমিসা

1

আমি আপনাকে জেনেরিক ওয়াইল্ডকার্ডের ডকুমেন্টেশন বিশেষত ওয়াইল্ডকার্ড ব্যবহারের জন্য নির্দেশিকাগুলি সন্ধান করার পরামর্শ দিচ্ছি

আপনার পদ্ধতিটি স্পষ্টভাবে বলছেন #doesntCompile

static void doesntCompile(Map<Integer, List<? extends Number>> map) {}

এবং কল করুন

doesntCompile(new HashMap<Integer, List<Integer>>());

মূলত ভুল

আসুন আইনী প্রয়োগকরণ যুক্ত করুন:

    static void doesntCompile(Map<Integer, List<? extends Number>> map) {
        List<Double> list = new ArrayList<>();
        list.add(0.);
        map.put(0, list);
    }

এটি সত্যিই ঠিক আছে, কারণ ডাবল সংখ্যা প্রসারিত করে তাই পুট List<Double>একেবারে ঠিক আছে ঠিক তাই List<Integer>না?

তবে, আপনি কি এখনও মনে করেন যে এটি আপনার উদাহরণ থেকে এখানে পাস করা আইনসম্মতnew HashMap<Integer, List<Integer>>() ?

সংকলক এমনটি মনে করে না এবং এ জাতীয় পরিস্থিতি এড়াতে তার (এর?) সেরা চেষ্টা করছেন।

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

    static <T extends Number> void compiles(Map<Integer, List<T>> map) {
        List<Double> list = new ArrayList<>();
        list.add(10.);
        map.put(10, list); // does not compile
    }

মূলত আপনি কিছুই লাগাতে পারেন কিন্তু List<T>কেন এটি নিরাপদ সঙ্গে যে পদ্ধতি কল যে new HashMap<Integer, List<Integer>>()বা new HashMap<Integer, List<Double>>()বা new HashMap<Integer, List<Long>>()বা new HashMap<Integer, List<Number>>()

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

নোট: মরিস পেরি পোস্ট করা উত্তর একেবারে সঠিক। আমি এটি নিশ্চিত যে এটি যথেষ্ট পরিষ্কার, তাই আরও বিস্তৃত পোস্ট যুক্ত করার চেষ্টা করেছি (সত্যিই আশা করি আমি পরিচালিত হয়েছি)।

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