"ভারার্গস প্যারামিটারের জন্য টি এর একটি জেনেরিক অ্যারে তৈরি করা হয়েছে" সংকলক সতর্কতাটি সমাধান করা কি সম্ভব?


153

এটি প্রশ্নে কোডের একটি সরল সংস্করণ, একটি জেনেরিক শ্রেণি জেনেরিক ধরণের প্যারামিটার সহ একটি অন্য শ্রেণি ব্যবহার করে এবং জেনেরিক ধরণের একটিকে ভ্যারাগস পরামিতি সহ একটি পদ্ধতিতে পাস করতে হবে:

class Assembler<X, Y> {
    void assemble(X container, Y... args) { ... }
}

class Component<T> {
    void useAssembler(T something) {

        Assembler<String, T> assembler = new Assembler<String, T>();

        //generates warning:
        // Type safety : A generic array of T is
        // created for a varargs parameter
        assembler.assemble("hello", something);
    }

}

এই সতর্কতার মুখোমুখি না হয়ে জেনেরিক প্যারামিটারটি ভ্যারাগস পদ্ধতিতে যাওয়ার কোনও সঠিক উপায় আছে কি?

অবশ্যই কিছু

assembler.assemble("hello", new T[] { something });

আপনি জেনেরিক অ্যারে তৈরি করতে পারবেন না বলে কাজ করে না।


3
এক অদ্ভুত। দেখে মনে হচ্ছে যে সংকলকটি এখানে সম্পূর্ণ ধরণের সুরক্ষার নিশ্চয়তা দিতে সক্ষম হবে।
এরিকসন

3
Angelika ল্যাঙ্গার এর জাভা জেনেরিক্স প্রায়শই জিজ্ঞাসিত প্রশ্নাবলী সম্পর্কিত এন্ট্রি: angelikalanger.com/GenericsFAQ/FAQSections/...
ফ্লো

উত্তর:


88

যোগ করা ছাড়াও @SuppressWarnings("unchecked"), আমি এটি মনে করি না।

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


3
উল্লেখ করতে ভুলে গেছি আমি @ সাপ্রেস ওয়ার্নিংস ("চেক না করা") এড়াতে চেয়েছিলাম। এই বাগ রিপোর্টটি আমাকে একটু আশা দেয়!
ম্যাট বি

3
জোশুয়া ব্লচ যেমন এটি কার্যকর জাভাতে রেখেছেন: "জেনেরিক এবং অ্যারেগুলি মিশ্রিত করবেন না।"
টিমমস

20
তারপরে, ইমপ্লিটালিটি: জেনারিকসের সাথে ভেরার্গস ব্যবহার করবেন না! ঠিক আছে ... অ্যারে থেকে ভারার্গস মানচিত্রের সিদ্ধান্ত এবং সংগ্রহ নয়, জাভা চিরকাল স্থির রাখবে। সুন্দরভাবে কাজ করেছেন মিঃ গোসলিং।
বার্নস্টেইন

57

টম হাটিন একটি মন্তব্যে এটিকে নির্দেশ করেছেন, তবে আরও স্পষ্ট করে বলতে পারেন: হ্যাঁ, আপনি এটি ডিক্লারেশন-সাইটে (সম্ভবত অনেকগুলি) কল সাইটগুলির তুলনায় সমাধান করতে পারেন: জেডিকে to এ স্যুইচ করুন।

আপনি জোসেফ ডার্সির ব্লগ পোস্টে দেখতে পাচ্ছেন , জাভা for এর জন্য কিছু ছোট বর্ধিত ভাষার উন্নতি নির্বাচন করার জন্য প্রকল্প কয়েন অনুশীলন বব লি'র প্রস্তাবটিকে@SuppressWarnings("varargs") পদ্ধতিটির পাশ দিয়ে কিছু করার অনুমতি দেওয়ার জন্য গৃহীত হয়েছিল, যেখানে এই সতর্কবার্তাটি এমন পরিস্থিতিতে সরে গিয়েছিল in নিরাপদ।

এটি এই প্রতিশ্রুতি দিয়ে ওপেনজেডিকে প্রয়োগ করা হয়েছে ।

এটি আপনার প্রকল্পের জন্য দরকারী বা নাও হতে পারে (অনেক লোক জেভিএম-এর একটি প্রাক-রিলিজের অস্থির সংস্করণে স্যুইচ করতে খুশি হবে না!) তবে সম্ভবত এটি হয় - বা সম্ভবত এই প্রশ্নটি পরে খুঁজে পাওয়া যায় (জেডিকে 7 পরে বেরিয়ে যাওয়ার পরে) ) এটি দরকারী খুঁজে পাবেন।


7
উল্লিখিত প্রকল্পের মুদ্রা বৈশিষ্ট্যটি এখন উপলভ্য - জাভা @-তে @SaffeVarargs দেখুন
জর্জ হকিন্স

ববের প্রস্তাবিত বিকল্প ই মোহনীয়।
ক্রিস্টোফার পেরি

জাভা 8 টি @ সাপ্রেস ওয়ার্নিংস ("ভারার্গস") এর পরিবর্তে @ সাফাইবার্গস ব্যবহার করতে দেখা গেছে
পল উইন্টজ

17

আপনি যদি সাবলীল ধরণের ইন্টারফেসের পরে থাকেন তবে আপনি বিল্ডার প্যাটার্নটি চেষ্টা করতে পারেন। ভারার্গসের মতো সংক্ষিপ্ত নয় তবে এটি নিরাপদ।

স্থির জেনারালি-টাইপড পদ্ধতিটি প্রকারটি সুরক্ষা বজায় রেখে, নির্মাতা ব্যবহার করার সময় কিছু বয়লারপ্লেটকে সরিয়ে ফেলতে পারে।

নির্মাতা

public class ArgBuilder<T> implements Iterable<T> {

    private final List<T> args = new ArrayList<T>();

    public ArgBuilder<T> and(T arg) {
        args.add(arg);
        return this;
    }

    @Override
    public Iterator<T> iterator() {
        return args.iterator();
    }

    public static <T> ArgBuilder<T> with(T firstArgument) {
        return new ArgBuilder<T>().and(firstArgument);
    }
}

এটি ব্যবহার করছি

import static com.example.ArgBuilder.*;

public class VarargsTest {

    public static void main(String[] args) {
        doSomething(new ArgBuilder<String>().and("foo").and("bar").and("baz"));
        // or
        doSomething(with("foo").and("bar").and("baz"));
    }

    static void doSomething(Iterable<String> args) {
        for (String arg : args) {
            System.out.println(arg);
        }
    }
}

1
রচনা শক্তি। আমি এটি ভারার্গ্সের চেয়ে অনেক বেশি পছন্দ করি, এটি আরও অভিব্যক্তিপূর্ণ।
ক্রিস্টোফার পেরি

1
ক্রিস্টোফেরপেরি ভালভাবে আপনার কোড কোডটিও বিবেচনা করতে হবে। অন্তর্নিহিত Collection(এই ক্ষেত্রে একটি ArrayList) কলকারীকে বাধ্য করা হয়, যেখানে তারা জানতে পারে যে একটি LinkedListআরও উপযুক্ত, বা নিজেই একটি অপরিবর্তনীয় অ্যারে (যেমন ওপি প্রশ্ন থেকে প্রাপ্ত ওয়ারার্স)। কোনও অ-বিশেষায়িত ব্যবহারের ক্ষেত্রে এটি উপযুক্ত হতে পারে তবে কেবল এটি নির্দেশ করে যে এটি এবং আপনার প্রয়োজন অনুসারে কোডের উপর নির্ভর করে একরকম একটি সীমাবদ্ধতাও রয়েছে।
searchengine27

5

ভারাক পদ্ধতি পদ্ধতিতে অবজেক্টে স্পষ্টভাবে প্যারামিটারগুলি ingালাই @ সাপ্লাইস ওয়ার্নিংস অবলম্বন না করে সংকলকটিকে খুশি করবে।

public static <T> List<T> list( final T... items )
{
    return Arrays.asList( items );
}

// This will produce a warning.
list( "1", 2, new BigDecimal( "3.5" ) )

// This will not produce a warning.
list( (Object) "1", (Object) 2, (Object) new BigDecimal( "3.5" ) )

// This will not produce a warning either. Casting just the first parameter to 
// Object appears to be sufficient.
list( (Object) "1", 2, new BigDecimal( "3.5" ) )

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

এটি আরও ভালভাবে বুঝতে, নীচের তালিকা 2 পদ্ধতির তুলনায় উপরের তালিকা পদ্ধতিতে অনুরোধের সাথে প্রায় খেলুন।

public static List<Object> list2( final Object... items )
{
    return Arrays.asList( items );
}

এটি কাজ করে, উদাহরণস্বরূপ: Iterator <?> It = Arrays.asList ((অবজেক্ট) টি) .iterator; যদি (যদি, hasNext ()) {শ্রেণি = it.next ()। getClass (); unknown উদাহরণস্বরূপ, অজানা প্রকারের অ্যারে থেকে কোনও বস্তুর শ্রেণি বের করা।
ggb667


1

আপনার পদ্ধতিগুলি ওভারলোড হতে পারে। এটি আপনার সমস্যার সমাধান করে না তবে এটি সতর্কতার সংখ্যা হ্রাস করে (এবং হ্যাঁ, এটি হ্যাক!)

class Assembler<X, Y> {
  void assemble(X container, Y a1) { ... }
  void assemble(X container, Y a1, Y a2) { ... }
  void assemble(X container, Y a1, Y a2, Y a3) { ... }
  void assemble(X container, Y a1, Y a2, Y a3, Y a4) { ... }
  void assemble(X container, Y... args) { ... }
}

23
ইডব্ল্যু। এটি হরফের ঠিক ধরণের যা ভারার্গসকে প্রতিরোধ করার কথা রয়েছে।
আমান্ডা এস

1
এটি একটি বৈধ পন্থা হতে পারে, উদাহরণস্বরূপ, পেয়ারা এর ইমট্যুয়েটসেট.ওফটি একবার দেখুন
জোনাথন

1

এটি সমাধান করা খুব সহজ একটি সমস্যা: ব্যবহার করুন List<T>!

রেফারেন্স প্রকারের অ্যারেগুলি এড়ানো উচিত।

জাভার বর্তমান সংস্করণে (1.7), আপনি এমন পদ্ধতি চিহ্নিত করতে পারেন @SafeVargsযা কলার থেকে সতর্কতাটি সরিয়ে দেবে। যদিও এটির সাথে যত্নশীল এবং আপনি উত্তরাধিকার বিন্যাস ছাড়াই এখনও ভাল।

ভারার্গস পদ্ধতিগুলি টেক নোট সহ অ-সংশোধনযোগ্য ফর্মাল পরামিতিগুলি ব্যবহার করার সময় উন্নত সংকলক সতর্কতা এবং ত্রুটিগুলিও দেখুন


6
এটি একটি ভার্সেস প্যারামিটারের সাথে অনিবার্য, তাই না?
ম্যাট বি

4
সতর্কতা দমনটি ব্যবহারের পরিবর্তে ভারার্গস পদ্ধতি ঘোষণায় যাওয়ার অনুমতি দেওয়ার জেডিকে 7-র একটি প্রস্তাব রয়েছে।
টম হাটিন -

11
এটি সম্পূর্ণরূপে লেখকের প্রশ্নের গুরুত্বপূর্ণ বিষয়টিকে উপেক্ষা করে - ভ্যারাগস পরামিতিগুলি একটি অ্যারে তৈরি করে এবং এটি এই সতর্কতা উত্পন্ন করে।
ড্যানিয়েল ইয়ানকোভস্কি

2
আমি @ টম হাটিন - ট্যাকললাইনের সাথে একমত বিশদর জন্য ব্লচ দেখুন << কার্যকর জাভা >> আইটেম 25: অ্যারেতে তালিকা পছন্দ করুন।
স্টান কুরিলিন

2
আমি সাধারণত ব্লোকের সাথে এটির বিষয়ে একমত হই, তবে ভারারাগুলি এই নিয়মের একটি স্পষ্ট ব্যতিক্রম ...
জোয়েরি হেন্ড্রিক্স

0

জেনেরিক টাইপের অ্যারেগুলির সাথে কাজ করার সময়, আমি জেনেরিক ধরণের কোনও রেফারেন্স দিতে বাধ্য হই। এর সাথে, আমি আসলে java.lang.reflect.Array ব্যবহার করে জেনেরিক কোডটি করতে পারি।

http://java.sun.com/javase/6/docs/api/java/lang/reflect/Array.html


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