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 <[email protected]> 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.

Reply via email to