Reputation: 533
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
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
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
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