为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕仙森 2022-10-26 17:19:20
我正在尝试实现近似于以下内容: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);    }}Object[] 变量不是实际代码,而是构造的实际参数的占位符。我的问题就在于此。我已经看到很多例子,无论有没有反射,当 T 的构造函数的参数提前知道时如何做到这一点,因此可以在构造的参数中指定。但是,即使 T 的构造函数的参数未知,我也希望能够做到这一点。有没有办法做到这一点?我并不特别关心解决方案是否使用反射,只要它有效,但反射似乎是最有可能的选择。作为一个整体,我对反思相当陌生,所以如果这个问题相当基本,我深表歉意。编辑:由于反馈无法动态设置construct()我想稍微改变问题的参数。假设受保护的构造函数具有类构造所需的参数,如果我使用vararg (public static <K extends Comparable<? super K>, T extends MyClass<K>>              T construct(T example, Object... variables))确保传递给变量的参数与构造函数所需的参数匹配的最佳方法是什么?我曾希望动态地执行此操作,因为编译器本身会防止此类问题,但如果没有这种可能性,我要求最好的替代解决方案。编辑:为澄清起见,这是我的实际目标:我希望 MyClass 接受扩展 Comparable 的参数化E或任何参数化,但传入一个 Comparator。我可以简单地通过构造函数实现第二个目标,但是为了让 E 在第二种情况下对任何选项开放,我必须将它对任何选项开放。为了解决这个问题,我对通用构造函数进行了保护,并创建了一个公共静态方法来强制 Comparable 实现并充当伪构造函数,返回类型为 MyClass,其中 K 是 Comparable。但是,当另一个类扩展 MyClass 时,这会导致问题。如果我事先知道继承类将具有与 MyClass 相同的参数,那么我可以简单地隐藏该方法并相应地更改返回类型。但是如果我想让子类有不同的参数,那么我已经改变了方法的签名,不能再用它来隐藏前一个,这意味着子类不仅可以返回自己的实例,还可以返回其父类的完全不同的实例。这是我想尽量避免的。
查看完整描述

3 回答

?
摇曳的蔷薇

TA贡献1793条经验 获得超6个赞

我认为你不需要进行反思。您只需要简化您的需求并使用 java 和泛型的强大功能来满足您的需求。这是根据您的第三次编辑的示例:


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);

    }

}


查看完整回答
反对 回复 2022-10-26
?
拉风的咖菲猫

TA贡献1995条经验 获得超2个赞

我想我自己可能已经意识到了一个潜在的解决方案,尽管我希望得到关于它的可行性的反馈。


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

    }

}

这个想法是 if 语句强制example成为与泛型 E 相同的类,并且example作为参数的存在强制该类实现 Comparable。


查看完整回答
反对 回复 2022-10-26
?
ibeautiful

TA贡献1993条经验 获得超5个赞

这可能有效,但我不建议这样做。请注意,要使其正常工作,必须不是example所有成员variablesnull


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);

}

通常,您正在做的事情可以通过创建一个创建特定类实例的工厂接口来实现。


查看完整回答
反对 回复 2022-10-26
  • 3 回答
  • 0 关注
  • 132 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信