How can I get class members of a generic class?
The result of findAll of Entity of type T is entered as a parameter.
findAll
is:
findAll = {ArrayList@11389} size = 1
0 = {Account@11395}
id = {Long@14680} 1
userid = "test"
username = "username"
password = "{bcrypt}$2a$10$n.BVxjdvW.C8jBPmZ6U.Ueldc2zb5JZud5U2zH0HaN6Pu0lcjndiK"
role = {AccountRole@14684} "USER"
At this time, you need to get all the values of id, userid, username, and password, which are the results of findAll, but you cannot do getId, getUserid, getUsername, getPassword, etc. because it is a generic class with T.
In this case, I wonder how I can get all class members in class T.
Below is my code.
public void entityToExcel(List<T> findAll) {
List<String> headers = createHeader();
// create worksheet
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet("proper sheetname");
int rowNumber = 0;
// create header
XSSFRow headerRow = sheet.createRow(rowNumber );
for (int i = 0; i < headers.size(); i ) {
headerRow.createCell(i).setCellValue(headers.get(i));
System.out.println("headers.get(i) = " headers.get(i));
}
//Enter entity data line by line
XSSFRow row = sheet.createRow(rowNumber );
for (int i = 0; i < findAll.size(); i ) {
T find = findAll.get(i);
find.getId(); ?? //cannot resolve method `getId` in `T` error
//I have to work here row.createCell(i).setCellValue(find.getEachClassVariable);
}
}
CodePudding user response:
The properties of T find
can be accessed by casting.
Account account = (Account) find;
account.getId()
But if the entityToExcel
function only accepts Account list
, why not just declare the function as
public void entityToExcel(List<Account > findAll)
Or interface-oriented programming
public class ExcelService {
public <T extends IEntity> void entityToExcel(List<T> findAll) {
for (int i = 0; i < findAll.size(); i ) {
T find = findAll.get(i);
System.out.println(find.getId());
System.out.println(find.getUsername());
}
}
interface IEntity {
String getId();
String getUsername();
}
static class Account implements IEntity {
private String id;
private String name;
@Override
public String getId() {
return this.id;
}
@Override
public String getUsername() {
return this.name;
}
}
}
CodePudding user response:
I recently had this problem when working with generics. The solution that I found was relatively simple.
First make sure that all classes that you are passing in is a subclass of some superclass. Let's define that superclass as Resource
. We will then call a method named getAllFields
which will get all of the fields of that class. The method will take a type E
which extends Resource
. We will then create a new instance of the class being passed in and set it to a Resource with (Resource) Class.forName(type.getName()).getConstructor().newInstance();
This creates a new instance of the type with class.forName() and casts it to a Resource object.
This is what the method looks like so far:
public <E extends Resource> E getAllFields(Class<E> type) {
Resource res = (Resource)
Class.forName(type.getName()).getConstructor().newInstance();
}
We can now iterate through each of the fields in the class with for (Field field : res.getClass().getDeclaredFields())
We can get the values of the fields with field.get(res)
BUT first we have to make the field accessible with field.setAccessible(true);
Finally, to get all the methods in the class the reflective method getDeclaredMethods
will return all the methods.
public <E extends Resource> E getAllFields(Class<E> type) {
Resource res = (Resource)
Class.forName(type.getName()).getConstructor().newInstance();
for (Field field : res.getClass().getDeclaredFields()) {
field.setAccessible(true);
System.out.println(field.get(res));
}
for(Method method : res.getClass.getDeclaredMethods() {
System.out.println(method.getName());
}
}