JMohasin
JMohasin

Reputation: 533

How to instantiate Generic class object?

I am trying to convert the following c# code into java

abstract class BaseProcessor<T> where T : new()
{
 public T Process(HtmlDocument html)
 {
         T data = new T();

        Type type = data.GetType();
        BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty;
        PropertyInfo[] properties = type.GetProperties(flags);
        foreach (PropertyInfo property in properties)
        {
             string value = "test";
             type.InvokeMember(property.Name, flags, Type.DefaultBinder, data, new object[] { value });
        }
 }
}

So i have done upto

public class BaseProcessor<T> 
{
   public T Process(String m_doc)
   {
      T data = (T) new BaseProcessor<T>(); // this is not working

      Document doc = Jsoup.parse(m_doc);
      return data;
   }
}

When i instantiate the data object its not acquiring the properties of the Generic class at runtime let say for example when i hit the code its not getting properties of DecodeModel class

IDocProcessor<DecodeModel> p = new DecodeThisProcessor();
return p.Process(doc);


public interface IDocProcessor<T>
{
    T Process(String webresponse);
}

public class DecodeThisProcessor extends BaseProcessor<DecodeModel> implements IDocProcessor<DecodeModel>
{
public void setup();
}

So please help me what will be the right syntax to instantiate generic object data

Upvotes: 3

Views: 1358

Answers (3)

Has QUIT--Anony-Mousse
Has QUIT--Anony-Mousse

Reputation: 77475

You cannot instantiate generics. The reason is that the type is not available at run-time, but actually replaced with Object by the compiler. So

T data = new T(); // Not valid in Java for a generics T!

would in fact be:

Object data = new Object(); // Obviously not the desired result

Read the Java Generics Tutorial wrt. to "type erasure" for details.


You will need to employ the factory pattern.

T data = factory.make();

where

public interface Factory<T> {
     T make();
}

needs to be implemented and passed to the constructor. To make this work, you need a factory that knows how to instantiate the desired class!

A (rather obvious) variant is to put the factory method into your - abstract - class.

public abstract class BaseProcessor<T> 
{
   protected abstract T makeProcessor();

   public T Process(String m_doc)
   {
       T data = makeProcessor(); // this is now working!

and when extending BaseProcessor implement it for the actual final type.

Upvotes: 2

Marko Topolnik
Marko Topolnik

Reputation: 200226

Tough luck; in Java the whole of Generics is strictly a compile-time artifact and the instantiation of the type parameters doesn't exist in the runtime. The usual workaround is to pass an instance of Class as a marker, which will allow you to reflectively create an object of that type. This is fraught with many pitfalls, but is the best you can get in Java.

Upvotes: 1

Eng.Fouad
Eng.Fouad

Reputation: 117655

You can do this:

public class BaseProcessor<T>
{
    private Class<T> clazz;

    public BaseProcessor(Class<T> clazz)
    {
        this.clazz = clazz;
    }

    public T Process(String m_doc)
    {
         T data = clazz.newInstance()
         Document doc = Jsoup.parse(m_doc);
         return data;
    }
}

Hint: Make sure that T has a no-arg constructor.

Upvotes: 0

Related Questions