简体   繁体   English

在Java中使用反射来设置方法的参数

[英]Using reflection in Java to set a method's parameters

I am trying to achieve something approximating the following: 我正在尝试实现一些近似的方法:

public class MyClass<E>
{
    protected MyClass(Object[] variables)
    {
        //init
    }

    public MyClass(Comparator<? super E> comp, Object[] variables)
    {
        //init
    }

    public static <K extends Comparable<? super K>, T extends MyClass<K>> 
         T construct(T example, Object[] variables)
    {
        return new T(variables);
    }
}

Where the Object[] variables is not the actual code, but rather a placeholder for whatever the actual parameters for construction are. 其中Object []变量不是实际代码,而是占位符(无论构造的实际参数是什么)。

Therein lies my question. 我的问题就在这里。 I have seen plenty of examples, both with and without reflection, of how to do this when the parameters of T's constructor are known ahead of time, and can thus be specified within construct's parameters. 我已经看到了无数个示例,无论有无反射,当T的构造函数的参数提前已知并且可以在构造的参数中指定时,该如何做。 However, I would like to be able to do this even when the parameters of T's constructor are unknown. 但是,即使T的构造函数的参数未知,我也希望能够做到这一点。 Is there a way to do this? 有没有办法做到这一点?

I don't particularly care if the solution uses reflection or not so long as it works, but reflection seemed the most likely option. 只要解决方案有效,我都不在乎该解决方案是否使用反射,但是反射似乎是最可能的选择。

I am fairly new to reflection as a whole, so I apologize if this question is fairly basic. 我对整体反思还很陌生,因此如果这个问题很基本,我深表歉意。

Edit: Due to feedback that there is no way to dynamically set the parameters of construct() I would like to alter the question slightly. 编辑:由于反馈,没有办法动态设置construct()的参数,我想稍微改变一下问题。

Assuming that the protected constructor has the required parameters for the class's construction, if I use a vararg (public static <K extends Comparable<? super K>, T extends MyClass<K>> T construct(T example, Object... variables)) what would be the best way of ensuring that the arguments passed in to variables match the parameters required for the constructor? 假定受保护的构造函数具有构造类所需的参数,如果我使用vararg (public static <K extends Comparable<? super K>, T extends MyClass<K>> T construct(T example, Object... variables))确保传递给变量的参数与构造函数所需的参数匹配的最佳方法是什么? I had hoped to do this dynamically, because then the compiler itself would prevent such issues, but without this possibility I ask for the best alternate solution. 我曾希望动态地执行此操作,因为这样编译器本身可以避免此类问题,但是如果没有这种可能性,我会寻求最佳的替代解决方案。

Edit: For clarification, this is my actual goal: I want MyClass to accept either a parameterization, E, that extends Comparable or any parameterization, but have a Comparator passed in. I can achieve the second goal simply through a constructor, but in order to leave E open to any option in the second case, I have to leave it open to any option overall. 编辑:为了澄清,这是我的实际目标:我想MyClass的能够接受一个参数,E,扩展相当任何参数,但有一个比较在过去,我可以简单地通过构造实现第二个目标,但为了。为了让E在第二种情况下对任何选项都开放,我必须对所有选项都保持开放。 To deal with this, I made the general constructor protected and made a public static method to force the Comparable implementation and act as a pseudo-constructor, with the return type being MyClass where K is Comparable. 为了解决这个问题,我使通用构造函数受到保护,并制作了一个公共静态方法来强制Comparable实现并充当伪构造函数,返回类型为MyClass,其中K是Comparable。 However, this causes problems when another class extends MyClass. 但是,这会在另一个类扩展MyClass时引起问题。 If I know beforehand that the inheriting class will have the same parameters as MyClass, then I can simply hide the method and alter the return type accordingly. 如果我事先知道继承的类将具有与MyClass相同的参数,那么我可以简单地隐藏该方法并相应地更改返回类型。 But if I want to have the subclass have different parameters, then I've altered the signature of the method and can no longer use it to hide the previous one, meaning that the subclass can not only return an instance of itself, but also a completely different instance of its parent. 但是,如果我想让子类具有不同的参数,那么我已经更改了方法的签名,并且不再可以使用它来隐藏前一个方法,这意味着子类不仅可以返回自身的实例,还可以返回一个实例。其父实例完全不同。 This is what I would like to try to avoid. 这是我想避免的。

This may work, but I would not recommend it. 这可能有效,但我不建议这样做。 Note, for this to work example and all members of variables MUST BE not null 请注意,要使该example正常工作, variables所有成员都不得为null

public static <K extends Comparable<? super K>, T extends MyClass<K>> 
     T construct(T example, Object[] variables) throws 
                 NoSuchMethodException,
                 SecurityException,
                 InstantiationException,
                 IllegalAccessException,
                 IllegalArgumentException,
                 InvocationTargetException 
{
    Objects.requireNotNull(example);

    Class<?>[] argTypes = new Class<?>[variables.length];
    for ( int i = 0; i < variables.length; ++i)
    {
        // This will NPE if variables[i] is null
        argTypes[i] = variables[i].getClass();
    }

    // This will throw, if constructor is not defined
    Constructor<?> constructor = example.getClass().getConstructor(argTypes);

    return (T) constructor.newInstance(variables);
}

Usually, what you are doing, can be achieved by creating a Factory interface that creates instances of specific class. 通常,您正在执行的操作可以通过创建一个创建特定类实例的Factory接口来实现。

I don't think you need to go into reflection. 我认为您不需要反思。 You just need to simplify what you need and use the power of java and generics for your needs. 您只需要简化所需的内容,并使用Java和泛型的功能来满足您的需求。 Here is an example according to your third edit: 这是根据您的第三个编辑的示例:

class MyClass<E> {
    private Comparator<MyClass<E>> comparator;

    public MyClass(List<Object> params, Comparator<MyClass<E>> comparator) {
        //init
        this.comparator = comparator;
    }

}
class  MyClassExtension extends MyClass<Integer> {

    public MyClassExtension(List<Object> params, Comparator<MyClass<java.lang.Integer>> comparator) {
        super(params, comparator);
    }
}
class  MyClassExtension2<E> extends MyClass<E> {

    public MyClassExtension2(List<Object> params, Comparator<MyClass<E>> comparator) {
        super(params, comparator);
    }
}

I think I may have realized a potential solution on my own, though I would like feedback as to it's viability. 我想我可能已经实现了一个潜在的解决方案,尽管我希望获得有关其可行性的反馈。

public class MyClass<E>
{
    public MyClass(Comparable<? super E> example, E example2, Object[] variables) 
      throws IllegalArgumentException
    {
        if(!example.getClass().equals(example2.getClass())
        {
             throw new IllegalArgumentException();
        }
        //init
    }

    public MyClass(Comparator<? super E> comp, Object[] variables)
    {
        //init
    }
}

The idea is that the if statement forces example to be the same class as the generic E, and the presence of example as a parameter forces that class to implement Comparable. 这个想法是,if语句强制example与通用E属于同一类,而example作为参数的存在强制该类实现Comparable。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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