How to pass generic class in reflection get method in java - java

I want my method "themethod" is referencing "foo", then in a static block, try to get the method "foo" with "getMethod", to which I pass the name of the method and type of the parameters, but "foo "receives as a parameter a type generic, then I know not to give to work.
Code:
public class Clazz<T>
{
static Method theMethod;
static
{
try
{
Class<Clazz> c = Clazz.class;
theMethod = c.getMethod( "foo", T.class ); // "T.class" Don't work!
}
catch ( Exception e )
{
}
}
public static <T> void foo ( T element )
{
// do something
}
}
How do I make "theMethod" referencing a method called 'foo'?

Something like this?
import java.lang.reflect.Method
public class Clazz<T>
{
static Method theMethod;
static Class<T> type;
public Clazz(Class<T> type) {
this.type = type;
this.theMethod = type.getMethod("toString");
}
}
System.out.println(new Clazz(String.class).theMethod);
Gives
public java.lang.String java.lang.String.toString()

This should work in the most cases:
public class Clazz<T> {
static Method theMethod;
static {
try {
Class<Clazz> c = Clazz.class;
theMethod = c.getDeclaredMethod("foo", Object.class);
} catch(Exception e) {}
}
public static <T> void foo(T element) {
// do whatever
}
}

Related

Check if the calling method is annotated

I have a use-case where the return behaviour of the callee method should change based on the annotation of the caller method.
Here is the situation:
#SomeAnnotation
public void caller(){
return SomeOtherClass.caller(String arg);
}
// Returns X in this case
public class SomeOtherClass{
public String callee(String arg){
if(annotationIsPresent(SomeAnnotation.class))
return "X";
else
return "Y";
}
}
I went through some resources and I found this.
I was thinking of using Thread.currentThread().getStackTrace() to get the current invoker method.
I have no clue if this is feasible or is a correct design also. Could someone please comment on it?
Adding code:
Annotation
#Retention(RetentionPolicy.RUNTIME)
public #interface SomeAnnotation {
}
Caller class
#SomeAnnotation
public class Caller {
#SomeAnnotation
public static void caller(){
System.out.println(new Callee().callee());
}
}
Callee
public class Callee {
public String callee(){
String className = Thread.currentThread().getStackTrace()[2].getClassName();
String methodName = Thread.currentThread().getStackTrace()[2].getMethodName();
try {
Class<?> klass = Class.forName(className);
Method method = klass.getMethod(methodName);
if(klass.isAnnotationPresent(SomeAnnotation.class))
System.out.println("HELLO");
if(method.isAnnotationPresent(SomeAnnotation.class))
System.out.println("HELLOW");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
Main class
public class Main {
public static void main(String[] args){
Caller.caller();
}
}

Creating a class and creating an instance from a string

I have a problem in creating an object.
Basically I would like to create an object from a given class by taking originally a string. I know that using Class.forName(field) works, but not in my case and I will show you why below. I have thought about reflection but fear it will cause the same problem.
My code as of right now is (template is a String):
int n = template.length();
String field = at.getFieldName().trim();
field = field.substring(0, field.length() - 1);
Class<?> correctClass = Class.forName(field);
UniqueEntity<correctClass> ue = new UniqueEntity<correctClass>();
The error message I get is that correctClass cannot be resolved to a type.
Once you used Class.forName() method you got your Class instance (variable correctClass) invoke method getConstructor() or getConstructors() to get an instance of class Constructor. Once you get your instance of class Constructor invoke method newInstance() to get an instance of your class. Here is the example:
Class myClass = Class.forName(field);
Constructor constructor = myClass.getConstructor()
Object o = constructor.newInstance()
All this assuming that your class has default constructor.
In order for you to be able to create a UniqueEntity with the type of your reflective class, you need to pass the class type into a generic helper method.
private static <T> UniqueEntity<T> createEntity(Class<T> clazz) {
return new UniqueEntity<T>(clazz);
}
Code
import java.lang.reflect.Type;
public class Generic {
public static void main(String[] args) {
try {
String field = "java.lang.Integer";
UniqueEntity<?> entity = fromField(field);
System.out.println(entity);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static UniqueEntity<?> fromField(String field) throws ClassNotFoundException {
return createEntity(Class.forName(field));
}
private static <T> UniqueEntity<T> createEntity(Class<T> clazz) {
return new UniqueEntity<T>(clazz);
}
private static class UniqueEntity<T> {
private final Type type;
public UniqueEntity(Class<T> clazz) {
this.type = clazz.getGenericSuperclass();
}
#Override
public String toString() {
return "UniqueEntity [type=" + type + "]";
}
}
}

java - Abstract base enum/class for singleton

I've created two enum classes as singleton:
public enum A {
INSTANCE;
public void init(param p1, param p2) {
}
public void connect() {
}
public void disconnect() {
}
public bool isConnected() {
}
}
public enum B {
INSTANCE;
public void init(param p1) {
}
public void connect() {
}
public void disconnect() {
}
public bool isConnected() {
}
}
As you can see both enum classes are very similar so I was wondering if I should create some kind of base abstract class/enum or interface and then have these two enums extend or implement from it.
UPDATE 1: I'd like to put some shared member variables on the base class
UPDATE 2: Should I just change the way I'm defining the singleton?
As per java enum tutorial
All enums implicitly extend java.lang.Enum. Since Java does not
support multiple inheritance, an enum cannot extend anything else.
Here is interesting SO discussion related to this topic.
As Nambari stated you can't have an enum extend anything. However what they neglected to say is you CAN have an enum implement an interface, which is done as with a class using the implements keyword. I've done this at work and it's very useful in the right situation! There's an example here: http://javahowto.blogspot.co.uk/2008/04/java-enum-examples.html
There is a sweet little class called a DynamicObjectAdapterFactory posted by Heinz Kabutz which uses generics and reflection to adapt an object to implement an interface by providing it with a source class that already implements the interface.
Using it like below you can wrap your INSTANCE in a proxy. Of course the resulting object is no longer an enum but it does retain all of the singletonness of the enum I think. It also, obviously - can use any object to implement your interface.
I think this is as close as you will get to an enum extending a class.
Here's some test code that seems to work. Obviously the object is no longer an enum but as your aim was a singleton this may be acceptable.
public class Test {
// To implement this.
public interface Implement {
public void init();
public void connect();
public void disconnect();
public boolean isConnected();
}
// An implementor that does implement.
public static class Implements implements Implement {
#Override
public void init() {
}
#Override
public void connect() {
}
#Override
public void disconnect() {
}
#Override
public boolean isConnected() {
return false;
}
}
// Extend the INSTANCE in this.
public enum Extend {
INSTANCE;
// Hold my adapted version - thus still a singleton.
public final Implement adaptedInstance;
Extend () {
// Use the constructor to adapt the instance.
adaptedInstance = DynamicObjectAdapterFactory.adapt(this, Implement.class, new Implements());
}
}
// Provides an INSTANCE that has been extended by an Implements to implement Implement.
public static Implement getInstance () {
return Extend.INSTANCE.adaptedInstance;
}
public void test() {
System.out.println("Hello");
Implement i = getInstance();
}
public static void main(String args[]) {
new Test().test();
}
}
Here's the DynamicObjectAdapterFactory - I've tweaked it a little from the original - I hope Dr. Kabutz does not object.
public class DynamicObjectAdapterFactory {
// Use methods in adaptee unless they exist in target in which case use adapter.
// Implement target in passing.
public static <T> T adapt(final Object adaptee,
final Class<T> target,
final Object adapter) {
return (T) Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class[]{target},
new InvocationHandler() {
private final String name =
adaptee.getClass().getSimpleName() + "(" + adaptee.toString() + ")"
+ "+" + adapter.getClass().getSimpleName() + "(" + adapter.toString() + ")";
// The methods I wish to adapt.
private Map<MethodIdentifier, Method> adaptedMethods = new HashMap<>();
{
// initializer block - find all methods in adapter object
Method[] methods = adapter.getClass().getDeclaredMethods();
for (Method m : methods) {
// Keep a map of them.
adaptedMethods.put(new MethodIdentifier(m), m);
}
}
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
// Has it been adapted?
Method otherMethod = adaptedMethods.get(new MethodIdentifier(method));
if (otherMethod != null) {
return otherMethod.invoke(adapter, args);
} else {
return method.invoke(adaptee, args);
}
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
#Override
public String toString() {
StringBuilder s = new StringBuilder();
// Really simple. May get more flexible later.
s.append("Adapted: ").append(name);
return s.toString();
}
});
}
private static class MethodIdentifier {
private final String name;
private final Class[] parameters;
public MethodIdentifier(Method m) {
name = m.getName();
parameters = m.getParameterTypes();
}
#Override
public boolean equals(Object o) {
// I am always equal to me.
if (this == o) {
return true;
}
// I cannot be equal to something of a different type.
if (!(o instanceof MethodIdentifier)) {
return false;
}
MethodIdentifier mid = (MethodIdentifier) o;
return name.equals(mid.name) && Arrays.equals(parameters, mid.parameters);
}
#Override
public int hashCode() {
return name.hashCode();
}
}
}
You can use the abstract class below for singleton instead of enum.
public abstract class AbstractSingleton {
private static Map<String, AbstractSingleton> registryMap = new HashMap<String, AbstractSingleton>();
AbstractSingleton() throws SingletonException {
String clazzName = this.getClass().getName();
if (registryMap.containsKey(clazzName)) {
throw new SingletonException("Cannot construct instance for class " + clazzName + ", since an instance already exists!");
} else {
synchronized (registryMap) {
if (registryMap.containsKey(clazzName)) {
throw new SingletonException("Cannot construct instance for class " + clazzName + ", since an instance already exists!");
} else {
registryMap.put(clazzName, this);
}
}
}
}
#SuppressWarnings("unchecked")
public static <T extends AbstractSingleton> T getInstance(final Class<T> clazz) throws InstantiationException, IllegalAccessException {
String clazzName = clazz.getName();
if (!registryMap.containsKey(clazzName)) {
synchronized (registryMap) {
if (!registryMap.containsKey(clazzName)) {
T instance = clazz.newInstance();
return instance;
}
}
}
return (T) registryMap.get(clazzName);
}
public static AbstractSingleton getInstance(final String clazzName)
throws ClassNotFoundException, InstantiationException, IllegalAccessException {
if (!registryMap.containsKey(clazzName)) {
Class<? extends AbstractSingleton> clazz = Class.forName(clazzName).asSubclass(AbstractSingleton.class);
synchronized (registryMap) {
if (!registryMap.containsKey(clazzName)) {
AbstractSingleton instance = clazz.newInstance();
return instance;
}
}
}
return registryMap.get(clazzName);
}
#SuppressWarnings("unchecked")
public static <T extends AbstractSingleton> T getInstance(final Class<T> clazz, Class<?>[] parameterTypes, Object[] initargs)
throws SecurityException, NoSuchMethodException, IllegalArgumentException,
InvocationTargetException, InstantiationException, IllegalAccessException {
String clazzName = clazz.getName();
if (!registryMap.containsKey(clazzName)) {
synchronized (registryMap) {
if (!registryMap.containsKey(clazzName)) {
Constructor<T> constructor = clazz.getConstructor(parameterTypes);
T instance = constructor.newInstance(initargs);
return instance;
}
}
}
return (T) registryMap.get(clazzName);
}
static class SingletonException extends Exception {
private static final long serialVersionUID = -8633183690442262445L;
private SingletonException(String message) {
super(message);
}
}
}
From: https://www.cnblogs.com/wang9192/p/3975748.html

How to identify the returned object's type of a method?

I have a helper class which gets notified by the below method
public void setObject(Object obj) {
this.obj = obj
}
There is getter method for the obj. Is there any way to identify the caller about the type of the obj. The object can take any object like :
List<Switch>
Switch
List<Link>
The caller has to process the obj after calling the getter method. Is there a way to do it?
You can always know the class (and then the class name) from obj.getClass(). What you want to do with it further ?
If you want to invoke methods on the obj - You need reflection..
Something like this -
Class myClass = obj.getClass();
Method m = myClass.getDeclaredMethod("get",new Class[] {});
Object result = m.invoke(myObject,null);
You could know the object type using instanceof operator.Consider the following example:
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
if (getObject() instanceof A) {
System.out.println("A class");
}
if (getObject() instanceof B) {
System.out.println("B class");
}
if (getObject() instanceof List) {
System.out.println("List class");
}
}
/**
*
* #return Object type.
*/
public static Object getObject() {
//Change this value to new A() or new B();
return new ArrayList<A>();
}
}
class A {
private String aName;
public A(String aName) {
this.aName = aName;
}
public String getaName() {
return aName;
}
public void setaName(String aName) {
this.aName = aName;
}
}
class B {
private String bName;
public B(String bName) {
this.bName = bName;
}
public String getbName() {
return bName;
}
public void setbName(String bName) {
this.bName = bName;
}
}
As you can see I have a method returning object type and if you are gonna change the returning value of that method you can easily understand what is going on.And one more thing you can't guess the generic types at runtime because "Generic types are erased before runtime".Hope you got my point.Cheers
This might help you. It informs you how to get the parameterized type.
Get generic type of java.util.List

Condition to choose which getConstructor method

I have a class in which i have intialized hashmap in static block. Passing the key, I have retrived the value which is a class. In order to create object for this class. I have used the constructor class to get the constructor and passed arguments and created object.
I have two class in hashmap. To create objectfor EchoExpression I need to pass two arguments and for OutExpression class i need to pass only one argument(String).
Question:
Based on the class returned by the key I need to execute which constructor to get and implement, whether the constructor with one argument or two argument.
public class ExampleFactory {
private static HashMap<String,Class<?>> hmap = new HashMap<String,Class<?>>();
static
{
hmap.put("echo", EchoExpression.class);
hmap.put("Out", OutExpression.class);
}
public void getExpo(String key,String expression)
{
Class aClass =map.get(key);
//Constructor implementation for OutExpression where only one argument string is passed
Constructor constructor = aClass.getConstructor(new Class[]{String.class});
Object object= constructor.newInstance(expression);
//constructor for passing two arguments string for EchoExpression
Constructor constructor = aClass.getConstructor(new Class[]{String.class,Class.class});
Object object= constructor.newInstance(expression, Boolean.class);
return null;
}
}
How to choose from the value(class) which class to implement without using if else?
Use an Enum and switch on it. Here is a executable stub without getting too deeply into the reflection or the syntax of your example:
package com.trip.test;
import java.util.HashMap;
import java.util.Map;
public class ExampleFactory {
private static Map<String, Class<?>> hmap = new HashMap<String, Class<?>>();
static {
hmap.put("echo", EchoExpression.class);
hmap.put("Out", OutExpression.class);
}
public static void getExpo(String key, String expression) {
Class aClass = hmap.get(key);
ClassMappingEnum myType = ClassMappingEnum.getClassMappingEnum(aClass);
switch (myType) {
case ECHO_EXPRESSION:{
System.out.println(aClass.getName());
// do something
break;
}
case OUT_EXPRESSION:{
System.out.println(aClass.getName());
// do something
break;
}
case UNKNOWN:
default:
System.out.println("Bummer: " + aClass.getName());
}
}
public static void main(String[] args) {
getExpo("echo", "B");
getExpo("Out", "B");
}
}
enum ClassMappingEnum {
ECHO_EXPRESSION(EchoExpression.class), OUT_EXPRESSION(OutExpression.class), UNKNOWN(null);
private Class typeDes;
private ClassMappingEnum(Class typeDes) {
this.typeDes = typeDes;
}
public static ClassMappingEnum getClassMappingEnum(Class compare) {
for (ClassMappingEnum cme : ClassMappingEnum.values()) {
if (cme.typeDes.equals(compare)) {
return cme;
}
}
return UNKNOWN;
}
}
class EchoExpression<T> {
private String someString;
private Class<T> someClass;
public EchoExpression(String someString, Class<T> someClass) {
super();
this.someString = someString;
this.someClass = someClass;
}
public String getSomeString() {
return someString;
}
public void setSomeString(String someString) {
this.someString = someString;
}
public Class<T> getSomeClass() {
return someClass;
}
public void setSomeClass(Class<T> someClass) {
this.someClass = someClass;
}
}
class OutExpression {
private String someString;
public OutExpression(String someString) {
super();
this.someString = someString;
}
public String getSomeString() {
return someString;
}
public void setSomeString(String someString) {
this.someString = someString;
}
}
If you can modify the classes so both constructor has the same signature (accepts the same number/type of arguments in the same order), you could do
Constructor constructor = aClass.getConstructor(new Class[]{String.class,Class.class});
Object object= constructor.newInstance(expression, Boolean.class);
for both classes.
This of course means that the class that right now do not need the extra parameter, will have to ignore the passed-in one it was not using before after the change
UPDATE: Here is a possible way of implementing the idea using Factory classes:
public interface ObjectFactory
{
Object create(String expr, Class cls);
}
public class EchoExpressionFactory implements ObjectFactory
{
public EchoExpression create(String expr, Class cls)
{
return new EchoExpression(expr, cls);
}
}
public class OutExpressionFactory implements ObjectFactory
{
public OutExpression create(String expr, Class cls)
{
return new OutExpression(expr);
}
}
public class ExampleFactory {
private static HashMap<String,ObjectFactory> hmap = new HashMap<String,ObjectFactory>();
static
{
hmap.put("echo", new EchoExpressionFactory());
hmap.put("Out", new OutExpressionFactory());
}
public void getExpo(String key,String expression)
{
ObjectFactory factory = map.get(key);
//Constructor implementation for Expression
Object object = factory.create(expression);
Object object= constructor.newInstance(expression, Boolean.class);
return;
}
}

Categories