40

While answering a few questions on here earlier and from some work I have been doing lately I have been wondering why Java does not support method chaining on its built in classes.

If I were to create a Car class for example, I could make it chainable by reutrning this instead of void as follows:

public class Car {
    private String make;        

    public Car setMake(String make) {
        this.make = make;
        return this;
    }   
}

Is there any particular reason why the built in libraries don't tend to do things this way? Is there a downside to method chaining?

I may have overlooked something which would explain the lack of method chaining however any setter method that returns void by default should return a reference to this (at least in my eyes it should). This would make situations like the following much cleaner.

container.add((new JLabel("label text")).setMaximumSize(new Dimension(100,200)));

rather than the more long winded: Note: It would not stop you from coding this way if you wished.

JLabel label = new JLabel("label text");
label.setMaximumSize(new Dimension(100,200));
container.add(label);

I would be very interested to hear the reasons behind this decision, If I had to guess it would be that there is an overhead associated with this and so should only be used when needed.

Jon Taylor
  • 7,865
  • 5
  • 30
  • 55
  • 23
    Your example shows the downsides of method chaining too though: by just glancing at the code it's not immediately obvious what you're setting the maximum size for: is it the label or the container? One misplaced closing parenthesis and things can go horribly wrong. – biziclop Jul 19 '12 at 13:58
  • 1
    Yeah I can see that but use of whitespace can definitely help to solve this issue. – Jon Taylor Jul 19 '12 at 14:04
  • 2
    @JonTaylor I am not sure relying on whitespace/formatting is a good solution. – Colin D Jul 19 '12 at 14:15
  • 4
    @ColinD If it is just a readability issue, then I see no reason to not use whitespace to make it clearer, isn't this the reason people don't write if/else all on a single line, or indeed write their entire program on a single line? – Jon Taylor Jul 19 '12 at 14:18
  • @ColinD you misquoted me, I added a *not* in literally 20 seconds after I made the comment. – Jon Taylor Jul 19 '12 at 14:35
  • @JonTaylor your edited comment never appeared for me, sorry. I generally only use whitespace to separate different chucks of logic(new lines/empty lines) and to denote scoping(tabs/indenting). I am not sure how one would use whitespace to solve the issues biziclop mentions. How would you? – Colin D Jul 19 '12 at 15:00
  • @ColinD well for example if a method has many parameters I often put each parameter on a seperate line, similarly you could put each chained method call on a seperate line, to me it would make things a lot clearer. I have written an example on pastebin since I cannot show blocks of code in a comment. http://pastebin.com/Njk3nV6M At least to me this seems clear that the methods are all being called on the burger and not the order. – Jon Taylor Jul 19 '12 at 15:09
  • It's been a while i've coded Java, are all the parenthesis mandatory in the one line snippet? In c# you can remove the ones around the new X() – Guillaume86 Jul 19 '12 at 16:28
  • @Guillaume86 To be honest, I am not entirely sure, I have always put them in, but I have a feeling like c# it may not be necessary. – Jon Taylor Jul 19 '12 at 17:13
  • 5
    @GeorgeStocker I don't see why this should be closed, it's a perfectly valid well worded question for which I have gotten some perfectly valid answers. This should not have been closed. – Jon Taylor Jul 20 '12 at 14:18
  • 2
    @JonTaylor I agree, anyone who's had more than a passing glance at the question and the answers can see that they contain mostly factual information that could be useful for others as well. – biziclop Jul 24 '12 at 11:39

6 Answers6

34

Eh. There's readability arguments to be made in both directions -- there's such a thing as trying to put too much into a single line.

But honestly, I suspect here it's for historical reasons: pervasive "chaining" behavior hadn't really become popular or well-known when e.g. Swing was being developed. You could argue that it should've been added in later on, but things like that tend to create binary incompatibilities and other issues that Sun/Oracle have historically been extremely cautious about.

More recent JDK libraries -- see e.g. ByteBuffer for a major, well-known example -- have provided chaining behavior and the like, where it makes sense.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
  • Yeah granted theres a readability issue. Yeah its a shame they dont update swing, but then Swing has always been one of my least favourite aspects of Java. – Jon Taylor Jul 19 '12 at 13:29
  • 4
    I believe that this is correct answer. As a historical note, a lot of the founding fathers of Java had a background in Smalltalk. Smalltalk doesn't have a lot of "and then return this" methods, because it has a syntactic construct for method chaining in the shape of the semicolon. Perhaps that influenced the designers of Java. Even though they didn't include a chaining operator. – Tom Anderson Jul 19 '12 at 13:29
  • 2
    @JonTaylor "it's a shame they don't update swing": they kind of do, it's called [Java Fx 2](http://www.oracle.com/technetwork/java/javafx/overview/faq-1446554.html#6). – assylias Jul 19 '12 at 13:35
  • As I described in my answer, chaining wouldn't even have been practical or even possible in earlier Java versions. It's not just a metter of fashion that they've started adding method chaining in newer classes. – biziclop Jul 19 '12 at 13:37
  • Would the anonymous downvoter care to explain? – Louis Wasserman Jul 19 '12 at 14:10
  • 1
    I would add that debuggin is another important reason. – razpeitia Jul 19 '12 at 14:37
  • 1
    ...Is that the reason for the downvote? (I'm not sure I even buy that as a reason -- I haven't had that much trouble debugging fluent syntax myself. It might be a flaw in certain debuggers that debugging fluent syntax is hard, but I wouldn't say that's a flaw with the syntax itself.) – Louis Wasserman Jul 19 '12 at 14:38
  • I wouldn’t say that this pattern hadn’t become popular by that time as even the `1.0` class `StringBuffer` uses it. But the knowledge of the Swing developers by that time is a different thing… – Holger Nov 04 '15 at 09:46
19

Another reason I can think of is performance, or more precisely: don't pay for something you don't use. return this after each and every method isn't very costly, but still requires few extra CPU cycles and one CPU registry.

There was even an idea to add implicit return this to every method declaring void return value but it was rejected.

Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
  • Ah ok, yeah I had thought that returning this implicitly would be very useful on anything that returned void however I can see how doing this on every method call could potentially become very costly performance wise. – Jon Taylor Jul 19 '12 at 13:30
  • 2
    Would the JIT seriously not optimize that away? At least, for every method short enough to get inlined, it should... – Louis Wasserman Jul 19 '12 at 13:35
  • 2
    @LouisWasserman: +1, but that sound like a lot of work. JIT would have to examine all calls to a method and make sure none of them actually use the return value. This examination process would have to be repeat after each class is loaded. Also remember about reflective invocations. – Tomasz Nurkiewicz Jul 19 '12 at 13:39
  • 3
    Please explain, oh, anonymous downvoter. – Tomasz Nurkiewicz Jul 19 '12 at 13:42
  • 2
    Regarding implicit `return this`, that could be implemented as a purely syntactic construction - for example, an automatic rewrite from `x.setFoo(1).setBar(2)` to `{ tmp = x; tmp.setFoo(1); tmp.setBar(2);}`. (I'm not the downvoter.) – gustafc Jul 19 '12 at 13:44
  • @TomaszNurkiewicz The JIT could compile two separate versions, one with `return this` and one without. The caller can then decide which one to call, depending on whether it uses the return value. – biziclop Jul 19 '12 at 13:55
  • 2
    @gustafc: That couldn't be _purely_ syntactic; you could only do it with methods that themselves return `void`. Eh. I'd expect the JIT to optimize it away in most cases. (In particular, I notice that `ByteBuffer` -- which seems pretty carefully designed for high-performance work -- uses the chaining syntax...) – Louis Wasserman Jul 19 '12 at 13:57
  • 4
    @LouisWasserman Yes, I was referring to *There was even an idea to add implicit return this to every method declaring void return value [...]* Maybe "syntactic" is the wrong word, "compile time" is better. What I meant was that the value of an expression `.y()`, where `y` is a void method, would be that of ``. In other words, dereferencing a `void` value would make the compiler look back in the dereferencing chain until it finds a non-`void` expression. So, that wouldn't have any performance implications (except on compilation, perhaps) and wouldn't be visible in the byte code. – gustafc Jul 19 '12 at 14:20
  • 3
    TL;DR: The compiler would let us use a `void` method as if it returned `this`, although it actually wouldn't. (It doesn't need to return `this` since we already know, at the call site, what it considers to be `this`.) – gustafc Jul 19 '12 at 14:39
  • This is a terrible reason to reject a potential design decision like this – BlueRaja - Danny Pflughoeft Jul 19 '12 at 19:53
  • 4
    I don't believe that performance is a reason to eschew this approach entirely. If you analyze your program and find out that chaining is the real, true bottleneck, then sure: don't use it. But if you haven't done that, then claiming performance reasons is **premature optimization.** – thedayturns Jul 20 '12 at 07:20
  • 1
    @thedayturns it depends, if this was a performance issue for all void returning methods regardless of if you end up chaining or not, then the programmer would have no choice but to accept any performance issues that came with it. I don't pretend to understand how the compiler actually works and although I'd love to learn more (and do everyday) I'm in no position to say whether this is something that could be implemented in such a way that if you choose not to use it it could be somehow optimized away to act the same way a void would have done. – Jon Taylor Jul 20 '12 at 08:47
  • If it was built into the opcodes, it wouldn't have to use a full jrs instruction every time; rather, the compiler would simply look anywhere you actually use the method chain, and push an extra reference to this on the stack. Instead of always adding a return statement, it would just add a stack push wherever needed. – Ajax Feb 01 '13 at 09:14
  • It’s hard to believe that it isn’t used for performance reasons, when essential classes like `StringBuffer` (since 1.0) use it throughout most methods… – Holger Nov 04 '15 at 09:42
9

Although we can but guess as to the real reason, one of them could be that strictly speaking it's not very OO.

If you view methods as actions that represent an action of the modelled world, method chaining doesn't really fit into that picture.

Another reason could be the chaos that might ensue when you're trying to override a chained method. Imagine this situation:

class Foo {
   Foo chainedMethod() {...}
}

class Bar extends Foo {
   Foo chainedMethod() {...} //had to return Foo for Java versions < 1.5
   void doStuff();
}

So when you're trying to do new Bar().chainedMethod().doStuff(), it won't compile. And ((Bar)new Bar().chainedMethod()).doStuff() doesn't look very good, does it :)

biziclop
  • 48,926
  • 12
  • 77
  • 104
  • 2
    Im not sure I agree, I would say you are just performing multiple actions at once. – Jon Taylor Jul 19 '12 at 13:27
  • 1
    @JonTaylor But why would a method return a value when in the modelled world that doesn't happen? – biziclop Jul 19 '12 at 13:35
  • 4
    I see where you are coming from but I see it like asking for a **Burger with cheese and ketchup enabled** rather than a **Burger with cheese enabled and the same Burger again with ketchup enabled**. Yes my example is silly but I think conveys my point (possibly). – Jon Taylor Jul 19 '12 at 13:37
  • But +1 for your example. – Jon Taylor Jul 19 '12 at 13:40
  • 2
    @JonTaylor The OO solution would be to have a combined `setCheeseAndKetchup()` action. I have to say that I don't necessarily agree with this viewpoint, but hardline OO is based on the principle of methods strictly modelling real-life activities. – biziclop Jul 19 '12 at 13:52
  • 1
    Yeah good point. I have to say I disagree with this viewpoint somewhat. I mean I wouldn't combine the two into `setCheeseAndKetchup()` atleast not in a more complex example, but then I guess you could use a `setToppings` method, either with a set of boolean parameters or some bit masked input to allow selection of topppings. – Jon Taylor Jul 19 '12 at 13:56
  • 2
    I'm not saying I agree with it either. I prefer practical solutions and every theory that tells what you must and mustn't do can be stretched beyond where it's practically usable. A too strict interpretation of OO can be a real pain, but trying to do everything with method chaining and without a bit of common sense can be just as painful. – biziclop Jul 19 '12 at 14:07
  • I strongly disagree that Method Chaining/Fluent Interface are not OO. Just because something can be abused c.f. Getter/Setters doesn't make no OO. – Martin Spamer May 02 '13 at 08:58
  • @MartinSpamer You may disagree but you're wrong. It's not the abuse that is the problem but that it's conceptually incompatible with what a method is supposed to represent in OO. – biziclop May 09 '13 at 14:20
  • Then you will have no trouble specifying which OO Principle it violates. – Martin Spamer Jul 22 '13 at 08:39
  • @MartinSpamer The principle that objects should model real-world entities and methods should correspond to actions performed on said entities. A setXXX() method returning the object on which it was called makes no real-world sense, it's a hack. An incredibly useful hack, one for which it's worth ditching the strict interpretation of OO but a hack nevertheless. – biziclop Jul 22 '13 at 15:00
4

Method chaining is typically used with the Builder pattern, and you can see this in the StringBuilder class. Outside of that, method chaining can make the command and creation separation less clear, for instance should repaint() also be part of the fluent interface? Then I could have:

container.add(label).repaint().setMaximumSize(new Dimension(100,200)));

and suddenly the order of my calls becomes important which can get hidden in the method chaining.

Garrett Hall
  • 29,524
  • 10
  • 61
  • 76
  • Yeah I can see how this sort of thing could get confusing, but then just because someone offers the possibility to do something doesn't mean you always have to do it. To me adding event listeners is a great example for using chaining, whereas situations highlighted above like the repaint call can become confusing. But then you could say the same about things like Ternary operators, if used inside each other some people find them horrible, while others like myself prefer them to standard if statements (depending on the scenario). – Jon Taylor Jul 19 '12 at 17:23
  • I actually like to use [method chaining (aka fluent interface)](http://programmers.stackexchange.com/questions/137999/what-is-the-pattern-name-for-using-method-chaining-to-build-an-object), although I realize it shouldn't be taken too far. – Garrett Hall Jul 19 '12 at 19:34
  • Yeah definitely, I think it can be very useful but do realise that in certain situations it can be confusing, but as I said, just because the option to do it is there doesn't mean people have to use it in every situation. – Jon Taylor Jul 20 '12 at 08:38
1

The reason behind not implementing method chaining would be some of the following:

  • The biggest problem for Method Chaining is the finishing problem. While there are workarounds, usually if you run into this you're better off using a Nested Function. Nested Functions are also a better choice if you are getting into a mess with Context Variables.

  • There's no guarantee that an object out of the chain will actually return a valid, non-null object. Also, debugging this style of code is often a lot harder since many *IDE*s will not evaluate the method call at debug time as an object that you can inspect

  • It can get confusing when you're calling routines to other classes to pass arguments to one of the chaining methods, when there are a lot of parameters to pass mainly because the lines get very long

  • There is also a performance issue, which will work hard on memory

GingerHead
  • 8,130
  • 15
  • 59
  • 93
1

You are really asking about the Law of Demeter

"Only talk to your immediate friends"

Note that the above link is a wonderful resource but you can spend a long time there and not get an answer you were looking for! :-)

Jool
  • 1,706
  • 16
  • 14
  • 1
    Unless I have misunderstood what you are saying, I don't think I am talking about the **Law of Demeter**. I am not talking about calling methods on objects within objects, simply chaining method calls on a single object. Does the **Law of Demeter** really apply to this? – Jon Taylor Jul 19 '12 at 13:51
  • 1
    It depends! I interpreted your original question perhaps more widely than you intended, but it certainly could apply. – Jool Jul 19 '12 at 14:05
  • afaik, the subject here is *one object* on which you've got many set-up to do, and want to go with o.settitle(x).setauthor(y).setdate(z) rather than o.settitle(x); o.setauthor(y); o.setdate(z); – PypeBros Jul 19 '12 at 19:31
  • 1
    -1 This has nothing to do with Law of Demeter (you are always working on the same object instance). – sleske Jul 20 '12 at 08:10
  • 1
    @sleske while I agree with you in the context of this question I can see where he is coming from. The reason is that some classes still use a form of chaining (looks the same) but they don't necessarily return the objects you'd think. I can't actually think of any examples this early in the morning but although they are not the typical method chaining mentioned in the question, they are somewhat similar. – Jon Taylor Jul 20 '12 at 08:43
  • Method chaining with delegation is very good way to talk to your friend's children in a way consistent with the Law of Demeter. – Martin Spamer May 02 '13 at 09:01