<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <p>There are 3 questions:<br>
      <br>
      (1) should we deprecate `Path::startsWith(String)`?<br>
      (2) should we deprecate `Path::endsWith(String)`?<br>
      (3) should we add a file extension API?<br>
      <br>
      And the TL;DR: no, no, yes.<br>
      <br>
      Let's first establish why `startsWith/endsWith` add tangible
      value:<br>
      because `path.startsWith("foo")` is not equivalent to
      `path.startsWith(Path.of("foo"))`<br>
      and is much more readable than
      `path.startsWith(getFileSystem().getPath("foo"))`.<br>
      <br>
      Next, let's consider why people might want to use String-based
      `startsWith/endsWith` testing on Path instances:<br>
      <br>
      * testing file extensions = 99.9999% of the times: covered by
      `FileSystem::getPathMatcher`<br>
      * testing name elements = 0.0000999% of the times: covered by
      `Path`<br>
      * any other use cases = ~0% of the times: covered by
      `FileSystem::getPathMatcher`<br>
      <br>
      So it is always possible to do without String conversion.<br>
      In fact, it is arguably always a bad idea to do String-based
      testing,<br>
      because `path.toString().endsWith(".java")` will also match a file
      named ".java",<br>
      which on Linux-like OSes would be considered a hidden file named
      "java" that has no file extension.<br>
      So using a dedicated `PathMatcher` for testing file extensions is
      more robust and elegant.<br>
      <br>
      However, when testing file extensions we inevitably start by
      typing `path.`<br>
      (assuming we don't just use a third-party library),<br>
      first notice there's no method `getFileExtension` or such,<br>
      and then notice `endsWith(String)`<br>
      (and maybe we've also noticed `getFileName` and already have
      `path.getFileName().`).<br>
      At this point it's pure psychology:<br>
      we're looking for a method that behaves like String's
      `endsWith(String)`,<br>
      we're looking at a method with the same method signature,<br>
      and we can't imagine that the Path class does *not* have a method
      to test the filename extension,<br>
      so surely this must be it.<br>
      And obviously we ignore any hints at the contrary<br>
      (like our IDE proposing both `endsWith(Path)` and
      `endsWith(String)` for autocompletion).<br>
      And we don't bother to read the Javadoc, because in cases like
      this we can easily verify our assumptions with JShell<br>
      and equally quickly realize our assumptions are wrong.<br>
      <br>
      So yes, this is a common mistake. But this is actually an argument
      for *not* deprecating it.<br>
      Many developers have bumped into this, but as far as I can tell
      the mailing list thread in September was the first in the
      existence of the API.<br>
      And I'm unable to find any previous bug reports either.<br>
      And here's why: when we realized our assumptions were wrong, we
      read the Javadoc, realized our mistake, learned from it, and moved
      on.<br>
      The Javadoc is crystal-clear, the method overloads another method
      with the same behavior, it clearly adds value over the other
      method.<br>
      In other words: we conclude "makes sense" and don't see any reason
      to complain.<br>
      <br>
      To turn this common mistake into a rare-if-ever mistake, I see two
      (combinable) options:<br>
      <br>
      * introduce a file extension API<br>
      * replace `startsWith/endsWith` with methods
      `startsWithNames/endsWithNames`<br>
      <br>
      I don't consider deprecating `startsWith/endsWith` without
      replacement an option because:<br>
      <br>
      * these methods add value (as was also argued by Rob Spoor), so
      it's a net loss for the Java SE APIs.<br>
      And all the people that are happily using these methods today and
      are unaware of this mailing list thread will be unpleasantly
      surprised to see it deprecated<br>
      * this means breaking compilation for everyone that builds with
      "-Werror" and "no usage of deprecated APIs" is a very common
      policy.<br>
      So people will end up adding a duplicate of the deprecated methods
      in their own utility libraries<br>
      * this trades one trap for another, much more subtle trap, since
      people will blindly replace `"foo"` with `Path.of("foo")`.<br>
      (We're having this very discussion because people don't read
      Javadoc.<br>
      So surely we're not expecting people to read the deprecation text
      and follow the recommendations, are we?)<br>
      Eventually they'll notice there's a bug, add `IO.println(foo)` and
      `IO.println(Path.of("foo"))`, notice these both print "foo",<br>
      but somehow `foo.endsWith(Path.of("foo"))` results in `false`,
      eventually find the culprit ... and then notice the deprecated
      `endsWith` method did exactly<br>
      what they wanted all along<br>
      * what would the rationale for the deprecation be? How would you
      document this in the Javadoc?<br>
      Now you might still say: "People who were looking for a file
      extension API regularly ended up here. If you're one of them, use
      Path::toString instead."<br>
      But once a file extension API will be available, it'll be
      extremely hard to come up with a reasonable justification for the
      deprecation.<br>
      And as argued above, simple String-based comparisons are rarely,
      if ever, the most robust solution<br>
      * for `startsWith` in particular: the only argument to deprecate
      it seems to be "for the sake of symmetry"<br>
      <br>
      Anthony</p>
    <div class="moz-cite-prefix">On 1/12/2026 8:36 PM, Stuart Marks
      wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:3316a206-c9c3-4bc0-896a-2e5a03c9b472@oracle.com">
      
      <p>Let's not tie these two issues together.</p>
      <p>The discussion clearly shows that the
        startsWith/endsWith(String) APIs are a trap that several people
        have fallen into. On that basis it should be deprecated.
        (Ordinarily, so as to emit a warning, and not for removal, so
        there won't be any compatibility issue.)</p>
      <p>There is also no requirement that a new API be introduced to
        replace any deprecated API. As the earlier discussion in the
        thread shows, both the path-based and the string-based use cases
        can be written using existing APIs, somewhat less conveniently
        and more verbosely; but these constructs are much more explicit
        and so are preferable to the APIs to be deprecated. The
        deprecation text should steer people toward the preferred
        constructs.<br>
      </p>
      <p>It would indeed be nice to have a file extension API, but this
        has been discussed several times and has run aground each time
        for a variety of reasons. Tying these together will hold up the
        deprecation for no good reason.</p>
      <p>Let's proceed with just the deprecation first and work on the
        file extension API separately.</p>
      <p>s'marks<br>
      </p>
      <div class="moz-cite-prefix">On 1/11/26 12:45 PM, David Alayachew
        wrote:<br>
      </div>
      <blockquote type="cite" cite="mid:CAA9v-_N24Mv5+JabZQHjuyMZVBCHE4c-_y2ByQ6omxQwyYbD3A@mail.gmail.com">
        <div dir="ltr">
          <div class="gmail_default" style="font-family:monospace">Thanks
            for the response Anthony. Messages have been arriving
            out-of-order for me, so I didn't see yours at the time of me
            writing that message.</div>
          <div class="gmail_default" style="font-family:monospace"><br>
          </div>
          <div class="gmail_default" style="font-family:monospace">I
            think introducing the file extension API first, then gauging
            the need for a deprecation before doing it is fine. Sounds
            like then that we are universally agreed on the first step
            being to add the file extension API, yes?</div>
        </div>
        <br>
        <div class="gmail_quote gmail_quote_container">
          <div dir="ltr" class="gmail_attr">On Sun, Jan 11, 2026 at
            2:06 PM Anthony Vanelverdinghe <<a href="mailto:anthonyv.be@outlook.com" moz-do-not-send="true" class="moz-txt-link-freetext">anthonyv.be@outlook.com</a>>
            wrote:<br>
          </div>
          <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
            <div>
              <p>I dissent. (Apparently my previous message wasn't
                clear.)<br>
                <br>
                The right order of things is to first introduce a file
                extension API. Then see if there's still complaints
                about `Path::endsWith(String)`. And only then, if there
                are, consider taking action.<br>
                <br>
                In my previous message I've already explained how these
                methods add real, tangible value and actually are
                intuitive.<br>
                (Again, ask developers to guess how `A::foo(B)` behaves,
                given that both `A::foo(A)` and `B::foo(B)` exist, and a
                large majority of them will intuitively guess it
                converts its `b` argument to an instance of `A` and
                passes it on to `A::foo(A)`. And their intuition would
                be correct in the case of `Path::endsWith(String)`. That
                being said, I'll be the first to admit that I've also
                made the mistake of attempting to use
                `Path::endsWith(String)` to test the file extension.)<br>
                <br>
                In hindsight, maybe `endsWithNames(String)` would've
                been a better choice, but hindsight is 20/20.<br>
                <br>
                Deprecating these methods now is premature. And
                deprecating them without replacement methods would
                result in way more complaints than there have ever been
                about `endsWith(String)`.<br>
                <br>
                Anthony</p>
              <div>On 1/11/2026 12:19 AM, David Alayachew wrote:<br>
              </div>
              <blockquote type="cite">
                <div dir="auto">Of course.
                  <div dir="auto"><br>
                  </div>
                  <div dir="auto">I see lots of approvals and not really
                    any dissenters. Are we waiting for more responses?
                    Or is there anything we can do to kick start this?</div>
                </div>
                <br>
                <div class="gmail_quote">
                  <div dir="ltr" class="gmail_attr">On Fri, Jan 9, 2026,
                    10:22 PM Brian Burkhalter <<a href="mailto:brian.burkhalter@oracle.com" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">brian.burkhalter@oracle.com</a>>
                    wrote:<br>
                  </div>
                  <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
                    <div> Thanks for the corroboration.<br id="m_-8914463101179384457m_-726007501657283544lineBreakAtBeginningOfMessage">
                      <div><br>
                        <blockquote type="cite">
                          <div>On Jan 8, 2026, at 1:50 PM, David
                            Alayachew <<a href="mailto:davidalayachew@gmail.com" rel="noreferrer" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">davidalayachew@gmail.com</a>>
                            wrote:</div>
                          <br>
                          <div><span style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration:none;float:none;display:inline">Thanks
                              for reviving this.</span>
                            <div dir="auto" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration:none">
                              <br>
                            </div>
                            <div dir="auto" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration:none">
                              I am perfectly happy with the idea of
                              deprecating the
                              Path.{start,ends}With(String), and then
                              only add the file extension method.
                              Originally, I didn't know that new method
                              was on the table, so I suggested a rename.
                              But the file extension api feels like the
                              superior solution.</div>
                            <div dir="auto" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration:none">
                              <br>
                            </div>
                            <div dir="auto" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration:none">
                              10 times out of 10, if I am calling
                              endsWith, the only time I am not looking
                              for "whole" path elements is when I am
                              looking for a file extension. In every
                              other instance, the api does exactly what
                              I expect and want. And plus, something
                              like looking for a file extension is
                              better off being explicit.</div>
                          </div>
                        </blockquote>
                      </div>
                    </div>
                  </blockquote>
                </div>
              </blockquote>
            </div>
          </blockquote>
        </div>
      </blockquote>
    </blockquote>
  </body>
</html>