我在与客户交流时常听到一种常见的误解,认为所有泛型类型信息都会从 Java 类文件中擦除。这是完全不正确的。所有静态泛型信息都被保留,只有关于单个实例的泛型信息被擦除。因此,如果我有一个实现 List<String> 的类 Foo,那么我可以在运行时确定 Foo 实现了以 String 为参数的 List 接口。但是,如果我在运行时实例化一个 ArrayList<String> 实例,我无法通过该实例确定其具体的类型参数(我可以确定 ArrayList 需要类型参数)。在本文中,我将向您展示一些可用的泛型元数据的实际用法,这可以简化策略接口和实现(按其处理的对象类型区分)的创建。
我在许多应用程序中看到的一种模式是使用某种策略接口,其具体实现分别处理特定的输入类型。例如,考虑投资银行业的一个简单场景。任何上市公司都可以发布 公司行为 (Corporate Actions),从而对其股票产生实际变化。其中一个关键例子是股息支付,它按每股向所有股东支付一定数量的现金、股票或财产。在投资银行内部,接收这些事件通知并计算由此产生的权益非常重要,以便使交易账簿保持正确的股票和现金价值。
作为一个具体的例子,考虑持有 1,200,000 股 IBM 股票的 BigBank。IBM 决定派发每股 0.02 美元的股息。因此,BigBank 需要接收股息行动的通知,并在适当的时间更新其交易账簿,以反映新增的 24,000 美元现金。
权益的计算将根据执行的公司行为类型而有很大差异。例如,合并很可能导致一家公司的股票损失,并获得另一家公司的股票。
如果我们考虑这在 Java 应用程序中可能是什么样子,我们可以假设看到类似下面(大大简化)的例子
public class CorporateActionEventProcessor {
public void onCorporateActionEvent(CorporateActionEvent event) {
// do we have any stock for this security?
// if so calculate our entitlements
}
}
关于事件的通知可能通过外部各方的多种机制传入,然后发送到这个 CorporateActionEventProcessor 类。CorporateActionEvent 接口可能通过多种具体类来实现
public class DividendCorporateActionEvent implements CorporateActionEvent {
private PayoutType payoutType;
private BigDecimal ratioPerShare;
// ...
}
public class MergerCorporateActionEvent implements CorporateActionEvent {
private String currentIsin; // security we currently hold
private String newIsin; // security we get
private BigDecimal…