57

In a language where both are available, would you prefer to see an instance constructor or a static method that returns an instance?

For example, if you're creating a String from a char[]:

  1. String.FromCharacters(chars);

  2. new String(chars);

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
Dan Goldstein
  • 23,436
  • 10
  • 47
  • 51
  • 6
    Have added "method" to the title, as otherwise it suggests the choice is between an instance constructor or a static constructor. (The text is clear, but the title provoked a certain "Huh?" question in my mind :) – Jon Skeet Oct 11 '08 at 19:49

11 Answers11

67

In Effective Java, 2nd edition, Joshua Bloch certainly recommends the former. There are a few reasons I can remember, and doubtless some I can't:

  • You can give the method a meaningful name. If you've got two ways of constructing an instance both of which take an int, but have different meanings for that int, using a normal method makes the calling code much more readable.
  • A corollary of the first - you can have different factory methods with the same parameter list
  • You can return null for "potentially expected failure" cases whereas a constructor will always either return a value or throw an exception
  • You can return a type other than the declared (e.g. return a derived class)
  • You can use it as a factory, to potentially return a reference to the same object several times

The downsides:

  • It's not as idiomatic, currently - developers are more used to seeing "new"
  • If you see "new" you know you're getting a new instance (modulo the oddity I mentioned recently)
  • You need to make appropriate constructors available for subclasses
  • In C# 3, constructor calls are able to set fields/properties in a compact manner with object initializer expressions; the feature doesn't apply to static method calls
Community
  • 1
  • 1
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 2
    Reading Item 2 in Effective Java one can easily get the impression that Joshua Bloch is in favour of using static factory methods as the default choice. But I don't think that's actually the case, or at least it wasn't in 2002 when he did [this interview](http://www.artima.com/intv/bloch14.html) with Bill Venners that I quoted in my answer further down. – MB. Jun 15 '11 at 11:06
  • re. your point about c#, I've used this pattern in the past; See my answer here which offers a workaround to the compact initializer problem (well, replaces it with something which is also compact anyway!) http://stackoverflow.com/a/10171659/705589 – Mikey Hogarth Apr 16 '12 at 11:54
  • One more advantage is that you can chain/compose/re-use static factory methods more easily compared to ctors. – Mahdi Sep 14 '20 at 23:44
27

I write a constructor when creating the instance has no side effects, i.e. when the only thing the constructor is doing is initializing properties. I write a static method (and make the constructor private) if creating the instance does something that you wouldn't ordinarily expect a constructor to do.

For example:

public class Foo
{
   private Foo() { }

   private static List<Foo> FooList = new List<Foo>();
   public static Foo CreateFoo()
   {
      Foo f = new Foo();
      FooList.Add(f);
      return f;
   }
}

Because I adhere to this convention, if I see

Foo f = Foo.CreateFoo();
Bar b = new Bar();

while reading my code, I have a very different set of expectations about what each of those two lines is doing. That code isn't telling me what it is that makes creating a Foo different from creating a Bar, but it's telling me that I need to look.

Robert Rossney
  • 94,622
  • 24
  • 146
  • 218
  • 1
    Good point about the abnormal processing. Personally, I don't like the idea of using a static method in place of a default constructor. It's repetitive and goes against the flow of the language. I'd prefer to refactor the abnormal processing and use the new keyword, if possible. – Dan Goldstein Oct 11 '08 at 20:12
  • @Robert, This doesn't invalidate the "use static as default" argument. You could still differentiate a static constructor from a special static constructor (that you need to *look*) by using naming conventions. E.g. `Foo.New()` as the default replacement for `new`, and `Foo.FromAbc()` etc for the *special* ones. – Pacerier Jun 25 '14 at 04:24
14

I've been working on a public API recently, and I've been agonizing over the choice of static factory methods versus constructor. Static factory methods definitely make sense in some instances, but in others it's not so clear and I'm uncertain whether consistency with the rest of the API is reason enough to include them over constructors.

Anyway, I came across a quote from a Bill-Venners interview with Josh Bloch that I found helpful:

When you are writing a class, you can run down the my book's list of the advantages of static factories over public constructors. If you find that a significant number of those advantages actually apply in your case, then you should go with the static factories. Otherwise you should go with the constructors.

Some people were disappointed to find that advice in my book. They read it and said, "You've argued so strongly for public static factories that we should just use them by default." I think the only real disadvantage in doing so is that it's a bit disconcerting to people who are used to using constructors to create their objects. And I suppose it provides a little less of a visual cue in the program. (You don't see the new keyword.) Also it's a little more difficult to find static factories in the documentation, because Javadoc groups all the constructors together. But I would say that everyone should consider static factories all the time, and use them when they are appropriate.

Having read that quote, and the study that Uri mentioned*, I'm feeling inclined to err in favour of constructors unless there are compelling reasons to do otherwise. I think a static factory method without good cause is probably just unnecessary complexity and over-engineering. Though I might well change my mind again by tomorrow...

*Unfortunately this study focused less on static factory methods and more on the factory pattern (where a separate factory object exists to create new instances), so I'm not sure one can really draw the conclusion that static factory methods confuse many programmers. Although the study did give me the impression that they often would.

MB.
  • 7,365
  • 6
  • 42
  • 42
10

If your object is immutable, you may be able to use the static method to return cached objects and save yourself the memory allocation and processing.

Dan Goldstein
  • 23,436
  • 10
  • 47
  • 51
8

There's a paper from ICSE'07 that studied the usability of constructors vs. factory patterns. While I prefer factory patterns, the study showed that developers were slower in finding the correct factory method.

http://www.cs.cmu.edu/~NatProg/papers/Ellis2007FactoryUsability.pdf

Uri
  • 88,451
  • 51
  • 221
  • 321
  • That's a good answer, unfortunately. I'm willing to do allocation without the "new" keyword, but discoverability is pretty important. I'd hate for someone to do their own processing to create a theoretical String object because they didn't see a constructor. – Dan Goldstein Oct 11 '08 at 20:08
  • I agree, the problem of how to ensure people discover a static is an important one. The second author of that paper is currently building some tool for that as part of his PhD work, it'll be interesting to see where this ends up. – Uri Oct 11 '08 at 20:13
  • 1
    @Uri, It's of course slower **currently** because there's not yet standards body creating proper naming conventions for static constructors. Contrast that with the widely known convention of `new` in normal constructors. – Pacerier Jun 25 '14 at 04:26
4

It depends. For languages in which using an instance constructor is "normal", I would generally use one unless I had good reason not to. This follows the principle of least surprise.

By the way, you forgot another common case: A null/default constructor paired with an initialization method.

ejgottl
  • 2,809
  • 19
  • 18
  • Yes, I didn't think of that case. I think it's inferior to the two presented because it needs to lines of code. I could edit the question to include it though. – Dan Goldstein Oct 11 '08 at 20:17
  • @ejgottl, What do you mean by "null constructor paired with initialization"? – Pacerier Jun 25 '14 at 04:20
  • A constructor which takes no parameters and, perhaps, only allocates memory leaving the object uninitialized. Paired with initialization method(s). If I recall correctly, this is how Ruby objects are implemented in C. – ejgottl Aug 20 '14 at 20:24
3

Static Method. Then you can return a null, rather than throwing an exception (unless a reference type)

Darren Kopp
  • 76,581
  • 9
  • 79
  • 93
3

I prefer instance constructor, just because that makes more sense to me, and there's less potential ambiguity with what you're trying to express (ie: what if FromCharacters is a method which takes a single character). Certainly subjective, though.

Nick
  • 6,808
  • 1
  • 22
  • 34
3

I personally prefer to see a normal constructor, since contructors should be used to construct. However, if there is a good reason to not use one, ie if FromCharacters explicitly stated that it didn't allocate new memory, it would be worthwhile. The "new" in the invocation has meaning.

nimish
  • 4,755
  • 3
  • 24
  • 34
3

As Jon Skeet paraphrased Josh Bloch, there are a number of reasons why a static factory method is preferable to a constructor in many cases. I would say that if the class is a simple one with no expensive setup or complicated usage, stay with the idiomatic constructor. Modern JVMs make object creation extremely fast and cheap. If the class might be subclassed or you are able to make it immutable (a big advantage for concurrent programming, which is only going to get more important), then go with the factory method.

One more tip. Don't name the factory method Foo.new* or Foo.create*. A method with these names should always return a new instance, and doing so misses one of the big advantages of the factory method. A better naming convention is Foo.of* or Foo.for*. The Google Guava library (formerly Google Collections Library) does a great job of this, imho.

Fruny
  • 6,453
  • 1
  • 17
  • 10
Dov Wasserman
  • 2,632
  • 17
  • 14
  • 2
    Could you expand a little on *why* `of*` and `for*` are better names than `new*` or `create*`? Naming things rightly is important to me, so I'd like to learn something new here. – stakx - no longer contributing May 08 '13 at 21:02
  • 2
    @stakx: If you use new* or create* you are "forced" to provide a new instance, while using the proposed namings allows you to reuse existing ones. – Igor Rodriguez Sep 30 '13 at 13:20
1

Of course, there are several advantages of static factory methods over constructors.

  1. factory methods help us to write flexible code. Whereas constructors made it tightly coupled.
  2. Static factory methods improve the readability since these allow you to create different instances.
  3. You can return a cached object. For example getInstance() in Singleton.
Sumanth Varada
  • 1,122
  • 1
  • 16
  • 17