简体   繁体   English

类的Java通用枚举器

[英]Java Generic Enumerator for classes

I want to create an enumerator with classes to get these classes in further code but I can't. 我想用类创建一个枚举器,以在进一步的代码中获取这些类,但是我不能。 I'll explain on example what I want to do: 我将在示例中说明我想做什么:

public enum SomeEnumeratorForClasses {
  FIRST_CLASS( "Name 1", FirstClass.class ),
  SECOND_CLASS( "Name 2", SecondClass.class );

  private String name;
  private Class<T> response;

  SomeEnumeratorForClasses ( String name, Class<T> clazz ) {...}

  public Class<T> getResponse() {
    return response;
  }
}

For example each class first/second has some fields/method example: 例如,每个类的第一个/第二个都有一些字段/方法示例:

getDescription()

And finally in other class I want something like that: 最后,在其他班级,我想要这样的事情:

SomeEnumeratorForClasses.FIRST_CLASS.getResponse().getDescription();

But I can't do it. 但是我做不到。 Each class inherit from other base class Zero.class example: 每个类都继承自其他基类Zero.class示例:

FirstClass extends Zero
SecondClass extends Zero

I try do this also instead 我也尝试这样做

private Class<T> response;

use this: 用这个:

private Class<? extends Zero> response;

But still doesn't work. 但是仍然不起作用。

Method getDescription is not static, is a public String for example: 方法getDescription不是静态的,例如是一个公共字符串:

class FirstClass {
  public String getDescription() {
    return "Text";
  }
}

Some methods like getDesciptions are abstract in Zero class. 诸如getDesciptions之类的某些方法在Zero类中是抽象的。 How can I do it? 我该怎么做?

If you know that each class shares a constructor signature (preferably a public no-args version), you can write a function that instantiates them. 如果您知道每个类都共享一个构造函数签名(最好是一个公共的无参数版本),则可以编写一个实例化它们的函数。

public class ObjectUtils {
    private ObjectUtils(){}

    public static <T> T init(Class<T> clazz, Object... args) {
        try {

            return (T) Arrays.stream(clazz.getConstructors())
                    .filter(construct -> Objects.equals(args.length, construct.getParameterCount()))
                    .filter(construct -> IntStream.range(0, construct.getParameterTypes().length)
                            .allMatch(val -> construct.getParameterTypes()[val].isAssignableFrom(args[val].getClass())))
                    .findFirst().orElseThrow(() -> new InstantiationException("Could not find compatible constructor."))
                    .newInstance(args);

        } catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
            throw new RuntimeException("Could not instantiate class for provided arguments.", e);
        }
    }
}

Now, your enum could look like: 现在,您的枚举可能看起来像:

public enum SomeEnumeratorForClasses {
  FIRST_CLASS( "Name 1", FirstClass.class ),
  SECOND_CLASS( "Name 2", SecondClass.class );

  private String name;
  private Class<? extends Zero> responseClass;

  SomeEnumeratorForClasses ( String name, Class<? extends Zero> responseClass ) {
       this.name = name;
       this.responseClass = responseClass;
  }

  public <T extends Zero> T getResponse() {
    return ObjectUtils.init(responseClass);
  }
}

And use it like so: 并像这样使用它:

SomeEnumeratorForClasses.FIRST_CLASS.getResponse().getDescription();

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

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