Reputation: 53
I want to separate 2 class from each other and DataExchange not info of Row Class, but it makes problem.
How to solve this problem?
Code:
class MyActivity {
public void onCrate() {
DataExchange de = new DataExchange(BookRow.Class);
....
}
public class BookRow {
public String book_id;
public String book_title;
}
}
File DataExchange:
class DataExchange<T> {
public DataExchange(Class<T> SendedClass) {
SendedClass[] items = new SendedClass[5]; // main problem
for(int i = 0; i < 5; i++) {
items[i] = new SendedClass(i , "my book title" + i); // problem
}
// ...
}
}
Upvotes: 1
Views: 3213
Reputation: 1382
Try this code:
public class MyActivity
{
public void onCrate()
{
DataExchange de = new DataExchange(BookRow.class);
}
}
public class BookRow
{
public String book_id;
public String book_title;
}
public class DataExchange<T>
{
public DataExchange(Class<T> sendedClass)
{
try
{
T[] items = (T[]) Array.newInstance(sendedClass, 5);
//or Class<T>[] items = (Class<T>[]) Array.newInstance(sendedClass, 5);
for(int i = 0; i<5; i++)
{
Constructor<T> constructor = (Constructor<T>) sendedClass.getConstructor(Integer.class, String.class);
items[i] = constructor.newInstance(i , "my book title" + i);
}
}
catch (final Exception e)
{
e.printStackTrace();
}
}
}
What you did wrong was:
BookRow.Class
instead of BookRow.class
.public DataExchange(Class<T> SendedClass)
and it should be public DataExchange(T sendedClass); Edit: as @Daniel suggested that is not needed - my bad.sendedClass[] items
even if sendedClass
is of type Class
. sendedClass
is a variable and not a type. Thats why you have to use T
or Class<T>
.sendedClass(params)
. If you know the class type you can use reflection to do that:
http://docs.oracle.com/javase/tutorial/reflect/
http://tutorials.jenkov.com/java-reflection/index.htmlUpvotes: 1
Reputation: 1861
You can make use of the reflection to instantiate your objects, but that is not type safe, nor safe in any way ( the constructor Class(int, String) might not exist and you'll get runtime errors).
public class DataExchange<T> {
public DataExchange(final Class<T> SendedClass) throws IllegalArgumentException, SecurityException, InstantiationException,
IllegalAccessException, InvocationTargetException, NoSuchMethodException {
T[] items = (T[])Array.newInstance(SendedClass, 5);
for (int i = 0; i < 5; i++) {
items[i] = SendedClass.getConstructor(MyActivity.class , Integer.class, String.class).newInstance(i, "my book title" + i); //1st param is outer class when you try to call constructors for inner classes
}
}
}
Upvotes: 0
Reputation: 11093
BookRow should be a static inner class
Your question has two parts, though. One for creating an array based on a generic type, the second constructing an item of that generic type (and setting its values).
public DataExchange(Class<T> SendedClass) {
// create an array of generic type
final T[] items = (T[]) Array.newInstance(SendedClass, 5);
for (int i = 0; i < 5; i++) {
// create item of generic type
T item = SendedClass.newInstance();
SendedClass.getField("book_id").set(item, "" + i);
SendedClass.getField("book_title").set(item, "book title"+i);
// add item of generic type to array of generic types.
items[i] = item;
}
//items is now an array with multiple items
...
}
Upvotes: 1
Reputation: 88757
First, you should adhere to the Java naming convention, to make things easier to understand.
In your case SendedClass
is a parameter name and not a class name, i.e. it should be sendedClass
which then would make it clear that you can't jsut call the constructor as you did.
So actually you can pass in any class and you'd have to call its constructor using reflection, e.g. like this:
items[i] = sendedClass.getConstructor( Integer.TYPE, String.class ).newInstance( i, "my book title" + i);
Just note that such a constructor might not exist and you'd have to account for that as well as for the multitude of exceptions that can be thrown by reflection.
Creating the array would be done in a similar way using reflection:
T[] array = (T[]) Array.newInstance( sendedClass, 5 );
As you can see, creating objects that way is not as easy as it would seem and thus patterns like the factory pattern would most probably help here.
Update on inner classes:
It would be easier if BookRow
wasn't an inner class, but it it really needs to be, you could still use reflection.
From the JavaDoc on getConstructor(...)
:
If this Class object represents an inner class declared in a non-static context, the formal parameter types include the explicit enclosing instance as the first parameter.
Hence you'd need to create the instance like this (which you'd have to know or pass as a parameter):
sendedClass.getConstructor( MyActivity.class, Integer.TYPE, String.class ).newInstance( myActivityInstance, i, "my book title" + i);
Upvotes: 1
Reputation: 7450
The inner class should be static, or it cannot be initialized in this way.
public static class BookRow
{
public String book_id;
public String book_title;
}
Upvotes: 0