সুরক্ষা প্রকার: চেক না করা castালাই


264

আমার বসন্তের অ্যাপ্লিকেশন প্রসঙ্গে ফাইলটিতে আমার মতো কিছু রয়েছে:

<util:map id="someMap" map-class="java.util.HashMap" key-type="java.lang.String" value-type="java.lang.String">
    <entry key="some_key" value="some value" />
    <entry key="some_key_2" value="some value" />   
</util:map>

জাভা শ্রেণিতে, বাস্তবায়নটি দেখে মনে হচ্ছে:

private Map<String, String> someMap = new HashMap<String, String>();
someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");

ইক্লিপসে, আমি একটি সতর্কতা দেখছি যা বলছে:

সুরক্ষা প্রকার: অবজেক্ট থেকে হ্যাশম্যাপে চেক করা কাস্ট

আমি কি ভুল করছি? আমি কীভাবে সমস্যাটি সমাধান করব?


আমি বাস্তবে প্যারামিটারাইজড হ্যাশম্যাপে কাস্টটি পরীক্ষা করার জন্য একটি রুটিন নিয়ে এসেছি, যা চেক না করা castালাইয়ের সতর্কতা দূর করে: লিঙ্কটি আমি বলব এটি "সঠিক" সমাধান, তবে এর মূল্য এটি বিতর্কযোগ্য হতে পারে কি না। :)
skiphoppy


উত্তর:


248

ঠিক আছে, সবার আগে, আপনি নতুন HashMapতৈরির কল দিয়ে স্মৃতি নষ্ট করছেন । আপনার দ্বিতীয় লাইনটি এই তৈরি করা হ্যাশম্যাপটির রেফারেন্সটিকে পুরোপুরি উপেক্ষা করে এটি আবর্জনা সংগ্রহকারীকে উপলভ্য করে। সুতরাং, এটি করবেন না, ব্যবহার করুন:

private Map<String, String> someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");

দ্বিতীয়ত, সংকলকটি অভিযোগ করছে যে আপনি বস্তুটি HashMapএটি কিনা তা যাচাই না করেই একটিটিতে ফেলে দেন HashMap। তবে, আপনি করতে থাকলেও:

if(getApplicationContext().getBean("someMap") instanceof HashMap) {
    private Map<String, String> someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");
}

আপনি সম্ভবত এখনও এই সতর্কতা পেতে হবে। সমস্যাটি রয়েছে, getBeanফিরে আসে Object, সুতরাং এটি কী তা কী তা অজানা। এটিকে HashMapসরাসরি রূপান্তরকরণের ফলে দ্বিতীয় কেসটি সমস্যা তৈরি করবে না (এবং সম্ভবত প্রথম ক্ষেত্রে কোনও সতর্কতা উপস্থিত হবে না, আমি নিশ্চিত নই যে জাভা সংকলক জাভা 5 এর সতর্কতার সাথে কতটা প্যাডেন্টিক)। তবে আপনি এটিকে রূপান্তর করছেন HashMap<String, String>

হ্যাশম্যাপস হ'ল মানচিত্র যা কোনও বিষয়টিকে কী হিসাবে গ্রহণ করে এবং মান হিসাবে একটি বস্তু HashMap<Object, Object>থাকে , যদি আপনি চান। সুতরাং, এর কোনও গ্যারান্টি নেই যে আপনি যখন আপনার শিমটি পান এটি এটি হিসাবে উপস্থাপিত HashMap<String, String>হতে পারে HashMap<Date, Calendar>কারণ যে নন-জেনেরিক উপস্থাপনা ফিরে আসে তাতে কোনও বস্তু থাকতে পারে।

যদি কোডটি সংকলন করে এবং আপনি String value = map.get("thisString");কোনও ত্রুটি ছাড়াই কার্যকর করতে পারেন তবে এই সতর্কতাটি সম্পর্কে চিন্তা করবেন না। তবে মানচিত্রটি স্ট্রিংয়ের মানগুলির সাথে স্ট্রিং কীগুলি সম্পূর্ণরূপে না থাকলে আপনি ClassCastExceptionরানটাইম এ পেয়ে যাবেন , কারণ জেনারিকরা এ ক্ষেত্রে ঘটতে বাধা দিতে পারে না।


12
এটি কিছুক্ষণ আগে ছিল, তবে আমি কাস্টের আগে একটি সেট <কাস্টমক্লাস> পরীক্ষা করার টাইপের উত্তর খুঁজছিলাম, এবং আপনি প্যারামাইট্রাইজড জেনেরিকের উদাহরণ দিতে পারবেন না। উদাহরণস্বরূপ যদি (ইভেন্ট.টেটরেট উদাহরণস্বরূপ <কাস্টমক্লাস> সেট করুন) আপনি কেবল একটি দিয়ে জেনেরিক চেক টাইপ করতে পারেন? এবং এটি castালাইয়ের সতর্কতা সরাবে না। উদাহরণস্বরূপ যদি (ইভেন্ট.জেটরেট উদাহরণস্বরূপ <?>) সেট করুন
রসিকান

314

সমস্যা করে এমন একটি Cast হল একটি রানটাইম চেক - কিন্তু টাইপ ইরেজিওর কারণে রানটাইম সেখানে আসলে একটি মধ্যে কোন পার্থক্য HashMap<String,String>এবং HashMap<Foo,Bar>অন্য কোন জন্য Fooএবং Bar

@SuppressWarnings("unchecked")আপনার নাকটি ব্যবহার করুন এবং ধরে রাখুন। ওহ, এবং জাভাতে সংশোধিত জেনেরিকের জন্য প্রচার করুন :)


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

12
যথাযথভাবে। আপনি যদি টাইপ চেকিংয়ে জোর দিয়ে থাকেন, তবে এটি কেবলমাত্র হ্যাশম্যাপ <?,?> দিয়েই করা যেতে পারে এবং এটি সতর্কতাটি মুছে ফেলবে না কারণ জেনেরিক প্রকারগুলি পরীক্ষা না করে টাইপ না করে। এটি বিশ্বের শেষ নয়, তবে বিরক্তিকর যে আপনি কোনও সতর্কতা দমন করতে বা এর সাথে জীবনযাপন করতে গিয়ে ধরা দিয়েছেন।
রসিকান

5
@ জোনস্কিট একটি সংশোধিত জেনেরিক কি?
সাসকিউ

89

উপরের বার্তাগুলি ইঙ্গিত হিসাবে, তালিকাটি একটি List<Object>এবং একটি List<String>বা এর মধ্যে পার্থক্য করা যায় না List<Integer>

আমি একই ত্রুটির জন্য এই ত্রুটি বার্তাটি সমাধান করেছি:

List<String> strList = (List<String>) someFunction();
String s = strList.get(0);

নিম্নলিখিত সহ:

List<?> strList = (List<?>) someFunction();
String s = (String) strList.get(0);

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


3
আপনি ঠিক আমার বন্ধু। তালিকাটি ingালাইয়ের পরিবর্তে, কেবল এটি পুনরাবৃত্তি করুন এবং প্রতিটি উপাদান কাস্ট করুন, সতর্কতা উপস্থিত হবে না, দুর্দান্ত।
জুয়ান ইসাজা

2
এটি সতর্কবার্তাটি সরিয়ে ফেলেছে তবুও আমি আত্মবিশ্বাসী নই: পি
মুমাইর

1
হ্যাঁ সংকলকটিকে চোখের পাতায় ফেলার মতো মনে হচ্ছে তবে রানটাইম নয়: ডি তাই আমি এই এবং @ সাপ্লাইস ওয়ার্নিংস ("চেক না করা")
ছন্নী

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

30

একটি সতর্কতা ঠিক যে। একটি সতর্কতা. কখনও কখনও সতর্কতাগুলি অপ্রাসঙ্গিক হয়, কখনও কখনও তা হয় না। তারা আপনার মনোযোগকে এমন কোনও দিকে কল করতে ব্যবহৃত হয়েছিল যা সংকলকটি মনে করে যে কোনও সমস্যা হতে পারে, তবে তা হতে পারে না।

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

@SuppressWarnings (value="unchecked")

14
-1: কোনও সতর্কতা কখনই গ্রহণ করা উচিত নয়। অথবা এই ধরণের সতর্কতাগুলি দমন করুন বা এটি ঠিক করুন। এমন মুহূর্তটি আসবে যেখানে আপনাকে অনেক সতর্কতা করতে হবে এবং আপনি একবার প্রাসঙ্গিক দেখতে পাবেন না।
ইজদাউজেন

10
প্যারামিটারাইজড জেনেরিকগুলি অর্থাৎ মানচিত্র কাস্ট করার সময় আপনি ক্লাস কাস্ট সতর্কতাগুলি সত্যই এড়াতে পারবেন না, সুতরাং এটি মূল প্রশ্নের সেরা উত্তর।
মাটনউপ

9

আপনি এই বার্তাটি পাচ্ছেন কারণ getBean একটি অবজেক্ট রেফারেন্স প্রদান করে এবং আপনি এটি সঠিক ধরণে কাস্ট করছেন। জাভা 1.5 আপনাকে একটি সতর্কতা দেয়। জাভা 1.5 ব্যবহার করার প্রকৃতি বা এর মতো কাজ করে এমন কোডের সাথে আরও ভাল। স্প্রিংয়ের টাইপসেফ সংস্করণ রয়েছে

someMap=getApplicationContext().getBean<HashMap<String, String>>("someMap");

তার করণীয় তালিকায়।


6

আপনি যদি সত্যই সতর্কতা থেকে মুক্তি পেতে চান, তবে একটি জিনিস আপনি যা করতে পারেন তা হল একটি বর্গ তৈরি করা যা জেনেরিক ক্লাস থেকে প্রসারিত।

উদাহরণস্বরূপ, যদি আপনি ব্যবহার করার চেষ্টা করছেন

private Map<String, String> someMap = new HashMap<String, String>();

আপনি যেমন একটি নতুন ক্লাস তৈরি করতে পারেন

public class StringMap extends HashMap<String, String>()
{
    // Override constructors
}

তারপরে আপনি যখন ব্যবহার করবেন

someMap = (StringMap) getApplicationContext().getBean("someMap");

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


3

চেক না করা সতর্কতা এড়ানোর সমাধান:

class MyMap extends HashMap<String, String> {};
someMap = (MyMap)getApplicationContext().getBean("someMap");

হ্যাকের মতো দেখে মনে হচ্ছে সমাধান নয়।
মালভিন্দর সিং

1
{: - serializable বর্গ MyMap দীর্ঘ ধরনের একটি স্ট্যাটিক চূড়ান্ত serialVersionUID ক্ষেত্র জানায় না
ভবিষ্য

1

আরেকটি সমাধান, যদি আপনি নিজেকে একই জিনিসটি প্রচুর পরিমাণে কাস্ট করে দেখেন এবং আপনি নিজের কোডটি লিটারে ফেলতে না চান @SupressWarnings("unchecked")তবে তা টীকা সহ একটি পদ্ধতি তৈরি করা হবে। এইভাবে আপনি কাস্টটিকে কেন্দ্রিয় করছেন, এবং আশা করছি ত্রুটির সম্ভাবনা হ্রাস করবেন।

@SuppressWarnings("unchecked")
public static List<String> getFooStrings(Map<String, List<String>> ctx) {
    return (List<String>) ctx.get("foos");
}

1

কোডের নীচে ধরণের সুরক্ষা সতর্কতা দেখা দেয়

Map<String, Object> myInput = (Map<String, Object>) myRequest.get();

কার্যসংক্রান্ত

পরামিতিগুলির উল্লেখ না করেই একটি নতুন মানচিত্র অবজেক্ট তৈরি করুন কারণ তালিকার মধ্যে রাখা বস্তুর ধরণের যাচাই করা হয়নি।

পদক্ষেপ 1: একটি নতুন অস্থায়ী মানচিত্র তৈরি করুন

Map<?, ?> tempMap = (Map<?, ?>) myRequest.get();

পদক্ষেপ 2: মূল মানচিত্রটি ইনস্ট্যান্ট করুন

Map<String, Object> myInput=new HashMap<>(myInputObj.size());

পদক্ষেপ 3: অস্থায়ী মানচিত্রটি চিহ্নিত করুন এবং মানচিত্রে মানচিত্রটি সেট করুন

 for(Map.Entry<?, ?> entry :myInputObj.entrySet()){
        myInput.put((String)entry.getKey(),entry.getValue()); 
    }

0

আমি কি ভুল করছি? আমি কীভাবে সমস্যাটি সমাধান করব?

এখানে :

Map<String,String> someMap = (Map<String,String>)getApplicationContext().getBean("someMap");

আপনি যে কোনও উত্তরাধিকার পদ্ধতি ব্যবহার করেন যা আমরা সাধারণত যেটি ব্যবহার করতে চাই না তা যেহেতু ফিরে আসে Object:

Object getBean(String name) throws BeansException;

শিমের কারখানা থেকে একটি বিন (সিঙ্গলটনের জন্য) / তৈরি (প্রোটোটাইপের জন্য) আনার পক্ষে পদ্ধতিটি হ'ল:

<T> T getBean(String name, Class<T> requiredType) throws BeansException;

এটি ব্যবহার করে যেমন:

Map<String,String> someMap = app.getBean(Map.class,"someMap");

সংকলন করবে কিন্তু তবুও একটি চেক না করা রূপান্তর সতর্কতা সহ যেহেতু সমস্ত Mapবস্তু অগত্যা নয়Map<String, String> অবজেক্ট নয়।

কিন্তু <T> T getBean(String name, Class<T> requiredType) throws BeansException; সংগ্রহে ধরন এবং তার জেনেরিক প্রকার (গুলি): যেহেতু যে প্যারামিটার হিসাবে একটির বেশি বর্গ নির্দিষ্ট করার প্রয়োজন যেমন জেনেরিক সংগ্রহের যেমন শিম জেনেরিক ক্লাসের যথেষ্ট নয়।

এই ধরণের দৃশ্যে এবং সাধারণভাবে, সরাসরি ব্যবহার না করাই একটি ভাল পন্থা BeanFactory পদ্ধতি নয় তবে কাঠামোটি শিমকে ইনজেক্ট করার সুযোগ দেয়।

শিমের ঘোষণা:

@Configuration
public class MyConfiguration{

    @Bean
    public Map<String, String> someMap() {
        Map<String, String> someMap = new HashMap();
        someMap.put("some_key", "some value");
        someMap.put("some_key_2", "some value");
        return someMap;
    }
}

শিম ইনজেকশন:

@Autowired
@Qualifier("someMap")
Map<String, String> someMap;
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.