2

I have this code

List<JComponent> myList = new ArrayList<>();
fillmyList(myList); //Some method filling the list
try{
    menuList.stream()
    .filter(m->m.getClass().getMethod("setFont", new Class[]{Font.class}) != null) //unreported exception NoSuchMethodException; must be caught or declared to be thrown
    .forEach(m -> m.setFont(someFont));
}
catch (NullPointerException |  NoSuchMethodException e) {} //exception NoSuchMethodException is never thrown in body of corresponding try statement

But, I have this error messages:

Exception in thread "AWT-EventQueue-0" java.lang.RuntimeException: Uncompilable source code - exception java.lang.NoSuchMethodException is never thrown in body of corresponding try statement

How solve this?

shmosel
  • 49,289
  • 6
  • 73
  • 138
  • You need to catch it the body of the lambda function. – Oliver Charlesworth Feb 28 '18 at 20:21
  • Please show me how to do that... –  Feb 28 '18 at 20:22
  • Your logic is flawed. `getMethod()` will never return null. – shmosel Feb 28 '18 at 20:24
  • Note that getMethod never returns null, that all JComponents have a setFont() method since it's declared in JComponent, that NullPointerException should never, ever be caught, and the catch blocks should never, ever be empty: that just hides bugs and makes them very hard to diagnose. This code doesn't make sense. – JB Nizet Feb 28 '18 at 20:31
  • Thank you, I'm working with JMenu, JPopupMenu, has items, and Separator.... –  Feb 28 '18 at 20:38
  • So you’re working with `JMenu`, `JPopupMenu`, “has items”?!, and `Separator` and all of them are subclasses of `Component` and have a `public` `setFont(Font)` method. There is no need for Reflection here. Perhaps, your problem is connected to the actual type of `menuList`. You should include it in your question. – Holger Mar 01 '18 at 10:32
  • 1
    @JBNizet it took me a while to realize that this code is actually invoking the `setFont` method without Reflection in `.forEach(m -> m.setFont(someFont))` which makes the entire `filter` step even more nonsensical, as the compiler already states that the `setFont` method is always present for all stream elements… – Holger Mar 01 '18 at 10:54
  • @Holger indeed. Didn't notice that until I read your comment. – JB Nizet Mar 01 '18 at 11:58

1 Answers1

2

It is not an exception but a compilation error.
You have to catch the lambda body that may throw the exception, not the whole stream.

Here is an example to return false in filter() for the element of the stream that has thrown the exception :

myList.stream()
      .filter(m -> {
          try {
              return m.getClass()
                      .getMethod("setFont", new Class[] { Font.class }) != null;
          } catch (NoSuchMethodException | SecurityException e) {
              // log the exception
              return false;
          }
      })

You may of course use a different strategy as throwing a RuntimeException and stopping the processing.

davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • 1
    Mind that it’s not necessary to wrap `Font.class` with `new Class[] { Font.class }` as `getMethod` is a *varargs* method. – Holger Mar 01 '18 at 10:27