The Java compiler is throwing a "Types are not compatible" error when you try to use a try-with-resources statement because the object you’re trying to manage doesn’t implement the AutoCloseable interface.

Here’s what’s actually broken: The try-with-resources statement is a syntactic sugar for ensuring that resources implementing AutoCloseable are automatically closed when the try block finishes, whether normally or via an exception. If the object you’re using isn’t AutoCloseable, the compiler has no guarantee it can be safely closed, hence the type incompatibility.

Common Causes and Fixes

1. Resource Doesn’t Implement AutoCloseable (or Closeable)

  • Diagnosis: Inspect the class definition of the resource you’re trying to use in the try-with-resources statement. Check its implements clause.
  • Fix:
    • If you control the class: Add implements AutoCloseable to the class declaration. Implement the close() method, even if it’s empty, or delegate to an existing close method if one exists.
      public class MyResource implements AutoCloseable {
          // ... existing code ...
          @Override
          public void close() {
              System.out.println("MyResource closed.");
              // Add actual closing logic here if needed
          }
      }
      
    • If you don’t control the class: Create a wrapper class that does implement AutoCloseable and holds an instance of your original resource. The wrapper’s close() method will then call the resource’s original closing method.
      public class AutoCloseableWrapper implements AutoCloseable {
          private final NonAutoCloseableResource delegate;
      
          public AutoCloseableWrapper(NonAutoCloseableResource resource) {
              this.delegate = resource;
          }
      
          @Override
          public void close() {
              System.out.println("Closing NonAutoCloseableResource via wrapper.");
              delegate.dispose(); // Assuming dispose() is the closing method
          }
      }
      
  • Why it works: This explicitly tells the Java runtime that the object can be managed by the try-with-resources mechanism, ensuring its close() method is called.

2. Using an Anonymous Inner Class That Doesn’t Implement AutoCloseable

  • Diagnosis: You’re creating an anonymous inner class instance directly within the try-with-resources declaration, and that class definition doesn’t implement AutoCloseable.
  • Fix: Ensure the anonymous inner class explicitly implements AutoCloseable and provides a close() method.
    try (MyService service = new MyService() {
        @Override
        public void doSomething() {
            System.out.println("Doing something...");
        }
    
        @Override // Explicitly implement close()
        public void close() {
            System.out.println("MyService anonymous instance closed.");
            // Add close logic if necessary
        }
    }) {
        service.doSomething();
    }
    
  • Why it works: The anonymous class becomes a concrete implementation of AutoCloseable, satisfying the compiler’s requirement.

3. Incorrectly Casting a Resource

  • Diagnosis: You have an object that is AutoCloseable, but you’re trying to cast it to a type that is not AutoCloseable within the try-with-resources statement.
  • Fix: Remove the incorrect cast or ensure the type you’re casting to also implements AutoCloseable.
    // Assume 'someResource' is AutoCloseable
    AutoCloseable autoCloseableResource = getResource();
    
    // Incorrect: Casting to a non-AutoCloseable type
    // try (NonAutoCloseableType typedResource = (NonAutoCloseableType) autoCloseableResource) { ... }
    
    // Correct: Use the AutoCloseable type directly
    try (AutoCloseable typedResource = autoCloseableResource) {
        // ...
    }
    
  • Why it works: The try-with-resources statement operates on the declared type of the resource. If that type is AutoCloseable, the compiler is satisfied.

4. Using a Lambda Expression That Doesn’t Return AutoCloseable

  • Diagnosis: You’re using a lambda expression to create your resource, and the lambda’s return type is not AutoCloseable.
  • Fix: Ensure the lambda expression returns an instance of a type that implements AutoCloseable.
    import java.util.stream.Stream;
    import java.io.Reader;
    import java.io.StringReader;
    
    // Assume a factory method that returns a Reader (which is AutoCloseable)
    Supplier<Reader> readerSupplier = () -> new StringReader("some data");
    
    try (Reader r = readerSupplier.get()) {
        int charCode;
        while ((charCode = r.read()) != -1) {
            System.out.print((char) charCode);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    
  • Why it works: The lambda’s execution result is what’s placed into the try-with-resources variable, and that result must be AutoCloseable.

5. Using a static Method Reference That Doesn’t Return AutoCloseable

  • Diagnosis: Similar to lambda expressions, if you’re using a method reference for a static method that doesn’t return an AutoCloseable, you’ll get this error.
  • Fix: Ensure the static method being referenced returns an object that implements AutoCloseable.
    import java.util.stream.Stream;
    import java.io.Reader;
    import java.io.StringReader;
    
    // Assume a static factory method that returns a Reader
    Supplier<Reader> readerSupplier = StringReader::new; // StringReader is AutoCloseable
    
    try (Reader r = readerSupplier.get()) {
        int charCode;
        while ((charCode = r.read()) != -1) {
            System.out.print((char) charCode);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    
  • Why it works: The method reference resolves to a way of obtaining an AutoCloseable resource.

6. Resource is a Primitive or null

  • Diagnosis: You’re mistakenly trying to put a primitive type (like int, boolean) or null into the try-with-resources statement.
  • Fix: Ensure the resource you are trying to manage is a non-null object reference that implements AutoCloseable.
    // Incorrect:
    // int count = 0;
    // try (count) { ... }
    
    // Correct:
    try (java.util.zip.ZipFile zipFile = new java.util.zip.ZipFile("myarchive.zip")) {
        // ...
    } catch (IOException e) {
        e.printStackTrace();
    }
    
  • Why it works: try-with-resources is designed for managing objects that have a lifecycle requiring explicit closing, not for primitive values or null.

The next error you’ll likely encounter after fixing this is a NullPointerException if your resource variable was intended to be null but the try-with-resources logic now attempts to call close() on it, or an IOException if the close() method itself throws an error during execution.

Want structured learning?

Take the full Java course →