title: java 8 switch case default with break for class type
body: <p>I was looking for switch over type for java, and I found a solution here: <a href="https://stackoverflow.com/questions/29570767/switch-over-type-in-java/37334159#37334159">Switch over type in java</a></p>
  
  <p>But the issue, solution was not really like a <code>switch</code> with <code>break</code>s, sure this will happen because I loop over <code>Consumer</code>s , I want to know a good way to <strong>modify</strong> my current code or <strong>clean alternative</strong> to have something to handle my class type, and <strong>break after handle first match</strong> and the default is to handle the unmatched only ( here it is the parent class <code>StripeObject</code>) .</p>
  
  <p>My business is to handle stripe events from <a href="https://stripe.com/docs/webhooks" rel="nofollow noreferrer">webhooks</a>, I'm using <a href="https://github.com/stripe/stripe-java" rel="nofollow noreferrer">stripe-java</a>, so my code now something like this:</p>
  
  <pre><code>    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("|-&gt; 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 -&gt; Logger.debug(AppUtils.concatStrings("|--&gt; !!! Not Handled StripeObject !!! [", object.toString(), "]")))
          );
      }
  
      private void handleEventObject(Customer customer) {
          Logger.debug(AppUtils.concatStrings("|--&gt; Customer ID &lt;Description&gt; : [", customer.getId(), " &lt;", customer.getDescription(), "&gt;]"));
      }
  
      private void handleEventObject(Card card) {
          Logger.debug(AppUtils.concatStrings("|--&gt; Card ID &lt;Brand&gt; : [", card.getId(), " &lt;", card.getBrand(), "&gt;]"));
      }
  
      private void handleEventObject(Charge charge) {
          Logger.debug(AppUtils.concatStrings("|--&gt; Charge ID &lt;Description , Customer , Amount&gt; : [", charge.getId(), " &lt;", charge.getDescription(), " , ", charge.getCustomer() ," , ", charge.getAmount(), "&gt;]"));
      }
  
      private void handleEventObject(Transfer transfer) {
          Logger.debug(AppUtils.concatStrings("|--&gt; Transfer ID &lt;Description , Destination , Amount&gt; : [", transfer.getId(), " &lt;", transfer.getDescription(), " , ", transfer.getDestination() ," , ", transfer.getAmount(), "&gt;]"));
      }
  
      @SuppressWarnings("unchecked")
      private static &lt;T&gt; void switchType(StripeObject stripeObject, Consumer... consumers) {
          for (Consumer consumer : consumers)
              consumer.accept(stripeObject);
      }
  
      private static &lt;T&gt; Consumer caze(Class&lt;T&gt; clazz, Consumer&lt;T&gt; consumer) {
          return obj -&gt; Optional.of(obj).filter(clazz::isInstance).map(clazz::cast).ifPresent(consumer);
      }
  </code></pre>
  
  <p>In the current code, if the evnet was Customer as example it will print : </p>
  
  <pre><code>|--&gt; Customer ID &lt;Description&gt; ... etc
  </code></pre>
  
  <p>Then </p>
  
  <pre><code>|--&gt; !!! Not Handled StripeObject !!! ... etc
  </code></pre>
  
  <p>It must print only the first line, not the second if match.</p>