Java 1.6 -> 1.8,同样的擦除编译错误

Java 1.6 -> 1.8, same erasure compile error

我正在将我的 Java 应用程序从 1.6 移植到 1.8,编译器对以下代码中的方法 getAbstractTransactionCriteria() 不满意:

public abstract class AbstractTransaction ...
public class TemplateTransaction extends AbstractTransaction ...
public class Transaction extends AbstractTransaction ...

abstract class AbstractTransactionCriteria {...}
class TransactionCriteria extends AbstractTransactionCriteria {...}
class TemplateCriteria extends AbstractTransactionCriteria {...}

TransactionCriteria getAbstractTransactionCriteria(Class<Transaction> c) {...}
TemplateCriteria    getAbstractTransactionCriteria(Class<TemplateTransaction> c) {...}

编译器告诉我这两个方法有相同的擦除,我可以接受,因为我在别处看到尖括号内的东西被编译器替换为Object

参数 c 只是为了实现多态性(它们不在方法体中使用)并且这在 Java 1.6.

中曾经完美地工作

我应该怎么做才能在 1.8 中获得相同的结果?

如果您可以随意更改函数原型,并且除了确定 return 类型外不使用参数,那么以下方法对您有用吗?

TransactionCriteria getAbstractTransactionCriteria(Transaction c) {...}
TemplateCriteria    getAbstractTransactionCriteria(TemplateTransaction c) {...}

或者,您可以使用不同的函数名称并让它们不带任何参数。例如

TransactionCriteria getAbstractTransactionCriteria() {...}
TemplateCriteria    getAbstractTemplateCriteria() {...}

为什么不为此使用泛型?像这样:

 public <T extends AbstractTransactionCriteria> T getAbstractTransactionCriteria(Class<T> c) {}
 // or
 public <T extends AbstractTransactionCriteria> T getAbstractTransactionCriteria(T t) {}

这样你只需要一种方法。现在我知道这两种方法可能完全不同(内容方面)。尽管您甚至可以简单地检查传入的参数类型,并相应地执行操作。

编辑:
我提到了静态占位符来支持多态性。 基本上,如果你看到上面的两个方法,一个请求一个 Class 对象,而另一个请求一个实例(通常不太理想,因为你调用这个方法来创建一个实例,而不是传递一个实例)。

如果你不想像上面描述的那样使用genericTypes,你也可以选择这样做:

 abstract class AbstractTransactionCriteria {...}

 // SubClass layout
 class TransactionCriteria extends AbstractTransactionCriteria {
     // dummy instance doing nothing.
     public static final TransactionCriteria type = new TransactionCriteria();
 }

 class TemplateCriteria extends AbstractTransactionCriteria {
     // dummy instance doing nothing.
     public static final TemplateCriteria type = new TemplateCriteria ();
 }



 // method layout
 TransactionCriteria getAbstractTransactionCriteria(TransactionCriteria t)
 {...}

 TemplateCriteria getAbstractTransactionCriteria(TemplateCriteria  t)
 {...}


 // Call methods
 TransactionCriteria transaction = getAbstractTransactionCriteria(TransactionCriteria.type);
 TemplateCriteria transaction = getAbstractTransactionCriteria(TemplateCriteria.type);

如您所见,这样就可以使用您的 'old' 布局。尽管如果这是唯一的方法,我肯定会建议您重新设计当前的模式,因为它绝对不理想。 (如前所述,您可能需要考虑为每种方法使用不同的名称,因为在这种情况下,它们的结果与它们的方法名称所暗示的结果有点 return 不同)