java 8 switch case默认为类类型的break

时间:2016-12-15 15:28:55

标签: java lambda java-8

我正在寻找java的切换类型,我在这里找到了一个解决方案:Switch over type in java

但问题是,解决方案并不像switch那样break,确定会发生这种情况,因为我循环了Consumer,我想知道一个好方法< strong>修改我当前的代码或清除替代以便处理我的类类型,并且在处理首次匹配后中断,默认是处理不匹配的只(这里是父类StripeObject)。

我的业务是处理来自webhooks的条带事件,我正在使用stripe-java,所以我的代码现在是这样的:

    public void handleWebHookEvent(Event eventJson) throws CardException, APIException, AuthenticationException, InvalidRequestException, APIConnectionException {
        Stripe.apiKey = configuration.getString(AppConstants.STRIPE_API_KEY);

        // Verify the event by fetching it from Stripe
        Event event = Event.retrieve(eventJson.getId());
        Logger.debug(AppUtils.concatStrings("|-> Event Received: [", event.getId(), "] Type: [", event.getType(), "] Request ID: [", event.getRequest(), "]"));
        handleEventObject(event.getData().getObject());
    }

    private void handleEventObject(StripeObject stripeObject) {
        switchType(stripeObject,
                caze(Customer.class, this::handleEventObject),
                caze(Card.class, this::handleEventObject),
                caze(Charge.class, this::handleEventObject),
                caze(Transfer.class, this::handleEventObject)
                caze(StripeObject.class, object -> Logger.debug(AppUtils.concatStrings("|--> !!! Not Handled StripeObject !!! [", object.toString(), "]")))
        );
    }

    private void handleEventObject(Customer customer) {
        Logger.debug(AppUtils.concatStrings("|--> Customer ID <Description> : [", customer.getId(), " <", customer.getDescription(), ">]"));
    }

    private void handleEventObject(Card card) {
        Logger.debug(AppUtils.concatStrings("|--> Card ID <Brand> : [", card.getId(), " <", card.getBrand(), ">]"));
    }

    private void handleEventObject(Charge charge) {
        Logger.debug(AppUtils.concatStrings("|--> Charge ID <Description , Customer , Amount> : [", charge.getId(), " <", charge.getDescription(), " , ", charge.getCustomer() ," , ", charge.getAmount(), ">]"));
    }

    private void handleEventObject(Transfer transfer) {
        Logger.debug(AppUtils.concatStrings("|--> Transfer ID <Description , Destination , Amount> : [", transfer.getId(), " <", transfer.getDescription(), " , ", transfer.getDestination() ," , ", transfer.getAmount(), ">]"));
    }

    @SuppressWarnings("unchecked")
    private static <T> void switchType(StripeObject stripeObject, Consumer... consumers) {
        for (Consumer consumer : consumers)
            consumer.accept(stripeObject);
    }

    private static <T> Consumer caze(Class<T> clazz, Consumer<T> consumer) {
        return obj -> Optional.of(obj).filter(clazz::isInstance).map(clazz::cast).ifPresent(consumer);
    }

在当前代码中,如果evnet是以客户为例,它将打印:

|--> Customer ID <Description> ... etc

然后

|--> !!! Not Handled StripeObject !!! ... etc

它必须只打印第一行,而不是第二行匹配。

1 个答案:

答案 0 :(得分:4)

您只需更改方法switchTypecaze即可使用Predicate而不是Consumer,因此循环可以在第一次匹配时停止。其余代码不需要任何更改:

@SafeVarargs
private static void switchType(StripeObject so, Predicate<Object>... predicates) {
    for(Predicate<Object> predicate : predicates)
        if(predicate.test(so)) return;
}

private static <T> Predicate<Object> caze(Class<T> clazz, Consumer<T> consumer) {
    return obj -> {
        if(clazz.isInstance(obj)) {
            consumer.accept(clazz.cast(obj));
            return true;
        }
        return false;
    };
}

请注意,这仍然与switch语义不同,因为switch语句通常会排除不明确的情况。在这里,其中一种类型仍然可以是另一种类型的子类型,因此,与switch语句不同,case语句的顺序确实很重要。

如果所有情况都不同,这不是问题。