কীভাবে তালিকাটি তালিকার জন্য << বিষয়> << MyClass> castালাই করবেন


104

এটি সংকলন করে না, কোনও পরামর্শ প্রশংসা করেছে।

 ...
  List<Object> list = getList();
  return (List<Customer>) list;

সংকলক বলেছেন: কাস্ট List<Object>করতে পারবেন নাList<Customer>

উত্তর:


160

আপনি সর্বদা অবজেক্টে আপ-কাস্টিং করে যে কোনও অবজেক্টকে সর্বদা কাস্ট করতে পারেন। আপনার ক্ষেত্রে:

(List<Customer>)(Object)list; 

আপনাকে অবশ্যই নিশ্চিত হতে হবে যে রানটাইমের সময় তালিকায় গ্রাহক সামগ্রী ছাড়া কিছুই নেই nothing

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


8
এটিও দরকার @SuppressWarnings("unchecked")। নোট করুন যে আপনি (List)পরিবর্তে পরিবর্তে আপকাস্ট করতে পারেন (Object)
200_সুকেস

37

কারণ গ্রাহক একটি অবজেক্ট হলেও গ্রাহকদের একটি তালিকা বস্তুর তালিকা নয় । যদি তা হয় তবে গ্রাহকদের তালিকায় আপনি কোনও বস্তু রাখতে পারেন ।


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

4
আপনার প্রয়োজনের জন্য @ ব্রেনস্লাগস 83 (তালিকা <গ্রাহক>) (অবজেক্ট) তালিকার জন্য;
মুঠু গণপতি নাথন

@ লাসেভি.কার্লসেন আমি কাস্টিংয়ের কথা বলছি না, আমি রূপান্তর করার কথা বলছি। এটি কোনও ধরণের সুরক্ষা ঘটাবে না, এটি এটি প্রয়োগ করবে। জাভা জেনেরিক প্রয়োগ, অপারেটর ওভারলোডের অভাব, এক্সটেনশান পদ্ধতি এবং আরও অনেক আধুনিক সুযোগ সুবিধাগুলি আমাকে চূড়ান্তভাবে হতাশ করেছে। - ইতিমধ্যে .NET এর জন্য পৃথক দুটি এক্সটেনশন পদ্ধতি রয়েছে - একটি কল .Cast<T>()এবং একটি কল .OfType<T>()। পূর্ববর্তী প্রতিটি উপাদানটিতে একটি কাস্ট সম্পাদন করে (পছন্দসই ব্যতিক্রমগুলি ছুঁড়ে ফেলে) যখন পরবর্তীকৃত উপাদানগুলি কাস্ট করা যায় না তা ফিল্টার করে (যাতে আপনি আপনার ব্যবহারের দৃশ্যের উপর নির্ভর করে কোনওটিকে বেছে নিতে পারেন)।
ব্রেইনস্লাগস

4
@ ইগা_এসটিউডেন্ট আমি জাভাকে অতীতে রাখব না যে এটি আসলে কাজ করতে পারে (এই সমস্ত হাস্যকর ধরণের মুছে ফেলার ব্যবসাটি আমাকে চেষ্টা করে দেখতে হবে ...) - তবে না, আমি কখনও কোডটি লিখব না - আপনি হেরে গেছেন সুরক্ষা টাইপ করুন, সংগ্রহের একটি উপাদান instanceofগ্রাহক না হলে কী হবে ?
ব্রেইনস্লাগস

4
@ BrainSlugs83 যে ব্যক্তি প্রশ্নটি জিজ্ঞাসা করেছিল সে সম্পর্কে কাস্টিংয়ের বিষয়ে বিশেষভাবে জিজ্ঞাসা করা হয়েছে এবং যদি জাভাতে ইতিমধ্যে আপনার সম্পর্কিত NET পদ্ধতিগুলির মতো প্রাসঙ্গিক পদ্ধতি না থাকে (যা এখনও বিটিডব্লিউ রূপান্তর করে না) তবে সহজেই সেগুলি যুক্ত করতে সক্ষম হওয়া উচিত। এটি হ'ল প্রশ্নটির সমস্ত দর্শনীয় অর্থোগোনাল, যা নির্দিষ্ট বাক্য গঠন সম্পর্কে জিজ্ঞাসা করেছিল।
ল্যাসে ভি কার্লসেন

34

আপনার অন্যান্য কোডের উপর নির্ভর করে সেরা উত্তরটি ভিন্ন হতে পারে। চেষ্টা করুন:

List<? extends Object> list = getList();
return (List<Customer>) list;

বা

List list = getList();
return (List<Customer>) list;

তবে মনে রাখবেন এ জাতীয় চেক করা ক্যাসেটগুলি করার পরামর্শ দেওয়া হয় না।


4
-1 - এটি প্রবেশ করা সত্যিই একটি খারাপ অভ্যাস এবং যদি আপনি "চেক না করা"
টিকাটি

26

জাভা 8 স্ট্রিম সহ :

কখনও কখনও নিষ্ঠুর বল castালাই ঠিক আছে:

List<MyClass> mythings = (List<MyClass>) (Object) objects

তবে এখানে আরও বহুমুখী সমাধান রয়েছে:

List<Object> objects = Arrays.asList("String1", "String2");

List<String> strings = objects.stream()
                       .map(element->(String) element)
                       .collect(Collectors.toList());

এক টন সুবিধাগুলি রয়েছে তবে একটি হ'ল আপনি যদি আপনার তালিকাটি আরও মার্জিতভাবে কাস্ট করতে পারেন তবে এটিতে কী রয়েছে তা নিশ্চিত না করতে পারলে:

objects.stream()
    .filter(element->element instanceof String)
    .map(element->(String)element)
    .collect(Collectors.toList());

4
যদিও এটি কাস্টের চেয়ে একটি অনুলিপি বেশি।
200_সুকেস

গৃহীত আনসারে উল্লিখিত কাস্টিং আমার পক্ষে কাজ করে না। এছাড়াও আমি জাভাতে ছিলাম But তবে গুয়ারা FluentIterableআমার পক্ষে কাজ করেছিল।
শ্রীধর সারনোবাত

এটিই আমি খুঁজছিলাম, আমি কেবল বাক্য
গঠনটি


8

মনে রাখবেন যে আমি কোনও জাভা প্রোগ্রামার নই, তবে। নেট এবং সি # তে এই বৈশিষ্ট্যটিকে কন্ট্রভ্যারিয়েন্স বা কোভেরিয়েন্স বলা হয়। আমি এখনও এই জিনিসগুলিতে প্রবেশ করিনি, যেহেতু সেগুলি নেট নেট in.০ এ নতুন, আমি এটি কেবল বিটা যেহেতু ব্যবহার করছি না, তাই আমি জানি না যে দুটি পদগুলির মধ্যে কোনটি আপনার সমস্যার বর্ণনা দেয়, তবে আমাকে বর্ণনা করতে দিন এই সঙ্গে প্রযুক্তিগত সমস্যা।

ধরে নেওয়া যাক আপনাকে কাস্ট করার অনুমতি দেওয়া হয়েছিল। দ্রষ্টব্য, আমি কাস্ট বলি , যেহেতু আপনি যা বলেছিলেন, কিন্তু দুটি ক্রিয়াকলাপ সম্ভব যা কাস্টিং এবং রূপান্তরিত হতে পারে ।

রূপান্তরকরণের অর্থ হ'ল আপনি একটি নতুন তালিকার অবজেক্ট পাবেন তবে আপনি কাস্টিং বলেছেন, যার অর্থ আপনি সাময়িকভাবে একটি অবজেক্টকে অন্য ধরণের হিসাবে বিবেচনা করতে চান।

এখানে যে সমস্যা আছে।

নিম্নলিখিতগুলির অনুমতি দেওয়া হলে কী হবে (দ্রষ্টব্য, আমি ধরে নিচ্ছি যে কাস্টের আগে, বস্তুর তালিকায় আসলে কেবল গ্রাহক বস্তু থাকে, অন্যথায় জাভা এই অনুমানীয় সংস্করণেও কাস্ট কাজ করবে না):

List<Object> list = getList();
List<Customer> customers = (List<Customer>)list;
list.Insert(0, new someOtherObjectNotACustomer());
Customer c = customers[0];

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

জেনারিকস, তবে আপনাকে সংগ্রহের মতো টাইপ-সেফ ডেটা টাইপ দেওয়ার কথা বলেছে এবং যেহেতু তারা 'গ্যারান্টিযুক্ত' শব্দটি চারপাশে ছুঁড়ে ফেলতে পছন্দ করে, এই সমস্যাগুলি অনুসরণ করে এমন সমস্যা সহ, এই ধরণের কাস্টের অনুমতি দেওয়া হয় না।

নেট 4.0 এ (আমি জানি, আপনার প্রশ্ন জাভা সম্পর্কে ছিল), এটি খুব নির্দিষ্ট কিছু ক্ষেত্রে অনুমোদিত হবে , যেখানে সংকলকটি গ্যারান্টি দিতে পারে যে আপনি যে কাজগুলি করেন সেগুলি নিরাপদ, তবে সাধারণ অর্থে এই ধরণের castালাই না অনুমতি দেওয়া। একইভাবে জাভাটির পক্ষে রয়েছে, যদিও আমি জাভা ভাষার সাথে সহযোগিতা এবং বৈপরীত্য প্রবর্তনের কোনও পরিকল্পনা সম্পর্কে অনিশ্চিত।

আশা করি, আমার চেয়ে আরও ভাল জাভা জ্ঞানের কেউ আপনাকে জাভা ভবিষ্যত বা বাস্তবায়নের সুনির্দিষ্ট কথা বলতে পারেন।


4
জাভা ভবিষ্যত ... স্কেলা। সিরিয়াসলি, যে লোকটি জাভাতে জেনেরিকগুলি বোল্ট করেছে সে একটি নতুন ভাষা তৈরি করেছে যা জাভা এর সাথে অস্পষ্টভাবে অনুরূপ তবে প্রকৃতপক্ষে, প্রকারের সাথে সত্যিই দক্ষ: টাইপ হ্যান্ডলিংয়ের একটি খুব পুঙ্খানুপুঙ্খ এবং ধারাবাহিক প্রয়োগ। আমি মনে করি যে স্কালার বৈশিষ্ট্যগুলি কখন জাভাতে ফিরে আসবে এবং কখন তা নির্দিষ্টভাবে কেউ জানে না।
কার্ল স্মট্রিক্জ

সম্প্রদায় সম্পর্কে একটি দুর্দান্ত ব্যাখ্যা যা ওপিএস প্রশ্নের সত্যই উত্তর দেয়। সাবাশ.
কেভিন ডে

কার্ল: আমি ভেবেছিলাম কিছু জাভা ডেভেল সি # তৈরি করতে এগিয়ে গেছে? :) যাই হোক হ্যাঁ, জাভা সম্ভবত ভবিষ্যতে স্কালার দিকে যাচ্ছেন, বলুন, কিছু কম জোরালোভাবে টাইপ করা পরিবর্তে।
ইসকো

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

এর ... প্রযুক্তিগতভাবে এটি সঠিক - তবে নেট নেট 4.0.০ এর আগে - আপনি নিয়মিত আইনিউমারেবল এক্সটেনশন পদ্ধতিগুলি (। কাস্টাল <> এবং .অফটাইপ <>) দিয়ে এটি করতে পারেন - সুতরাং গভীর প্রান্তটি ছাড়ার দরকার নেই যদি আপনি কেবল শক্ত টাইপ পুনরাবৃত্তি চান।
BrainSlugs83

7

আর একটি পদ্ধতিতে জাভা 8 স্ট্রিম ব্যবহার করা হবে।

    List<Customer> customer = myObjects.stream()
                                  .filter(Customer.class::isInstance)
                                  .map(Customer.class::cast)
                                  .collect(toList());

4
ধন্যবাদ, পদ্ধতিটি উল্লেখটি ব্যবহার করে এই সমাধানটি এত সুন্দর
থ্যাং করুন

4
কখনও ভাবিনি যে কেউ এতদূর নেমে যাবে: D
d0x

3

আপনার কেবল তালিকাটি পুনরাবৃত্তি করা উচিত এবং সমস্ত অবজেক্টকে একে একে কাস্ট করা উচিত


3

আপনি এরকম কিছু করতে পারেন

List<Customer> cusList = new ArrayList<Customer>();

for(Object o: list){        
    cusList.add((Customer)o);        
}

return cusList; 

অথবা জাভা 8 উপায়

list.stream().forEach(x->cusList.add((Customer)x))

return cuslist;

2

আপনি পারবেন না কারণ List<Object>এবং List<Customer>একই উত্তরাধিকার গাছে নেই।

তুমি তোমার কাছে নতুন কন্সট্রাকটর যোগ করতে পারিনি List<Customer>বর্গ করে একটি সময় লাগে List<Object>এবং তারপর বারবার তালিকা মাধ্যমে একে ভোটদান Objectএকটি থেকে Customerএবং আপনার সংগ্রহে এটি যোগ। সচেতন হন যে কলারটির List<Object>মধ্যে এমন কিছু নেই যা একটি অবৈধ কাস্ট ব্যতিক্রম ঘটতে পারে Customer

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


2

আপনি একটি নতুন তালিকা তৈরি করতে এবং এতে উপাদান যুক্ত করতে পারেন:

উদাহরণ স্বরূপ:

List<A> a = getListOfA();
List<Object> newList = new ArrayList<>();
newList.addAll(a);

1

আপনার সেরা বাজি হ'ল একটি নতুন তৈরি করা List<Customer>, এর মাধ্যমে পুনরাবৃত্তি করা List<Object>, প্রতিটি আইটেমকে নতুন তালিকায় যুক্ত করা এবং এটি ফিরিয়ে দেওয়া।


1

অন্যরা যেমন উল্লেখ করেছে, আপনি সেগুলি সংরক্ষণের সাথে সংরক্ষণ করতে পারবেন না, যেহেতু এটি একটি List<Object>নয় List<Customer>। আপনি যা করতে পারেন তা হ'ল তালিকার একটি ভিউ সংজ্ঞায়িত করা যা স্থানের ধরণের চেক করে। গুগল সংগ্রহগুলি যেগুলি হবে তা ব্যবহার করে :

return Lists.transform(list, new Function<Object, Customer>() {
  public Customer apply(Object from) {
    if (from instanceof Customer) {
      return (Customer)from;
    }
    return null; // or throw an exception, or do something else that makes sense.
  }
});

1

উপরের বোজোর সাথে একই রকম। এই পদ্ধতির মাধ্যমে আপনি এখানে কিছুটা কাজ করতে পারেন (যদিও আমি নিজে এটি পছন্দ করি না):

public <T> List<T> convert(List list, T t){
    return list;
}

হ্যাঁ. এটি আপনার দাবি করা জেনেরিক প্রকারে আপনার তালিকাটি ফেলে দেবে।

উপরের প্রদত্ত ক্ষেত্রে, আপনি এর মতো কিছু কোড করতে পারেন:

    List<Object> list = getList();
    return convert(list, new Customer());

আমি এই সমাধানটি পছন্দ করি। এমনকি আপনার যদি সাপ্রেস ওয়ার্নিংস যুক্ত করার প্রয়োজন হয় তবে প্রতিটি অনিরাপদ কাস্টিংয়ের চেয়ে এটি এক জায়গায় যুক্ত করা ভাল।
রোবসন

1

আপনি তালিকার সাথে কী করতে চান তার উপর নির্ভর করে আপনার এটি এটিকে কাস্ট করার দরকারও পড়তে পারে না List<Customer>। আপনি যদি কেবলমাত্র Customerতালিকায় অবজেক্টগুলি যুক্ত করতে চান তবে আপনি এটি নীচে ঘোষণা করতে পারেন:

...
List<Object> list = getList();
return (List<? super Customer>) list;

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

অন্যদিকে, আপনি যদি তালিকা থেকে অবজেক্টগুলি পুনরুদ্ধার করতে এবং সেগুলি গ্রাহক হিসাবে দৃ strongly়ভাবে টাইপ করতে চান - তবে আপনার ভাগ্য খুব খারাপ, এবং ঠিক তাই। তালিকাটি যেহেতু List<Object>সামগ্রীগুলির গ্রাহকগণের কোনও গ্যারান্টি নেই তাই আপনাকে পুনরুদ্ধারে নিজের কাস্টিং সরবরাহ করতে হবে। (বা সত্যই, একেবারে দ্বিগুণ নিশ্চিত হন যে তালিকার মধ্যে কেবলমাত্র Customersঅন্য উত্তরগুলির মধ্যে একটি রয়েছে এবং ডাবল কাস্ট ব্যবহার করবে তবে বুঝতে হবে যে আপনি জেনারিকগুলি থেকে প্রাপ্ত কম্পাইল-টাইম টাইপ-সুরক্ষাটি সম্পূর্ণরূপে নষ্ট করছেন) কেস)।

বিস্তৃতভাবে বলতে গেলে কোনও পদ্ধতি লেখার সময় গ্রহণযোগ্য হবে এমন বিস্তৃত সম্ভাব্য জেনেরিক সীমা বিবেচনা করা সর্বদা ভাল, যদি এটি কোনও গ্রন্থাগার পদ্ধতি হিসাবে ব্যবহার করা হয় তবে দ্বিগুণ। আপনি শুধুমাত্র একটি তালিকা থেকে পড়তে যাচ্ছেন করেন, ব্যবহার List<? extends T>পরিবর্তে List<T>, উদাহরণস্বরূপ - আপনার কলারের দেয় অনেক আর্গুমেন্ট এবং মানে তারা সম্ভাবনা কম এক আপনি 'অনুরূপ পরিহার্য সমস্যার সম্মূখীন হয় তারা পাস করতে পারেন আরও সুযোগ এখানে আছে।


0
List<Object[]> testNovedads = crudService.createNativeQuery(
            "SELECT ID_NOVEDAD_PK, OBSERVACIONES, ID_SOLICITUD_PAGO_FK FROM DBSEGUIMIENTO.SC_NOVEDADES WHERE ID_NOVEDAD_PK < 2000");

Convertir<TestNovedad> convertir = new Convertir<TestNovedad>();
Collection<TestNovedad> novedads = convertir.toList(testNovedads, TestNovedad.class);
for (TestNovedad testNovedad : novedads) {
    System.out.println(testNovedad.toString());
}

public Collection<T> toList(List<Object[]> objects, Class<T> type) {
    Gson gson = new Gson();
    JSONObject jsonObject = new JSONObject();
    Collection<T> collection = new ArrayList<>();
    Field[] fields = TestNovedad.class.getDeclaredFields();
    for (Object[] object : objects) {
        int pos = 0;
        for (Field field : fields) {
            jsonObject.put(field.getName(), object[pos++]);
        }
        collection.add(gson.fromJson(jsonObject.toString(), type));
    }
    return collection;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.