flamasterrr
flamasterrr

Reputation: 315

Why can't I pass lambda inline into try-with-resources

Help me understand why the following code doesn't compile. AutoCloseable is a single abstract method interface and I am able to assign it to lambda expression, just not in try-with-resources context:

class Main {
  public static void main(String[] args) {
    try (AutoCloseable test = () -> System.out.println("Closing")) {}
  }
}

I'm getting following compilation error and trying to wrap my head around - why?

error: unreported exception Exception; must be caught or declared to be thrown

exception thrown from implicit call to close() on resource variable 'test'

Upvotes: 0

Views: 109

Answers (2)

Slaw
Slaw

Reputation: 45816

Your problem is not due to implementing java.lang.AutoCloseable as a lambda. That interface, at least as of Java 23, only has a single abstract method and is therefore capable of being implemented as a lambda expression or method reference.

The problem is that a try-with-resources statement will automatically and implicitly call close(), and that method is declared to be able to throw Exception. That is a checked exception type which means you must explicitly handle it.

There are two solutions (not including using or creating your own subtype of AutoCloseable; see this answer).

1) Declare the caller method to be able to throw Exception
class Main {
  // Declare that 'main' can also throw Exception
  public static void main(String[] args) throws Exception {
    try (AutoCloseable test = () -> System.out.println("Closing")) {}
  }
}
2) Catch the exception
class Main {
  public static void main(String[] args) {
    try (AutoCloseable test = () -> System.out.println("Closing")) {
    } catch (Exception ex) {
      // handle 'ex'
    }
  }
}

Upvotes: 4

tquadrat
tquadrat

Reputation: 4044

Option 3 for the answer here would be to define your own implementation of java.lang.AutoCloseable where the method close() does not declare an exception at all:

public interface MyCloseable extends AutoCloseable
{ 
  @Override
  public void close();
}

public static final void main( final String... args )
{
  try( final MyCloseable test = () -> System.out.println( "Closing" ) ) 
  { /*Do something*/ }
} 

Upvotes: 4

Related Questions