简体   繁体   中英

Java get an existing list of objects knowing the class name(dynamically)

I have a class containing 2 lists, of different object types.

List<Student> students;
List<Lecturer> lecturers;

Each of these classes have a method that returns a String. I want to find something from that String and the method that I would create would be the same for both lists,the class name(Student/Lecturer), the list name(students/lecturers) and the method name(studentMethod/lecturerMethod) being the only ones that differ.

Knowing the className, listName and the methodName, how can I get the proper list(called listName) so I can then call the desired method(called methodName) from each object in the list.

PS : I know it would be easier to just create 2 separate methods for each list but I want my code to be DRY and also to learn more about OOP principles.

Example: If I want to get the students list and then invoke the studentMethod for each student I should have something like this:

void dryMethod(String className, String listName, String methodName) {
    Class<?> desiredClass = Class.forName(className);
    List<desiredClass> desiredList = getListByName(listName);
    Method desiredMethod = getMethodByName(methodName);
    for(desiredClass object : desiredList){
        manipulateString(object.desiredMethod());
    }
}
dryMethod("Student","students","studentMethod");

Is it possible?

Create a parent abstract class/interface that defines that method both classes should define. For example:

public interface Person {
    public void desiredMethod();
}

// Student will have to give an implementation for desiredMethod()
public class Student implements Person

// Lecturer will have to give an implementation for desiredMethod()
public class Lecturer implements Person

Then make dryMethod use a list of a type that implements Person :

void dryMethod(List<? implements Person> myList) {
   // you can use List<Student> and List<Lecturer> as myList
   for (Person person : myList) {
       person.desiredMethod();
   }
}

I recommend you to read some info about Polymorphism .

EDIT: When declaring your lists, you can do:

List<Student> students;  // only Student class allowed
List<Lecturer> lecturers;  // only Lecturer class allowed
List<Person> students;  // both Student and Lecturer class allowed

One thing to ask yourself is, if you have two classes with two methods that do pretty much the same thing, should those two methods actually have the same name and be specified by the same interface?

Even if that is not the case, you don't have to abandon DRY. You can define the string processing logic in a common method, and use the stream operator map to transform students and lecturers into streams of String :

students.stream().map(Student::studentMethod).forEach(this::commonMethod);
lecturers.stream().map(Lecturer::lecturerMethod).forEach(this::commonMethod);

void commonMethod(String str) { ... }

This is more FP style than OOP style though. A good OOP method of doing generic operations on different types is using the Visitor design pattern , but that requires writing quite a bit of boilerplate code compared to streams.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM