জাভা SafeVarargs টীকা, একটি মান বা সেরা অনুশীলন বিদ্যমান?


175

আমি সম্প্রতি জাভা @SafeVarargsটিকাটি পেরিয়ে এসেছি । জাভাতে বৈকল্পিক ক্রিয়াকলাপ কী করে তার জন্য গুগলিং আমাকে বরং বিভ্রান্ত করে ফেলেছে (হ্যাপ পয়জনানিং? মুছে ফেলা ধরনের?), তাই আমি কয়েকটি বিষয় জানতে চাই:

  1. কোন বৈকল্পিক জাভা ক্রিয়াকলাপটি @SafeVarargsঅর্থে অনিরাপদ করে তোলে (গভীরতার উদাহরণ হিসাবে আকারে ব্যাখ্যা করা যায়)?

  2. কেন এই টিকাটি প্রোগ্রামারের বিবেচনার জন্য রেখে গেল? এই কি কম্পাইলারটি চেক করতে সক্ষম হওয়া উচিত না?

  3. তার কাজটি ভার্জাগুলি নিরাপদ কিনা তা নিশ্চিত করার জন্য কিছু মানক মানতে হবে? যদি তা না হয় তবে এটি নিশ্চিত করার সর্বোত্তম অনুশীলনগুলি কী কী?


1
আপনি জাভাডকে উদাহরণ (এবং ব্যাখ্যা) দেখেছেন ?
jlordo

2
আপনার তৃতীয় প্রশ্নের জন্য, এক অনুশীলন সবসময় একটি প্রথম উপাদান এবং অন্যদের আছে হল: retType myMethod(Arg first, Arg... others)। যদি আপনি নির্দিষ্ট না করেন first, একটি খালি অ্যারে অনুমোদিত, এবং আপনার একই নাম অনুসারে একই পদ্ধতিতে কোনও যুক্তি না নিয়ে খুব ভাল পদ্ধতিতে থাকতে পারে যার অর্থ জেভিএমকে কোন পদ্ধতিটি ডাকা উচিত তা নির্ধারণ করতে বেশ সময় লাগবে।
fge

4
@ জ্লোর্ডো আমি করেছি, তবে আমি বুঝতে পারছি না যে এটির ভার্সের প্রসঙ্গে যেমন কোনও ভারার্গস ফাংশনের বাইরেও সহজেই এই পরিস্থিতিটির প্রতিরূপ তৈরি করতে পারে (এটি যাচাই করা হয়েছে, রানটাইমের প্রত্যাশিত ধরণের সুরক্ষা সতর্কতা এবং ত্রুটিগুলি সংকলন করে) ..
ওরেণ

উত্তর:


244

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

<T> void foo(T... args);

জাভাতে, ভারারাগস একটি সিনট্যাকটিক চিনি যা সংকলন-সময়ে একটি সাধারণ "পুনরায় লেখার" মধ্য দিয়ে যায়: টাইপের একটি ভ্যারাগার্স পরামিতি টাইপের X...একটি প্যারামিটারে রূপান্তরিত হয় X[]; এবং প্রতিবার এই ভারার্গস পদ্ধতিতে যখন কোনও কল করা হয়, কম্পাইলারটি ভারেগেস প্যারামিটারে থাকা সমস্ত "ভেরিয়েবল আর্গুমেন্ট" সংগ্রহ করে এবং ঠিক ঠিক এর মতো একটি অ্যারে তৈরি করেnew X[] { ...(arguments go here)... }

যখন ভারার্গস টাইপটি কংক্রিটের মতো হয় তখন এটি ভালভাবে কাজ করে String...। এটি যখন কোনও টাইপের ভেরিয়েবলের মতো হয় T..., যখন Tসেই কলটির জন্য কংক্রিটের ধরণের হিসাবে পরিচিত হয় এটিও কাজ করে । যেমন যদি পদ্ধতি উপরে একটি বর্গ অংশ ছিল Foo<T>, এবং আপনি একটি আছে Foo<String>রেফারেন্স, তারপর কলিং fooতে এটি কারণ আমরা জানি ঠিক আছে হবে Tহয়String কোডে যে সময়ে।

যাইহোক, "মান" যখন Tঅন্য ধরণের প্যারামিটার হয় তখন এটি কাজ করে না । জাভাতে, টাইপ-প্যারামিটার উপাদান টাইপের ( new T[] { ... }) একটি অ্যারে তৈরি করা অসম্ভব । সুতরাং জাভা এর পরিবর্তে ব্যবহার করে new Object[] { ... }(এখানে Objectউপরের সীমানাটি রয়েছে T; যদি উপরের বাউন্ড কিছু আলাদা থাকে তবে তার পরিবর্তে এটি হবে Object) এবং তারপরে আপনাকে একটি সংকলক সতর্কতা দেয়।

সুতরাং এর new Object[]পরিবর্তে new T[]বা যা কিছু তৈরি করে ভুল ? ওয়েল, জাভাতে অ্যারেগুলি রানটাইমের সময় তাদের উপাদানগুলির ধরনগুলি জানে। সুতরাং, পাস সময়কালে অ্যারে অবজেক্টের রানটাইমে ভুল উপাদান টাইপ থাকবে।

সম্ভবত উপাদানগুলির উপর পুনরাবৃত্তি করার জন্য, ভারার্গগুলির সর্বাধিক সাধারণ ব্যবহারের জন্য, এটি কোনও সমস্যা নয় (আপনি অ্যারের রানটাইম ধরণের বিষয়ে চিন্তা করেন না) তাই এটি নিরাপদ:

@SafeVarargs
final <T> void foo(T... args) {
    for (T x : args) {
        // do stuff with x
    }
}

যাইহোক, পাস করা অ্যারের রানটাইম উপাদান উপাদান ধরণের উপর নির্ভর করে এমন কোনও কিছুর জন্য, এটি নিরাপদ হবে না। এটি অনিরাপদ এবং ক্র্যাশ হওয়া এমন একটি সাধারণ উদাহরণ:

class UnSafeVarargs
{
  static <T> T[] asArray(T... args) {
    return args;
  }

  static <T> T[] arrayOfTwo(T a, T b) {
    return asArray(a, b);
  }

  public static void main(String[] args) {
    String[] bar = arrayOfTwo("hi", "mom");
  }
}

এখানে সমস্যা যে আমরা ধরনের উপর নির্ভর করে argsহতে T[]অর্ডার যেমন আসতে হবে T[]। তবে আসলে রানটাইমের সময় যুক্তির ধরণটি উদাহরণ নয় T[]

3) যদি আপনার পদ্ধতিতে টাইপের একটি আর্গুমেন্ট T...(যেখানে টি কোনও ধরণের প্যারামিটার হয়), তবে:

  • নিরাপদ: যদি আপনার পদ্ধতিটি কেবল অ্যারের উপাদানগুলির উদাহরণগুলির উপর নির্ভর করে T
  • অনিরাপদ: এটি অ্যারের উদাহরণ হিসাবে যদি এটি নির্ভর করে T[]

অ্যারের রানটাইম টাইপের উপর নির্ভর করে এমন জিনিসগুলির মধ্যে রয়েছে: এটিকে টাইপ হিসাবে ফিরিয়ে দেওয়া, এটিকে টাইপের T[]পরামিতি হিসাবে আর্গুমেন্ট হিসাবে পাস করা T[], অ্যারের টাইপটি ব্যবহার করে .getClass()এটিকে রানটাইম টাইপের উপর নির্ভর করে এমন পদ্ধতিতে পাস করা, যেমন List.toArray()এবংArrays.copyOf() ইত্যাদি

2) আমি উপরে বর্ণিত পার্থক্যটি সহজেই স্বয়ংক্রিয়ভাবে আলাদা করা খুব জটিল।


7
ঠিক আছে এখন এটা সব বোঝার। ধন্যবাদ। সুতরাং কেবল দেখতে যে আমি আপনাকে পুরোপুরি বুঝতে পেরেছি, আসুন আমরা বলতে পারি যে একটি ক্লাস রয়েছে FOO<T extends Something>এটির একটি অ্যারে হিসাবে একটি ভার্সেস পদ্ধতির টি [] ফিরিয়ে দেওয়া কি নিরাপদ হবে Somthing?
ওরেেন

30
লক্ষ্য করার মতো বিষয় যে এটির ক্ষেত্রে সম্ভবত (সম্ভবতঃ) ব্যবহার @SafeVarargsকরা সর্বদা সঠিক হয় যখন আপনি অ্যারের সাথে একমাত্র জিনিসটি ইতিমধ্যে টীকাযুক্ত অন্য কোনও পদ্ধতির কাছে পৌঁছে দেন (উদাহরণস্বরূপ: আমি প্রায়শই নিজেকে ভেরাগ পদ্ধতি লিখতে দেখি যে তাদের যুক্তি ব্যবহার করে তালিকায় রূপান্তর করতে Arrays.asList(...)এবং এটি অন্য পদ্ধতিতে পাস করার জন্য উপস্থিত রয়েছে; এ জাতীয় কেসটি সর্বদা এর সাথে টিকা দেওয়া যেতে পারে @SafeVarargsকারণ Arrays.asListএনেটেশন রয়েছে)।
জুলাই

3
@ নিউওয়া্যাক্ট আমি জানি না জাভা in-তে এটি ছিল কিনা, তবে @SafeVarargsপদ্ধতিটি না হওয়া staticবা জাভা 8 অনুমতি দেয় না finalকারণ অন্যথায় এটি কোনও অনিরাপদ সহ কোনও উদ্দীপনাবদ্ধ শ্রেণিতে ওভাররাইড হয়ে যেতে পারে।
অ্যান্ডি

3
এবং জাভা 9 এ এটি এমন privateপদ্ধতির জন্যও অনুমোদিত হবে যা ওভাররাইড করা যায় না।
ডেভ এল।

4

সেরা অনুশীলনের জন্য, এটি বিবেচনা করুন।

আপনার যদি এটি থাকে:

public <T> void doSomething(A a, B b, T... manyTs) {
    // Your code here
}

এটিতে এটি পরিবর্তন করুন:

public <T> void doSomething(A a, B b, T... manyTs) {
    doSomething(a, b, Arrays.asList(manyTs));
}

private <T> void doSomething(A a, B b, List<T> manyTs) {
    // Your code here
}

আমি খুঁজে পেয়েছি যে আমি সাধারণত আমার কলকারীদের আরও সুবিধাজনক করে তুলতে কেবল ভারার্গ যুক্ত করি। এটি ব্যবহার করার জন্য আমার অভ্যন্তরীণ বাস্তবায়নের পক্ষে প্রায় সবসময় আরও সুবিধাজনক হবে List<>। পিগি-ব্যাক অনArrays.asList() এবং নিশ্চিত করে নিন যে আমি হিপ পলিউশন প্রবর্তনের কোনও উপায় নেই, এটি আমি করি।

আমি জানি এটি কেবল আপনার # 3 উত্তর দেয়। নিউঅ্যাক্যাক্ট উপরে # 1 এবং # 2 এর জন্য দুর্দান্ত উত্তর দিয়েছে, এবং এটিকে কেবল একটি মন্তব্য হিসাবে রাখার মতো আমার যথেষ্ট সুনাম নেই। : P: P

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