繁体   English   中英

将类传递给方法以实例化泛型

[英]Passing Class to a method to instantiate a generic

以下代码不起作用,因为标记的行无法编译:

MyClass {
    //singleton stuff
    private static MyClass instance;
    private MyClass () {}
    public static MyClass getInstance() {
        if(instance==null) {
            instance = new MyClass ();
        }
        return instance;
    }

    // method creating problems
    public NonGenericSuperClassOfGenericClass create(Class<?> c1, Class<?> c2) {
        return new GenericClass<c1,c2>; // DOES NOT COMPILE!!!
    }
}

我不希望MyClass是泛型的。 为什么? 因为创建方法的实际实现类似于以下内容:

    // method creating problems
    public NonGenericSuperClassOfGenericClass create(Class<?>... classes) {
        if(someCondition)
             return new GenericClass<classes[0],classes[1]>;
        else
             return new OtherGenericClass<classes[0]>;
}

因此,我不能将MyClass耦合到任何特定的泛型。 有没有办法通过传递的参数实例化我的GenericClass? 怎么样?

谢谢


谢谢您的回答。 我会告诉你整个故事。

我正在使用Spring,并且打算使用MongoDB

类GenericClass类似于:

 GenericClass<PersistetType1, Long> 

要么

 GenericClass<PersistentType2, Long>

其中PersistentType1 / 2是我最终需要存储在数据库中的类,而GenericClass是一种访问Mongo API的代理。 实际上,它看起来像:

  public MongoTemplate getTemplate();
  public void save(T toInsert);
  public List<T> select(Query selectionQuery);
  public T selectById(ID id);
  public WriteResult update(Query selectionQuery, Update updatedAttributes);
  public void delete(T toRemove);
  public void delete(Query selectionQuery);

怎么办? 从控制器(或实体,如果您很挑剔),我需要实例化存储库并调用任何方法。 这导致控制器与MongoDB耦合,也就是说,它们必须明确实例化此类GenericClass,该类实际上称为MongoRepository,并且严格依赖于Mongo(实际上,它是具有两个“自由度”的泛型)。

因此,我决定创建MyClass,这是隔离Controllers的另一个代理。 通过这种方式,Controller可以获取MyClass的单​​个实例,并使其创建相应存储库的新实例。 特别是,当“ somecondition”为true时,这意味着我们要使用MongoRepository(如果为false,则可能需要实例化一个Hibernate代理,即HibernateRepository)。 但是,MongoRepository是通用的,因此它需要某种形式的实例化,我希望将其作为参数传递。

不幸的是,泛型在编译时已解决,因此我猜它们对我不起作用。

我该如何解决?

这没有意义,尤其是在Java中。

泛型的全部要点是在编译时指定类型是什么。

如果您直到运行时都不知道类型是什么,由于类型擦除,Java泛型将毫无用处。 (在C#中,您需要进行反思)

由于类型擦除 ,第一个实现只能考虑原始类型实现。

// Similar to original method
@SuppressWarnings("rawtypes")
public Map<?, ?> create(Class<?> c1, Class<?> c2) {
    return new HashMap();
}

更加干净的替代方法如下:

// A more generic alternative
public <S, T> Map<S, T> create2(Class<? extends S> c1, Class<? extends T> c2) {
    return new HashMap<S, T>();
}

两种实现在运行时都做完全相同的事情。 第二个更好,因为其签名取决于其参数(而create返回Map<?, ?> ,第二个可能返回Map<String, Integer>

无需在运行时传递Class对象。 泛型纯粹是编译时。 因为(看起来)您正在返回一个非泛型类型,所以无论如何您都将泛型参数丢弃(我不知道您为什么要这样做;但是既然如此,我将继续使用它)用作参数无关紧要。 任何通过类型检查器的类型参数就足够了:

public NonGenericSuperClassOfGenericClass create() {
    if(someCondition)
         return new GenericClass<Object,Object>();
    else
         return new OtherGenericClass<Object>();
}

我想到的一件事是:

public NonGenericSuperClassOfGenericClass create(Class<?>... classes) {
    if(someCondition)
         return new helper1(classes[0],classes[1]);
    else
         return new helper2(classes[0]);
}

public <R,T> GenericClass<R,T> helper1( Class<R> a, Class<T> b ){
    return new GenericClass<R,T>();
}

public <T> OtherGenericClass<T> helper2( Class<T> a ){
    return new OtherGenericClass<T>();
}

方法是使用另一个泛型参数化泛型参数:T1>。 这样,我就可以获得所需的耦合。 适当选择AnotherClass可以得到预期的结果。

暂无
暂无

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

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