Instantiating dynamically assigned classes in Java
I need a function to create instances of a dynamically given class in java.
I found many samples, but in all of them the class to be created was known prior to runtime.
There are user-defined classes:
class Student { //some code }
class Teacher { //some code }
class Course { //some code }
I need
List<class> MyFunction(<class>) {
List<class> items = new ArrayList<class>();
for(int i = 0; i < 5; i++) {
create_a_new_class_instance;
items.add(new_created_instance);
}
return items;
}
How to use
List<Student> students = MyFunction(Student);
List<Teacher> teachers = MyFunction(Teacher);
List<Course> courses = MyFunction(Course);
Hope someone can help.
This is my first question on Stackoverflow, sorry for any inconvenience.
Duck
source to share
Assuming the classes supplied in MyFunction
have a default constructor, a simple implementation would be
public static <T> List<T> MyFunction(Class<T> clazz) {
if (clazz == null) {
return null;
}
T item;
List<T> items = new ArrayList<T>();
for (int i = 0; i < 5; i++) {
try {
item = clazz.newInstance();
} catch (Exception e) {
item = null;
}
if (item != null) {
items.add(item);
}
}
return items;
}
and the above method can be called like
List<Student> student = MyFunction(Student.class);
To increase transparency, an exception thrown inside a method can be handled in another way (for example, added to the method signature).
source to share
In Java 8, you can use reference or lambda expressions to dynamically instantiate classes without using reflection.
public static <T> List<T> myFunction(Supplier<T> supplier) {
return Stream.generate(supplier)
.limit(5)
.collect(Collectors.toList());
}
You would call it like this:
List<Student> students = myFunction(Student::new);
If you're unfamiliar with streams, the imperative equivalent is:
public static <T> List<T> myFunction(Supplier<T> supplier) {
int size = 5;
List<T> list = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
list.add(supplier.get());
}
return list;
}
source to share
This should work.
import java.util.ArrayList;
import java.util.List;
public class DynamicClassList {
public <T> List<T> myFunction(Class<T> inputClass) {
List<T> items = new ArrayList<T>();
for(int i = 0; i < 5; i++) {
try {
T myT = inputClass.getConstructor().newInstance();
items.add(myT);
} catch (Exception e) {
e.printStackTrace();
}
}
return items;
}
public static void main(String[] args) {
DynamicClassList dynamicClassList = new DynamicClassList();
List<Student> s = dynamicClassList.myFunction(Student.class);
List<Teacher> t = dynamicClassList.myFunction(Teacher.class);
List<Course> c = dynamicClassList.myFunction(Course.class);
}
}
source to share
You can use reflection to do this, every class you pass must have a default no-argument constructor. for this particular application you will probably need all 3 classes to share the interface so you can post the list back correctly
public interface Unit {
//Put any common functionality method stubs here
}
public class Teacher implements Unit {
}
//....etc for the other classes
List<Unit> MyFunction(Class<Unit> clazz) {
List<Unit> items = new ArrayList<Unit>();
for(int i = 0; i < 5; i++) {
items.add(clazz.newInstance());
}
return items;
}
when you assign your list to a list variable you will need to cast it.
eg:
List<Student> students = (List<Student>) MyFunction(Student.class);
source to share