Generate an instantiable class based on a static class reflectively

不打扰是莪最后的温柔 提交于 2021-02-15 07:42:12

问题


Can I (using reflection I presume?) create a class with all the same method names as java.lang.Math and each method just forwards it to Math?

E.g.

public class MyMath {
  public MyMath() {}

  public double abs(double a) {
    return Math.abs(a);
  }

  public float abs(float a) {
    return Math.abs(a);
  }

  public int abs(int a) {
    return Math.abs(a);
  }

  ...

  public double acos(double a) {
    return Math.acos(a);
  }
  
  ...

How could I generate this programmatically?


回答1:


You can do this with reflection to get an instance of class Math:

try {
    Constructor[] cs = Math.class.getDeclaredConstructors();
    cs[0].setAccessible(true);
    Math m = (Math) cs[0].newInstance();
    //e.g.
    System.out.println(m.sqrt(16));
}
catch (Exception e) {
    e.printStackTrace();
}

Whether this is a sensible thing to do is another question.




回答2:


Yes, you can. However, not the way you want it to be I'm afraid.

There are some libraries that you can use to generate dynamic classes at runtime (such as cglib). In order to do so, first, you must define an interface that contains every method definition in Math class.

Here is an example:

public interface MathProxy
{

    double cos(double a);

    double tan(double a);

    double log(double a);

    double log10(double a);

    double sqrt(double a);

    double cbrt(double a);

    double pow(double a, double b);

    double random();

    // other methods are listed as well

}

Then, using cglib, you can create a proxy object that delegates all methods to the original Math class:

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class MathEnhancer
{

    public static void main(String[] args)
    {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(MathProxy.class);
        enhancer.setCallback(new MethodInterceptor()
        {
            @Override
            public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable
            {
                Method actualMethod = Math.class.getDeclaredMethod(method.getName(), method.getParameterTypes());
                return actualMethod.invoke(null, args);
            }
        });

        MathProxy mathProxy = (MathProxy) enhancer.create();
        System.out.println(mathProxy.pow(2, 8));
    }

}

This will print out 256.0 to console.



来源:https://stackoverflow.com/questions/65937379/generate-an-instantiable-class-based-on-a-static-class-reflectively

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!