java - কশন - বাংলায় জাভা pdf




জাভা জেনেরিক টাইপ উদাহরণ তৈরি করুন? (17)

জাভা একটি জেনেরিক টাইপ একটি উদাহরণ তৈরি করা সম্ভব? আমি যা দেখেছি তার উপর ভিত্তি করে চিন্তা করছি আমি উত্তরটি no ( টাইপ মরার কারণে ), কিন্তু কেউ যদি আমার অনুপস্থিত কিছু দেখতে পারে তবে আমি আগ্রহী হব:

class SomeContainer<E>
{
    E createContents()
    {
        return what???
    }
}

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

ইয়ান রবার্টসনের আর্টিমা আর্টিকেল থেকে কেউ নাটকীয়ভাবে ভিন্ন কিছু দেখতে পায় কিনা তা দেখার জন্য আমি কিছুক্ষণের জন্য এই খোলা ছেড়ে দেব।


@ নোহ এর উত্তর একটি imporovement।

পরিবর্তনের কারণ

a] যদি আপনি ক্রমটি পরিবর্তন করেন তবে আরও 1 জেনেরিক টাইপ ব্যবহার করা নিরাপদ।

খ] সময়-সময় একটি শ্রেণী জেনেরিক টাইপ স্বাক্ষর পরিবর্তন যাতে আপনি রানটাইমতে অনির্দিষ্ট ব্যতিক্রমগুলি দ্বারা অবাক হবেন না।

শক্তসমর্থ কোড

public abstract class Clazz<P extends Params, M extends Model> {

    protected M model;

    protected void createModel() {
    Type[] typeArguments = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments();
    for (Type type : typeArguments) {
        if ((type instanceof Class) && (Model.class.isAssignableFrom((Class) type))) {
            try {
                model = ((Class<M>) type).newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

অথবা এক মাছ ধরার নৌকা ব্যবহার করুন

এক লাইন কোড

model = ((Class<M>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[1]).newInstance();

Dunno যদি এটি সাহায্য করে, তবে যখন আপনি সাব্লকাস (বেনামে সহ) একটি জেনেরিক টাইপ করেন, টাইপ তথ্য প্রতিফলন মাধ্যমে উপলব্ধ হয়। যেমন,

public abstract class Foo<E> {

  public E instance;  

  public Foo() throws Exception {
    instance = ((Class)((ParameterizedType)this.getClass().
       getGenericSuperclass()).getActualTypeArguments()[0]).newInstance();
    ...
  }

}

সুতরাং, যখন আপনি Foo সাব্লকাস করবেন, তখন আপনি বারের উদাহরণ পাবেন যেমন,

// notice that this in anonymous subclass of Foo
assert( new Foo<Bar>() {}.instance instanceof Bar );

কিন্তু এটি অনেক কাজ, এবং শুধুমাত্র subclasses জন্য কাজ করে। যদিও সহজ হতে পারে।


আপনি একটি classloader এবং ক্লাসের নাম দিয়ে, অবশেষে কিছু পরামিতি করতে পারেন।

final ClassLoader classLoader = ...
final Class<?> aClass = classLoader.loadClass("java.lang.Integer");
final Constructor<?> constructor = aClass.getConstructor(int.class);
final Object o = constructor.newInstance(123);
System.out.println("o = " + o);

আপনি এখন এটি করতে পারেন এবং এটি প্রতিফলন কোড একটি গুচ্ছ প্রয়োজন হয় না।

import com.google.common.reflect.TypeToken;

public class Q26289147
{
    public static void main(final String[] args) throws IllegalAccessException, InstantiationException
    {
        final StrawManParameterizedClass<String> smpc = new StrawManParameterizedClass<String>() {};
        final String string = (String) smpc.type.getRawType().newInstance();
        System.out.format("string = \"%s\"",string);
    }

    static abstract class StrawManParameterizedClass<T>
    {
        final TypeToken<T> type = new TypeToken<T>(getClass()) {};
    }
}

অবশ্যই আপনাকে যদি কনস্ট্রাকটরকে কল করতে হয় তবে কিছু প্রতিফলন দরকার, তবে এটি খুব ভালভাবে নথিভুক্ত করা, এই কৌশলটি নয়!

TypeToken এর জন্য এখানে জাভাডোক


আপনি বলেন, আপনি টাইপ erasure কারণে সত্যিই এটি করতে পারেন না। আপনি প্রতিফলন ব্যবহার করে এটি করতে পারেন, কিন্তু এটি অনেক কোড এবং ত্রুটি হ্যান্ডলিং অনেক প্রয়োজন।


আপনি যদি new E() অর্থ new E() তবে এটি অসম্ভব। এবং আমি যোগ করব যে এটি সর্বদা সঠিক নয় - যদি আপনি সর্বজনীন কোন-আর্গস কন্সট্রাকটর থাকে তবে কীভাবে জানেন? কিন্তু আপনি কোনও বর্গ তৈরি করতে জানেন এমন কোনও শ্রেণিতে সৃষ্টি করতে পারেন - এটি Class<E> বা আপনার কাস্টম কোড হতে পারে

interface Factory<E>{
    E create();
}    

class IntegerFactory implements Factory<Integer>{    
  private static int i = 0; 
  Integer create() {        
    return i++;    
  }
}

আপনি সঠিক. আপনি new E() করতে পারবেন না। কিন্তু আপনি এটি পরিবর্তন করতে পারেন

private static class SomeContainer<E> {
    E createContents(Class<E> clazz) {
        return clazz.newInstance();
    }
}

এটি একটি ব্যথা। কিন্তু এটি কাজ করে. কারখানা প্যাটার্ন এটি মোড়ানো এটি একটু বেশি সহনশীল করে তোলে।


আমি ভেবেছিলাম আমি এটা করতে পারব, কিন্তু বেশ হতাশ ছিল: এটা কাজ করে না, কিন্তু আমি মনে করি এটি ভাগ করে নেওয়া এখনও মূল্যবান।

হয়তো কেউ সঠিক করতে পারেন:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

interface SomeContainer<E> {
    E createContents();
}

public class Main {

    @SuppressWarnings("unchecked")
    public static <E> SomeContainer<E> createSomeContainer() {
        return (SomeContainer<E>) Proxy.newProxyInstance(Main.class.getClassLoader(),
                new Class[]{ SomeContainer.class }, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Class<?> returnType = method.getReturnType();
                return returnType.newInstance();
            }
        });
    }

    public static void main(String[] args) {
        SomeContainer<String> container = createSomeContainer();

    [*] System.out.println("String created: [" +container.createContents()+"]");

    }
}

এটি উৎপন্ন করে:

Exception in thread "main" java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.String
    at Main.main(Main.java:26)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

লাইন 26 [*] সাথে এক।

একমাত্র কার্যকর সমাধান হল @ জাস্টিনউড


এই সাহায্য করতে খুব দেরী না আশা করি !!!

জাভা টাইপ-নিরাপত্তা, শুধুমাত্র বস্তু উদাহরণ তৈরি করতে সক্ষম।

আমার ক্ষেত্রে আমি createContents করতে প্যারামিটার পাস করতে পারছি না। আমার সমাধান সব bellow উত্তর পরিবর্তে প্রসারিত ব্যবহার করা হয়।

private static class SomeContainer<E extends Object> {
    E e;
    E createContents() throws Exception{
        return (E) e.getClass().getDeclaredConstructor().newInstance();
    }
}

এই আমার উদাহরণ ক্ষেত্রে যা আমি পরামিতি পাস করতে পারবেন না।

public class SomeContainer<E extends Object> {
    E object;

    void resetObject throws Exception{
        object = (E) object.getClass().getDeclaredConstructor().newInstance();
    }
}

প্রতিফলন ব্যবহার করে রান টাইম ত্রুটি তৈরি করুন, যদি আপনি কোনও বস্তুর ধরন সহ আপনার জেনেরিক ক্লাস প্রসারিত করেন। অবজেক্টের জন্য আপনার জেনেরিক টাইপ প্রসারিত করতে সময় ত্রুটি সংকলন করার জন্য এই ত্রুটিটি রূপান্তর করুন।


এখানে TypeTools প্রতিনিধিত্বকারী কাঁচা শ্রেণির সমাধান করতে TypeTools ব্যবহার করে TypeTools প্রয়োগ করা হয়েছে:

E createContents() throws Exception {
  return TypeTools.resolveRawArgument(SomeContainer.class, getClass()).newInstance();
}

এই পদ্ধতিটি কেবল তখনই কাজ করে যখন কিছু SomeContainer হয় তাই E এর প্রকৃত মান একটি টাইপ সংজ্ঞাতে ধরা হয়:

class SomeStringContainer extends SomeContainer<String>

অন্যথায় ই এর মান রানটাইম এ মুছে ফেলা হয় এবং পুনরুদ্ধারযোগ্য নয়।


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

public static class Container<E> {
    private Class<E> clazz;

    public Container(Class<E> clazz) {
        this.clazz = clazz;
    }

    public E createContents() throws Exception {
        return clazz.newInstance();
    }
}

সম্পাদনা করুন: বিকল্পভাবে আপনি এই কন্সট্রাকটরটি ব্যবহার করতে পারেন (তবে এটি একটি উদাহরণ প্রয়োজন):

@SuppressWarnings("unchecked")
public Container(E instance) {
    this.clazz = (Class<E>) instance.getClass();
}

জাভা 8 এ আপনি Supplier কার্যকরী ইন্টারফেসটি এই সুন্দরভাবে অর্জন করতে ব্যবহার করতে পারেন:

class SomeContainer<E> {
  private Supplier<E> supplier;

  SomeContainer(Supplier<E> supplier) {
    this.supplier = supplier;
  }

  E createContents() {
    return supplier.get();
  }
}

আপনি এই শ্রেণীর মত এই নির্মাণ করবে:

SomeContainer<String> stringContainer = new SomeContainer<>(String::new);

সিনট্যাক্স String::new যে লাইন String::new একটি কনস্ট্রাকটর রেফারেন্স

যদি আপনার কনস্ট্রাক্টর আর্গুমেন্টগুলি নেয় তবে আপনি তার পরিবর্তে একটি ল্যাম্বা এক্সপ্রেশন ব্যবহার করতে পারেন:

SomeContainer<BigInteger> bigIntegerContainer
    = new SomeContainer<>(() -> new BigInteger(1));

তুমি ব্যবহার করতে পার:

Class.forName(String).getConstructor(arguments types).newInstance(arguments)

তবে আপনাকে প্যাকেজের সমেত সঠিক শ্রেণী নাম সরবরাহ করতে হবে, যেমন। java.io.FileInputStream । আমি একটি গণিত এক্সপ্রেশন পাসার তৈরি করতে এই ব্যবহার।


যখন আপনি কম্পাইল সময়তে E এর সাথে কাজ করেন তখন আপনি প্রকৃত জেনারিক টাইপ "E" (আসলে আপনি জেনেরিক টাইপের বেস ক্লাসের সাথে প্রতিফলন বা কাজটি ব্যবহার করেন) যত্ন করেন না। সুতরাং উপশ্রেণীটি E এর উদাহরণ প্রদান করে।

Abstract class SomeContainer<E>
{

    abstract protected  E createContents();
    public doWork(){
        E obj = createContents();
        // Do the work with E 

     }
}


**BlackContainer extends** SomeContainer<Black>{
    Black createContents() {
        return new  Black();
    }
}

রবার্টসন নিবন্ধটির আলোচনার মতো কৌশলগুলি ব্যবহার করে আপনার জন্য E সমাধান করতে পারে এমন বিভিন্ন লাইব্রেরি রয়েছে। এখানে TypeTools প্রতিনিধিত্বকারী কাঁচা শ্রেণির সমাধান করতে TypeTools ব্যবহার করে TypeTools এর একটি প্রয়োগ করা হয়েছে:

E createContents() throws Exception {
  return TypeTools.resolveRawArgument(SomeContainer.class, getClass()).newInstance();
}

এটি অনুমান করে যে GetClass () SomeContainer এর একটি উপশ্রেণীতে সমাধান করে এবং অন্যথায় ব্যর্থ হ'ল যেহেতু E এর প্রকৃত প্যারামিটারাইজড মানটি উপ-ক্লাসে ধরা না থাকলে রানটাইম এ মুছে ফেলা হবে।


জাভা টিউটোরিয়াল থেকে - জেনেরিকস উপর নিষেধাজ্ঞা :

টাইপ পরামিতি এর উদাহরণ তৈরি করতে পারবেন না

আপনি একটি টাইপ পরামিতি একটি উদাহরণ তৈরি করতে পারবেন না। উদাহরণস্বরূপ, নিম্নলিখিত কোডটি কম্পাইল-টাইম ত্রুটি সৃষ্টি করে:

public static <E> void append(List<E> list) {
    E elem = new E();  // compile-time error
    list.add(elem);
}

একটি কার্যকারিতা হিসাবে, আপনি প্রতিফলন মাধ্যমে একটি টাইপ পরামিতি একটি বস্তু তৈরি করতে পারেন:

public static <E> void append(List<E> list, Class<E> cls) throws Exception {
    E elem = cls.newInstance();   // OK
    list.add(elem);
}

আপনি এপেন্ড পদ্ধতিটি নিম্নরূপ ব্যবহার করতে পারেন:

List<String> ls = new ArrayList<>();
append(ls, String.class);

return   (E)((Class)((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]).newInstance();






generics