Why LocalDate
, LocalTime
, Stream
, etc. objects use a factory method of()
instead of a constructor?
I found an explanation of why a factory methods should be used instead of new
here. This answer gives a number of reasons, but the only thing that is relevant to Java Date/Time API is the following:
unlike constructors, they are not required to create a new object each
time they’re invoked
As LocalDate
and LocalTime
are immutable, it probably makes sense to use a factory and reuse existing objects instead of creating a new object every time.
Is it the reason why objects like LocalDate
and LocalTime
are created with a factory method (i.e., LocalDate.of()
)? Are there any other reasons?
Also, Stream
objects are mutable. Why a factory method (Stream.of()
) is used to create a Stream
?
Why a factory method (Stream.of()) is used to create a Stream?
Using a factory method means you don't need to know the exact class used. This is a good example as Stream
is an interface and you can't create an instance of an interface.
From the source for Stream.of
/**
* Returns a sequential {@code Stream} containing a single element.
*
* @param t the single element
* @param <T> the type of stream elements
* @return a singleton sequential stream
*/
public static<T> Stream<T> of(T t) {
return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
}
/**
* Returns a sequential ordered stream whose elements are the specified values.
*
* @param <T> the type of stream elements
* @param values the elements of the new stream
* @return the new stream
*/
@SafeVarargs
@SuppressWarnings("varargs") // Creating a stream from an array is safe
public static<T> Stream<T> of(T... values) {
return Arrays.stream(values);
}
Note: these methods call other factory methods.
You can see you get different constructions depending on how it is called. You don't need to know this or that the ultimate class created which is a ReferencePipeline.Head
+1 to Peter's answer.
Another reason for using factory methods is that they act like "named constructors".
For example, LocalDate
has 6 static factory methods (at least, I may not be exhaustive here):
of(int year, int/Month month, int dayOfMonth)
(two overloads)
ofEpochDay(long epochDay)
ofYearDay(int year, int dayOfYear)
parse(CharSequence text)
parse(CharSequence text, DateTimeFormatter formatter)
I think that it is a lot clearer to understand the meanings of the various parameters by having these as separately-named methods, rather than a bunch of constructors with very similar parameter types; you can pretty much guess what the parameters should be for the factory methods, whereas you might actually have to read the Javadoc (shock horror) if they were "unnamed" constructors.
Admittedly, of
is the least clear of these names - one might want ofYearMonthDayOfMonth
- however, I suspect that this is the most commonly-used factory method, and it's just too cluttered to type that long name all the time.
In case you've not read it, Item 1 of Effective Java 2nd Edition is all about why and when to prefer static factory methods over constructors. The "named constructor" advantage I mention here is actually the first advantage Bloch highlights.