1

I was given to understand that the standard convention was for setters not to return anything. However, the NIO.2 API has a few methods like setOwner, setLastModifiedTime and setAttribute that return Path instances. Are these methods not true setters, or else do not all setters have to have void return types?

K Man
  • 602
  • 2
  • 9
  • 21
  • 3
    There is no "rule". They're probably not "true setters", but why does that matter? If you're overly relying on setters in the first place, your design is probably bad. – Michael Feb 20 '20 at 15:10
  • 2
    You would probably notice, that are static functions. And not changing any attribute of "this" object. It is changing something external, not attributed to current object. Anyway, void is not a must. – armagedescu Feb 20 '20 at 15:11
  • Consider examples like this: `Path file = Files.setOwner(dir.resolve("foo"), owner);` It's very useful sometime to have the file path returned. – Alan Bateman Feb 21 '20 at 07:42

2 Answers2

6

The obsolete JavaBean standard (which was meant to help with tooling so that JavaBeans could be automatically handled) may have said something about void setters, but Fluent Builder is aimed at making things easier.

Allowing method chaining makes for nicer code, and as there's no good reason for requiring a void return type from setters, they've chosen to get with the program (no they haven't see comments):

path.setOwner(foo).setLastModifiedTime(bar).setAttribute(baz);

The JDK does have examples of fluent interface in classes like StringBuilder and ProcessBuilder, but they avoid using the setXXX nomenclature (possibly to avoid confusion) even when it would make sense. StringBuilder.append() obviously wouldn't be named setMoreText(), but ProcessBuilder.directory(File) is less obvious than setWorkingDirectory(File) IMHO.

Kayaman
  • 72,141
  • 5
  • 83
  • 121
  • 2
    Actually all the methods `setOwner`, `setLastModifiedTime`, `setAttribute` are static methods in `java.nio.file.Files` class. You can't chain them the way you did, but the idea of chaining still holds, since, let's say, `Files.setLastModifiedTime(Path path, FileTime time)` returns the first argument . The chaining might look like: `Files.setLastModifiedTime(myPath, myFileTime).resolve(anotherPath)` –  Feb 20 '20 at 15:16
  • @EugenCovaci well that changes the spirit of the question. I assumed the class was `Path`, not `Paths` which is a collection of static utility methods and doesn't use a fluent interface. Let's see if there are actually any proper fluent builders in the JDK. – Kayaman Feb 20 '20 at 15:19
  • Well darn. This answer isn't correct. There's probably no `setXXX` in the JDK that would return `this`, although for example `StringBuilder.append()` and others do provide a fluent interface, so maybe they (JDK developers) do adhere to their rules. – Kayaman Feb 20 '20 at 15:24
  • [Here](https://stackoverflow.com/questions/1345001/is-it-bad-practice-to-make-a-setter-return-this) is a debate about setters returning `this` –  Feb 20 '20 at 15:33
  • 2
    The JavaBean specification most certainly is not obsolete. [EL](https://docs.oracle.com/javaee/7/api/javax/el/package-summary.html) (used by JSP and JSF) uses them. [JavaFX](https://openjfx.io/javadoc/13/javafx.base/javafx/beans/property/package-summary.html) uses them. JAXB uses them. [XMLEncoder](https://docs.oracle.com/en/java/javase/13/docs/api/java.desktop/java/beans/XMLEncoder.html) and XMLDecoder use them. – VGR Feb 20 '20 at 15:34
  • @VGR I thought someone was going to address that :) the spec itself is ancient, and some consider it obsolete as advances in the language made it less necessary than it originally was. Obsolete may be the wrong word, but JavaBeans is a *relic* of the olden times. Also, obsolete doesn't mean "not used", and `XMLEncoder/Decoder` isn't exactly shining proof of a useful standard. – Kayaman Feb 21 '20 at 07:38
  • 1
    A late comment here. You said "This answer isn't correct. There's probably no setXXX in the JDK that would return this". Actually, I found one in `java.nio.channels.AsynchronousServerSocketChannel` class. Take a look at `setOptions` method –  Apr 13 '20 at 07:43
1

A setter is usually used as an accessor method to change the state of an object. As Kayaman mentioned it can be useful to return the object itself to create a fluent api instead of void - see it as syntactical sugar, when working with these objects.

Nevertheless, in the NIO case, it is a static method of the class "Files" that changes the state of the Path that is given as first argument - so in this case it's no accessor but a "normal" method that has "set" in its name.

Jonas
  • 494
  • 4
  • 7
  • 1
    Just for clarification: Implementations of `Path` are supposed to be immutable, so the methods of `Files` never change the state of the _`Path`_ instance. What the `Path` argument does is point to the data which is to be accessed/modified (e.g. a file on the native file system). – Slaw Feb 20 '20 at 15:37