java কশন জাভা জেনেরিক টাইপ উদাহরণ তৈরি করুন?




বাংলায় জাভা pdf (20)

আপনি যদি তাত্ক্ষণের সময় ক্লাসের নাম দুবার টাইপ করতে না চান তবে:

new SomeContainer<SomeType>(SomeType.class);

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

<E> SomeContainer<E> createContainer(Class<E> class); 

ভালো লেগেছে:

public class Container<E> {

    public static <E> Container<E> create(Class<E> c) {
        return new Container<E>(c);
    }

    Class<E> c;

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

    public E createInstance()
            throws InstantiationException,
            IllegalAccessException {
        return c.newInstance();
    }

}

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

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

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

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


আরো কার্যকরী পদ্ধতির বিষয়ে চিন্তা করুন: কিছু ই তৈরির পরিবর্তে (যা পরিষ্কারভাবে একটি কোড গন্ধ) তৈরি করার পরিবর্তে, কোনও ফাংশনটি কীভাবে তৈরি করা যায় তা জানেন।

E createContents(Callable<E> makeone) {
     return makeone.call(); // most simple case clearly not that useful
}

এখানে একটি উন্নত সমাধান, ParameterizedType.getActualTypeArguments টাইপ.getঅ্যাক্টুয়াল টাইপঅর্গমেন্টের উপর ভিত্তি করে, ইতিমধ্যে @noah, @Lars Bohl, এবং অন্য কিছু উল্লেখ করেছেন।

বাস্তবায়ন প্রথম ছোট উন্নতি। ফ্যাক্টরী উদাহরণ না, কিন্তু একটি টাইপ উচিত। যত তাড়াতাড়ি আপনি Class.newInstance() ব্যবহার করে ইনস্ট্যান্স ফেরত Class.newInstance() আপনি ব্যবহার একটি সুযোগ কমাতে। কারন কোনও আর্গুমেন্ট কনস্ট্রাক্টরকে এভাবে আহ্বান করা যাবে না। একটি ভাল উপায় একটি টাইপ ফেরত দেওয়া, এবং একটি ক্লায়েন্ট চয়ন করতে চান, কোন কনস্ট্রাক্টর তিনি আহ্বান করতে চায়:

public class TypeReference<T> {
  public Class<T> type(){
    try {
      ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
      if (pt.getActualTypeArguments() == null || pt.getActualTypeArguments().length == 0){
        throw new IllegalStateException("Could not define type");
      }
      if (pt.getActualTypeArguments().length != 1){
        throw new IllegalStateException("More than one type has been found");
      }
      Type type = pt.getActualTypeArguments()[0];
      String typeAsString = type.getTypeName();
      return (Class<T>) Class.forName(typeAsString);

    } catch (Exception e){
      throw new IllegalStateException("Could not identify type", e);
    }

  }
}

এখানে একটি ব্যবহার উদাহরণ। @ লারস বোল এক্সটেনশনের মাধ্যমে পুনঃপ্রতিষ্ঠিত জেনেরিক পেতে শুধুমাত্র একটি সাইন ওয়ে দেখিয়েছেন। @noah শুধুমাত্র {} সহ একটি উদাহরণ তৈরি করে। এখানে উভয় ক্ষেত্রে প্রদর্শন করার জন্য পরীক্ষা হয়:

import java.lang.reflect.Constructor;

public class TypeReferenceTest {

  private static final String NAME = "Peter";

  private static class Person{
    final String name;

    Person(String name) {
      this.name = name;
    }
  }

  @Test
  public void erased() {
    TypeReference<Person> p = new TypeReference<>();
    Assert.assertNotNull(p);
    try {
      p.type();
      Assert.fail();
    } catch (Exception e){
      Assert.assertEquals("Could not identify type", e.getMessage());
    }
  }

  @Test
  public void reified() throws Exception {
    TypeReference<Person> p = new TypeReference<Person>(){};
    Assert.assertNotNull(p);
    Assert.assertEquals(Person.class.getName(), p.type().getName());
    Constructor ctor = p.type().getDeclaredConstructor(NAME.getClass());
    Assert.assertNotNull(ctor);
    Person person = (Person) ctor.newInstance(NAME);
    Assert.assertEquals(NAME, person.name);
  }

  static class TypeReferencePerson extends TypeReference<Person>{}

  @Test
  public void reifiedExtenension() throws Exception {
    TypeReference<Person> p = new TypeReferencePerson();
    Assert.assertNotNull(p);
    Assert.assertEquals(Person.class.getName(), p.type().getName());
    Constructor ctor = p.type().getDeclaredConstructor(NAME.getClass());
    Assert.assertNotNull(ctor);
    Person person = (Person) ctor.newInstance(NAME);
    Assert.assertEquals(NAME, person.name);
  }
}

দ্রষ্টব্য: আপনি TypeReference ক্লায়েন্টদের সর্বদা {} ব্যবহার করতে পারেন যখন {} এই বর্গটি বিমূর্ত করে তৈরি করা হয়: public abstract class TypeReference<T> । আমি এটা করেছি, শুধুমাত্র মুছে ফেলা পরীক্ষার ক্ষেত্রে দেখাতে।


আপনি নিম্নলিখিত স্নিপেটটি দিয়ে এটি অর্জন করতে পারেন:

import java.lang.reflect.ParameterizedType;

public class SomeContainer<E> {
   E createContents() throws InstantiationException, IllegalAccessException {
      ParameterizedType genericSuperclass = (ParameterizedType)
         getClass().getGenericSuperclass();
      @SuppressWarnings("unchecked")
      Class<E> clazz = (Class<E>)
         genericSuperclass.getActualTypeArguments()[0];
      return clazz.newInstance();
   }
   public static void main( String[] args ) throws Throwable {
      SomeContainer< Long > scl = new SomeContainer<>();
      Long l = scl.createContents();
      System.out.println( l );
   }
}

আপনি যদি 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++;    
  }
}

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

public final class Foo<T> {

    private Class<T> typeArgumentClass;

    public Foo(Class<T> typeArgumentClass) {

        this.typeArgumentClass = typeArgumentClass;
    }

    public void doSomethingThatRequiresNewT() throws Exception {

        T myNewT = typeArgumentClass.newInstance();
        ...
    }
}

ব্যবহার:

Foo<Bar> barFoo = new Foo<Bar>(Bar.class);
Foo<Etc> etcFoo = new Foo<Etc>(Etc.class);

পেশাদাররা:

  • রবার্টসনের সুপার টাইপ টোকেন (এসটিটি) পদ্ধতির তুলনায় অনেক সহজ (এবং কম সমস্যাযুক্ত)।
  • এসটিটি পদ্ধতির চেয়ে অনেক বেশি কার্যকর (যা ব্রেকফাস্টের জন্য আপনার সেলফোন খাবে)।

কনস:

  • ক্লাসটিকে একটি ডিফল্ট কন্সট্রকটারে পাস করতে পারছেন না (এ কারণে Foo চূড়ান্ত)। আপনি যদি একটি ডিফল্ট কনস্ট্রাক্টারের প্রয়োজন হয় তবে আপনি সর্বদা একটি সেট্টার পদ্ধতি যোগ করতে পারেন তবে তারপরে আপনাকে তার পরে একটি কল দেওয়ার কথা মনে রাখতে হবে।
  • রবার্টসন এর আপত্তি ... একটি কালো ভেড়া চেয়ে আরো বার (যদিও টাইম আর্গুমেন্ট ক্লাসটি আরো একটি সময় নির্দিষ্টভাবে আপনাকে হত্যা করবে না)। এবং রবার্টসনের দাবির বিপরীতে এটি DRY প্রিন্সিপালকে লঙ্ঘন করে না কারণ কম্পাইলারটি সঠিকতা নিশ্চিত করবে।
  • সম্পূর্ণভাবে Foo<L> প্রমাণ নয়। প্রারম্ভিকদের জন্য ... newInstance() টাইপ আর্গুমেন্ট ক্লাসের ডিফল্ট কন্সট্রকটার না থাকলে একটি newInstance() নিক্ষেপ করবে। এই যাই হোক না কেন সব পরিচিত সমাধান প্রয়োগ করা হয়।
  • এসটিটি পদ্ধতির মোট encapsulation অভাব। যদিও একটি বড় চুক্তি (এসটিটি এর অপমানজনক কর্মক্ষমতা ওভারহেড বিবেচনা)।

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

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

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

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();

জাভা দুর্ভাগ্যবশত আপনি কি করতে চান অনুমতি দেয় না। অফিসিয়াল কাজকর্ম দেখুন :

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

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);

যখন আপনি কম্পাইল সময়তে 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();
    }
}

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

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

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


আপনি এক ধরণের বা অন্য কোন ধরণের বিমূর্ত কারখানার জন্য বকেয়া পাস করতে হবে:

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

class SomeContainer<E> {
    private final Factory<E> factory;
    SomeContainer(Factory<E> factory) {
        this.factory = factory;
    }
    E createContents() {
        return factory.create();
    }
}

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


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

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

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 [*] সাথে এক।

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


@ নোহ এর উত্তর একটি 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();

package org.foo.com;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * Basically the same answer as noah's.
 */
public class Home<E>
{

    @SuppressWarnings ("unchecked")
    public Class<E> getTypeParameterClass()
    {
        Type type = getClass().getGenericSuperclass();
        ParameterizedType paramType = (ParameterizedType) type;
        return (Class<E>) paramType.getActualTypeArguments()[0];
    }

    private static class StringHome extends Home<String>
    {
    }

    private static class StringBuilderHome extends Home<StringBuilder>
    {
    }

    private static class StringBufferHome extends Home<StringBuffer>
    {
    }   

    /**
     * This prints "String", "StringBuilder" and "StringBuffer"
     */
    public static void main(String[] args) throws InstantiationException, IllegalAccessException
    {
        Object object0 = new StringHome().getTypeParameterClass().newInstance();
        Object object1 = new StringBuilderHome().getTypeParameterClass().newInstance();
        Object object2 = new StringBufferHome().getTypeParameterClass().newInstance();
        System.out.println(object0.getClass().getSimpleName());
        System.out.println(object1.getClass().getSimpleName());
        System.out.println(object2.getClass().getSimpleName());
    }

}

আপনি একটি 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 এর জন্য এখানে জাভাডোক


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

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

আমার ক্ষেত্রে আমি 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();
    }
}

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


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

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

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





generics