0

User supports userType and userFunction by config:

{"userType": "com.user.Person", "userFunction": "com.user.userFunction"}

we expect to get data for user and feed data to userFunction:

public class DataConsumer<T> {
    //get data from some place, such as kafka
    T data;
}
process() {
    String userType = userInput();
    DataConsumer<userType> dataConsumer = new DataConsumer<userType>(); // error because generic class's type name don't support String or Class 
    userFunction(dataConsumer.data); // We get this function by reflection
}

// This is ok in the user side
userFunction(userType data) {
    data;
}

How can I implement this function without error? If it is not possible, Is there another way?

At last, I use Object to stand all type names. But user must transform Object type to userType manually. Is there a better way?

{
    String userType = userInput();
    DataConsumer<Object> dataConsumer = new DataConsumer<Object>(); // ok
    userFunction(dataConsumer.data); 
}

userFunction(Object data) {
    (userType)data;
}
user2928444
  • 49
  • 1
  • 7
  • `Class.forName(...)`? – Thorbjørn Ravn Andersen Oct 17 '18 at 07:46
  • You mean like `"java.util.List"`? what exactly you want to do, can you add examples to your question? – GotoFinal Oct 17 '18 at 08:11
  • Possible duplicate of [Create new class from a Variable in Java](https://stackoverflow.com/questions/1268817/create-new-class-from-a-variable-in-java) – oerl Oct 17 '18 at 08:23
  • Sorry for my unclear description. I have updated my question. I do not think it will be solved by reflection simply. Thank you very much. – user2928444 Oct 17 '18 at 08:53
  • I still don't understand your exact goal, can you expand this example to also how you want to use it? it does not need to be valid java code, just some pseudocode and replace that code you don't know how to write with some non-existing method with readable name. And also explain why you need this – GotoFinal Oct 17 '18 at 09:07
  • Above is a simple abstract for my question. Thank you. – user2928444 Oct 17 '18 at 09:20
  • what is the error? – SamHoque Oct 17 '18 at 09:21
  • 1
    How do you think, does specifying `myType` in the generic type of the variable (if it worked) change the way `MyClass` works? – Holger Oct 17 '18 at 11:22
  • I edited my answer, maybe it will help you more, but I think that in your case user should just cast and handle this manually, this just look very unsafe. – GotoFinal Oct 19 '18 at 19:57

2 Answers2

0

You can use the Reflection API to get the instance of Classes, Methods and Fields;

First you can get the Class using

 Class c = Class.forName("Class Name");

You can get the methods from that class using

 c.getDeclaredMethod("Method Name");

and same goes for the Fields

 c.getDeclaredField("Field Name");
SamHoque
  • 2,978
  • 2
  • 13
  • 43
0

Ah, you should know that generics in java are only syntax sugar in compiler for most of the time, so if you don’t know runtime type just use wildcard or raw type:
MyClass<?> myClass = new MyClass<>();, MyClass myClass = new MyClass();
But if user input is always of known type like that String then you can just do:
MyClass<String> myClass = new MyClass<>();
You can also create generic constructor in your class like this:

public class MyClass<T> {
    T data;
    public <T> MyClass(T data) {this.data = data;}
}

So generic type will be of type of data you passed to it - but this only exist at compile time, in runtime java IGNORES all generics here, like this is valid java code:

List<String> strings = new ArrayList<>();
strings.add(“a”);
List<Integer> integersKindOf = (List)strings;
integersKindOf.remove(“a”);

Java only saves generic type of fields, super classes (class MyMap extends HashMap<String, Integer> - you can get that super type with generic parameters) and methods. But they are not used in runtime and but reflections can be used to read that type.
For local variables this is not possible and would be useless due to that type erasure.

There is also common pattern for unsafe generic cast, but you should be very careful when to use it:

public <T> T doSomething(String type) {
    return (T) Class.forName(type).newInstance();
}

and then this can be used like this:
ArrayList<Whatever> list = doSomething("java.util.ArrayList");
but it can be also used like this:
Integer list = doSomething("java.util.ArrayList");
And this will throw exception at runtime, and this is why it is very unsafe.

GotoFinal
  • 3,585
  • 2
  • 18
  • 33
  • Thank you. Your suggestions are pretty good and I learn a lot. But consider my situation, I use Object to stand for all type names. My solution is not clean enough, because it requires to convert Object to certain class when deal with the instance. – user2928444 Oct 17 '18 at 12:14
  • then add this to your example, your example should show your usecase, and explain why you need such weird solution, what you are creating, maybe there is other way. – GotoFinal Oct 17 '18 at 12:23
  • Thank you for your detail answer. I will take it. – user2928444 Oct 22 '18 at 01:44