Can we deprecate Path.endsWith(String)?

Stuart Marks stuart.marks at oracle.com
Thu Jan 8 00:36:04 UTC 2026


On 1/7/26 12:34 PM, Brian Burkhalter wrote:
> Resuscitating  this discussion thread from last year ...
>
> To summarize my rereading of the thread, there is good agreement that 
> Path.{ends,starts}With(String) should be deprecated and replaced with something 
> else, perhaps Path.{ends,starts}WithString(String). There was also a parallel 
> suggestion that Path.{ends,starts}With(Path) be deprecated in favor of 
> Path.{ends,starts}WithPath(Path). Thus:
>
> * Path.{ends,starts}With(String) -> Path.{ends,starts}WithString(String)
> * Path.{ends,starts}With(Path) -> Path.{ends,starts}WithPath(Path)

My experience is that deprecation for the purposes of renaming doesn't work very 
well. I don't think we're intending to remove the old APIs, so they'd remain, so 
"renaming" would merely be the addition of new APIs with similar names. This would 
just make things more confusing.

The main problem is that Path.{ends,starts}With(String) is confusing and misleading, 
so let's focus on that.

> Among doubtlessly many others, one alternative is
>
> 1. Leave Path.{ends,starts}With(Path) unchanged

This makes sense. I haven't seen any evidence that this is a problem if one is 
already working in the Path domain.

> 2. Deprecate Path.{ends,starts}With(String)

This is the confusing one, so yes, deprecate this (not for removal). It's an open 
question regarding what the deprecation text should recommend be used instead. 
Perhaps some of the discussion below will resolve this.

> 3. Add Path.pathString{ends,starts}With(String)
>
> where "pathstring" in effect implies the value of Path.toString().

Before we start adding new APIs, I think we should consider which use cases we think 
we want to support. The methods take a string argument, and the two cases are 
whether the operation is performed on Paths and Path segments or whether the 
operation is performed in terms of Strings.

For brevity I'll just use "EW" to represent the "endsWith" operation in either 
domain, but the analysis applies equally to the "startsWith" operation.

Suppose we start off with

var path = Path.of("/one/two/three");

The cases are:

a) Path domain. The code path.EW(string) is equivalent to

path.endsWith(path.getFileSystem().getPath(string))
     // note, this is Path.endsWith(Path)

and thus we have

     path.EW("/two/three") ==> false
     path.EW("two/three") ==> true

b) String domain. The code path.EW(string) is equivalent to

     path.toString().endsWith(string)
     // note, this is String.endsWith(String)

and thus we have

     path.EW("/two/three") ==> true
     path.EW("two/three") ==> true

=====

I'm not convinced we need any new APIs at all. It seems likely that many people want 
to perform the string-based endsWith() operation, in which case maybe it's best to 
be explicit and convert the path to a string using toString() before doing that. 
Adding a deprecation for Path.endsWith(String) should warn people not to use this 
method for the string-domain case.

If you want to perform this operation in the Path domain, maybe it's best to be 
explicit about it. If you're writing library code that wants to be very general, 
then you probably have the relevant FileSystem in a local variable already, and you 
might construct Path objects explicitly before invoking the endsWith(Path) 
operation. Using string literals directly, and having them implicitly be converted 
to Path objects, seems like it easily leads to subtle problems (such as the 
difference in behavior between my "/two/three" and "two/three" examples above.) So, 
maybe being explicit is better, even if it is more verbose and less convenient.

If you're writing an application that uses the default FileSystem everywhere, and 
you really want to perform a Path-based operation, you can just slap Path.of() 
around your string literal and move on. I don't think we need another method to 
handle this case.

So, maybe do (1) and (2) but omit (3). This boils down to just deprecating 
endsWith(String) and startsWith(String).

s'marks

>
> Comments?
>
> Brian
>
>> On Nov 2, 2025, at 3:35 PM, David Alayachew <davidalayachew at gmail.com> wrote:
>>
>> As for deprecations, I still think all 4 methods should be deprecated. This path 
>> variants are kind of ok, but the String variants are just too deceptively named.
>>
>> I think Rob Spoor hit it on the head with this quote.
>>
>> > Perhaps both can be added?
>> >
>> > Path.{start,end}sWithString would default to calling
>> > toString().{start,end}sWith(arg) and
>> > Path.{start,end}sWithPath would default to calling
>> > {start,end}sWith(arg). The latter could default to
>> > calling {start,end}sWith(getFileSystem().getPath(arg))
>> > but then custom implementations that do something else
>> > (in addition) may not work as expected.
>>
>> Doing it this way, we can have (start|end)sWithPath() have both String and Path 
>> overloads with no ambiguity.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/nio-dev/attachments/20260107/64c62b6e/attachment-0001.htm>


More information about the nio-dev mailing list