এখানে একটি উন্নত সমাধান, উপর ভিত্তি করে ParameterizedType.getActualTypeArguments
ইতিমধ্যে @noah, @ লার্স বোহল এবং আরও কিছু দ্বারা উল্লিখিত হয়েছে।
বাস্তবায়নে প্রথম ছোট উন্নতি। কারখানার উদাহরণ না দিয়ে ফিরে আসা উচিত, তবে একধরণের। ব্যবহারের Class.newInstance()
সুযোগ হ্রাস করে আপনি উদাহরণটি ফিরে আসার সাথে সাথে soon কারণ কেবল নো-আর্গুমেন্ট কনস্ট্রাক্টরদের এভাবেই প্রার্থনা করা যেতে পারে। আরও ভাল উপায় হ'ল কোনও প্রকার ফেরত দেওয়া এবং কোনও ক্লায়েন্টকে চয়ন করার অনুমতি দেওয়া, তিনি কোন নির্মাতাকে ডাকতে চান:
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);
}
}
}
এখানে ব্যবহারের উদাহরণ দেওয়া হল। @ লার্স বোহাল সম্প্রসারনের মাধ্যমে পুনরায় সংশোধিত জেনেরিক পাওয়ার জন্য কেবলমাত্র একটি সহজ উপায় দেখিয়েছে। @ নোহ শুধুমাত্র সাথে উদাহরণ তৈরি করার মাধ্যমে {}
। উভয় ক্ষেত্রেই প্রদর্শন করার জন্য এখানে পরীক্ষা দেওয়া হচ্ছে:
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>
। আমি এটি করিনি, কেবল মুছে যাওয়া পরীক্ষার কেসটি দেখানোর জন্য।