Is a nested Builder class really necessary as described in Effective Java? - java

So, in the famous Effective Java book, it introduces a Builder pattern where you can have an inner static Builder class to instantiate a class. The book suggests the following design of a class:
public class Example {
private int a;
private int b;
public static class Builder() {
private int a;
private int b;
public Builder a(int a) {
this.a = a;
return this;
}
public Builder b(int b) {
this.b = b;
return this;
}
public Example build() {
return new Example(this);
}
}
private Example(Builder builder) {
this.a = builder.a;
this.b = builder.b;
}
}
However I have failed to understand why do we really need an inner Builder class? The above code have duplicate lines for field declarations (int a, b), this would become relatively messy if we had more fields.
Why not just get rid of the Builder class, and let Example class take on all the set methods that were in Builder class?
So to instantiate Example, it would become Example e = new Example().a(3).b.(3); instead of Example e = new Example.Builder.a(3).b(3).build();
NOTE: The book suggests this pattern for classes that have a long list of parameters to be set.

Builder is a pattern for the construction of complex objects. I wouldn't count your example as complex; indeed, the builder adds an awful lot of unnecessary code, rather than just using constructor parameters.
There are a few reasons why you'd want to use a builder:
To construct complex immutable objects. Immutable objects need to have final (or logically final) fields, so they must be set at construction time.
Let's say that you have N fields, but you only want to explicitly set some of them in certain use cases. You would need up to 2^N constructors to cover all of the cases - known as "telescoping", since the length of the parameter list gets longer and longer. The builder allows you to model optional parameters: if you don't want to set that parameter, don't call that setter method.
To allow self-documentation of the parameters' meaning. By naming the setter methods appropriately, you can see what the values mean at a glance.
It also helps to verify that you are not accidentally reversing parameters of the same type, since you can see what each value is used for.

If the fields in the outer class are final, then the builder is necessary if you want to incrementally specify parameter values, as all fields must be initialized in the constructor.
The builder inner class allows fields to be initialized incrementally.
As others have pointed out, this applies to immutable objects as well. The fields don't need to be final; they effectively will be if no setters are supplied in the outer class.
The builder can possibly accumulate the parameters more efficiently than direct construction. Consider the StringBuilder. It allocates a temporary buffer to accumulate partial results. The "build" operation in its case is toString().
Finally, there could be things you just can't do in the constructor of a class. If you need to pass a value to a super constructor, but that value is not part of the arguments to your constructor, it may not be possible to, since you must call super() first, and you might not be able to create the argument(s) as a simple expression inside the super(...) call. The BoxLayout comes to mind. You pass the JPanel to the BoxLayout constructor. You pass the layout to the JPanel constructor. Chicken and egg. And this code is not allowed, because this is not yet constructed.
class X extends JPanel {
X() {
super( new BoxLayout(this) ); // Error: Cannot use "this" yet
}
}
Fortunately, a JPanel is not immutable; you can set the layout after construction.

The rationale is for complicated classes. Notice that the Builder object returns itself, so one can do chaining, such as:
Example exp = Example.Builder().a(5).b(10).build();
Apache uses this approach in some cases to allow the incremental setting of various values. It also allows the .build() method to do some checking of all of the correct values to make an object if desired.

Related

How much more expensive is the creation of an object without data in Java instead of the use of static methods?

Java lacks the ability to specify interfaces for static methods. A method in an interface must be non static. This makes it impossible to specify requirements for Classes. Instead one is limited to specify requirements for Objects. This makes it also impossible for example to specify the singleton functionality in an interface, because in Java the singleton pattern requires to be implemented as a static method. Here is a nice article, which explains it, but it is only in German.
When one is forced to implement something as a functionality of an object instead of the functionality of a class, an instance of this object has to be created, before the functionality can be used. But such object has some special characteristic: it has no state, because class functionality has no state either. Theoretically the instance creation of an object without data can be optimized to an NOP, because all methods can be linked to the class instead of any object. Java could implement some kind of implicit singleton functionality.
But how it this actually handled?
Think about some kind of functionality without any state.
interface Adder<T> { T add(T ... arguments); }
Basically it would be sufficient to implement this as a static method:
class IntegerAdder implements Adder<Integer> {
public static Integer add (Integer ... arguments) { }
}
But because Java does not allow static interface methods it has to be implemented in a non static way. The result is, that when ever an IntegerAdder is required one has to create an instance.
IntegerAdder integer_adder = new IntegerAdder();
Integer a = 1;
Integer b = 2;
Integer c = integer_adder.add (1, 2);
I fear this might be slower than the version without the instance creation:
Integer a = 1;
Integer b = 2;
Integer c = IntegerAdder.add (1, 2);
But how much slower is it in reality? Is it possible for the Java compiler to optimize the first version in that way that it performs as fast as the second one? And is this actually done?
You can create an instance of IntegerAdder once and reuse it, it is thread safe. Also pay attention that Integer ... arguments leads to 1) using objects instead of primitive ints 2) creating an array to pass parameters. Both things should be avoided if performance is concern

Java Constructor and static method

When should I use a constructor and when should I use static method?
Can you explain above with small snippet? I skimmed through a few threads but I'm still not clear with this.
Joshua Bloch advises to favor static factory methods instead of constructors (which I think is a good practice). Couple of advantages and disadvantages :
Advantages of static factory methods :
unlike constructors, they have names
unlike constructors, they are not required to create a new object each time they're invoked (you can cache instances : e.g. Boolean.valueOf(..)
unlike constructors, they can return an object of any subtype of their return type (great flexibility)
Disadvantages of static factory methods :
They are not really distiguishable from other static methods (it's hard to find out how to initialize an object if you are not familiar with the API)
The main disadvantage (if you use only static factory methods, and make constructors private) is that you cannot subclass that class.
Use a public constructor when you only ever want to return a new object that type and you want simplicity.
A good example is StringBuilder as it's mutable and you are likely to want a new object each time.
public String toString() {
StringBuilder sb = new StringBuilder();
// append fields to the sb
return sb.toString();
}
Use a static factor method when you might want to re-use objects (esp if immutable), you might want to return a sub-class or you want descriptice construction. A good example is EnumSet which has a number of static factories which do different things even though some have the same arguments.
EnumSet.noneOf(RetentionPolicy.class);
// has the same arguments, but is not the same as
EnumSet.allOf(RetentionPolicy.class);
In this case, using a static factory makes it clear what the difference between these two ways of construction the set.
Also EnumSet can return two different implementations, one optimised for enums with a small number of values (<= 64) RegularEnumSet and another for many values called JumboEnumSet
Always use a constructor if your class has a state (even for a single instance; singleton pattern ).
Only use static for utility methods like in java.lang.Math
Example:
public static int max(int a, int b) {
return (a >= b) ? a : b;
}
Doesn't change any state (instance variables) of an object, thus it can be declared static.
Use constructor when you need an object and other stuffs like functions and variables having one copy for every object.
when you want to do something without creating object then use static method.
Example:
public class Test {
public int value;
public static int staticValue;
public int getValue() {
return ++value;
}
public static int getStaticValue() {
return ++staticValue;
}
}
public class TestClass {
public static void main(String[] args) {
Test obj = new Test();
Test obj1 = new Test();
S.o.p(obj.getValue());
S.o.p(obj1.getValue));
S.o.p(Test.getStaticValue());
S.o.p(Test.getStaticValue());
}
}
Static factory methods have names, constructors don't. Thus factory methods can carry natural documentation about what they do that constructors can't. For example, see the factory methods in the Guava Libraries, like ImmutableMap.copyOf(otherMap). While this might have little effect on behaviour of construction, it has a huge effect on readability of the code. Definitely consider this if you're publishing an API.
Also you can use a factory when you need to do any more complicated configuration of the object you're creating, especially if you need to publish to other threads (registering in pools, exposing as an MBean, all manner of other things...) to avoid racy publication. (See e.g. Java Concurrency In Practice section 3.2)
Static methods that do something (e.g. Math.min) are not really the same thing as static factories, which can be considered direct replacements for constructors, with added flexibility, evolvability and (often) clarity.
Whenever you need to create an instance of an object you will have to use the constructor.
So, if you want to create a Car object, then you will need a constructor for that.
The keyword static means, that your method can be called without creating an instance.
class Car
{
private int num_of_seats;
public Car(int number_of_seats)
{
this.num_of_seats = number_of_seats;
}
// You want to get the name of the class that has to do with
// this class, but it's not bounded with any data of the class
// itself. So you don't need any instance of the class, and
// you can declare it as static.
static String getClassName()
{
return "[Car]";
}
}
In general you will use static class with data that are not correlated with the instance of the object.
Another example is:
class Ring
{
private List nodes;
public Ring(List nodes)
{
this.nodes = nodes;
}
// You want to calculate the distance of two ids on the ring, but
// you don't care about the ring. You care only about the ids.
// However, this functionality logical falls into the notion of
// the ring, that's why you put it here and you can declare it
// as static. That way you don't have to manage the instance of
// ring.
static double calculateDistance(int id_1, int id_2)
{
return (id_1 - id_2)/383; // The divisor is just random just like the calculation.
}
}
As the posts above say, it's just a matter of what you want to do and how you want to do it. Also, don't try to understand everything rightaway, write some code then try different approaches of that code and try to understand what your code does. Examples are good, but you need to write and then understand what you did. I think it's the only way you will figure out
why you do staff the way you have to do.
Static methods do not have to instantiate new objects everytime. Since object instantiation is expensive it allows instances to be cached within the object. So, it can improve performance.
This is the explanation from the Effective Java :
This allows immutable classes (Item 15) to use preconstructed
instances, or to cache instances as they’re constructed, and dispense
them repeatedly to avoid creating unnecessary duplicate objects. The
Boolean.valueOf(boolean) method illustrates this technique: it never
creates an object. This technique is similar to the Flyweight pattern
[Gamma95, p. 195]. It can greatly improve performance if equivalent
objects are requested often, especially if they are expensive to
create.
i.e. if you want to use a singleton, which means that you have only one instance of the object, which might be shared with others, then you need a static method, which will internally will call the constructor. So, every time someone wants an instance of that object you will return always the same, thus you will consume memory only for one. You always need a constructor in object oriented programming, in every OO language. In java an in many other languages the default constructor of an object is implied, and built automatically. But you need some custom functionality you have to make your own.
Above you see a few good examples of the usage. However, if you have something specific in your mind, please let us know. I mean if you have a specific case where you are not sure if you should use a static method or a constructor. Anyhow, you will definitely need a constructor, but I am not sure about the static method.

Java interfaces and types

Let's say you have some Java code as follows:
public class Base{
public void m(int x){
// code
}
}
and then a subclass Derived, which extends Base as follows:
public class Derived extends Base{
public void m(int x){ //this is overriding
// code
}
public void m(double x){ //this is overloading
// code
}
}
and then you have some declarations as follows:
Base b = new Base();
Base d = new Derived();
Derived e = new Derived();
b.m(5); //works
d.m(6); //works
d.m(7.0); //does not compile
e.m(8.0); //works
For the one that does not compile, I understand that you are passing in a double into Base's version of the m method, but what I do not understand is... what is the point of ever having a declaration like "Base b = new Derived();" ?
It seems like a good way to run into all kinds of casting problems, and if you want to use a Derived object, why not just go for a declaration like for "e"?
Also, I'm a bit confused as to the meaning of the word "type" as it is used in Java. The way I learned it earlier this summer was, every object has one class, which corresponds to the name of the class following "new" when you instantiate an object, but an object can have as many types as it wants. For example, "e" has type Base, Derived, (and Object ;) ) but its class is Derived. Is this correct?
Also, if Derived implemented an interface called CanDoMath (while still extending Base), is it correct to say that it has type "CanDoMath" as well as Base, Derived, and Object?
I often write functions in the following form:
public Collection<MyObject> foo() {}
public void bar(Collection<MyObject> stuff){}
I could just as easily have made it ArrayList in both instances, however what happens if I later decide to make the representation a Set? The answer is I have a lot of refactoring to do since I changed my method contract. However, if I leave it as Collection I can seamlessly change from ArrayList to HashSet at will. Using the example of ArrayList it has the following types:
Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccess
There are a number of cases where confining yourself to a particular (sub)class is not desired, such as the case you have where e.m(8.0);. Suppose, for example, you have a method called move that moves an object in the coordinate graph of a program. However, at the time you write the method you may have both cartesian and radial graphs, handled by different classes.
If you rely on knowing what the sub-class is, you force yourself into a position wherein higher levels of code must know about lower levels of code, when really they just want to rely on the fact that a particular method with a particular signature exists. There are lots of good examples:
Wanting to apply a query to a database while being agnostic to how the connection is made.
Wanting to authenticate a user, without having to know ahead of time the strategy being used.
Wanting to encrypt information, without needing to rip out a bunch of code when a better encryption technique comes along.
In these situations, you simply want to ensure the object has a particular type, which guarantees that particular method signatures are available. In this way your example is contrived; you're asking why not just use a class that has a method wherein a double is the signature's parameter, instead of a class where that isn't available. (Simply put; you can't use a class that doesn't have the available method.)
There is another reason as well. Consider:
class Base {
public void Blah() {
//code
}
}
class Extended extends Base {
private int SuperSensitiveVariable;
public setSuperSensistiveVariable(int value) {
this.SuperSensistiveVariable = value;
}
public void Blah() {
//code
}
}
//elsewhere
Base b = new Extended();
Extended e = new Extended();
Note that in the b case, I do not have access to the method set() and thus can't muck up the super sensitive variable accidentally. I can only do that in the e case. This helps make sure those things are only done in the right place.
Your definition of type is good, as is your understanding of what types a particular object would have.
What is the point of having Base b = new Derived();?
The point of this is using polymorphism to change your implementation. For example, someone might do:
List<String> strings = new LinkedList<String>();
If they do some profiling and find that the most common operation on this list is inefficient for the type of list, they can swap it out for an ArrayList. In this way you get flexibility.
if you want to use a Derived object
If you need the methods on the derived object, then you would use the derived object. Have a look at the BufferedInputStream class - you use this not because of its internal implementation but because it wraps an InputStream and provides convenience methods.
Also, I'm a bit confused as to the meaning of the word "type" as it is used in Java.
It sounds like your teacher is referring to Interfaces and Classes as "types". This is a reasonable abstraction, as a class that implement an interface and extends a class can be referred to in 3 ways, i.e.
public class Foo extends AbstractFoo implements Comparable<Foo>
// Usage
Comparable<Foo> comparable = new Foo();
AbstractFoo abstractFoo = new Foo();
Foo foo = new Foo();
An example of the types being used in different contexts:
new ArrayList<Comparable>().Add(new Foo()); // Foo can be in a collection of Comparable
new ArrayList<AbstractFoo>().Add(new Foo()); // Also in an AbstractFoo collection
This is one of the classic problems on object oriented designs. When something like this happens, it usually means the design can be improved; there is almost always a somewhat elegant solution to these problems....
For example, why dont you pull the m that takes a double up into the base class?
With respect to your second question, an object can have more than one type, because Interfaces are also types, and classes can implement more than one interface.

Methods using private members or public accessors

I realize this probably cannot be answered, but I'm looking for whether there is some sort of guidance about whether to use private members directly or public accessors inside class methods.
For example, consider the following code (in Java, but it would look very similar in C++):
public class Matrix {
// Private Members
private int[][] e;
private int numRows;
private int numCols;
// Accessors
public int rows(){ return this.numRows; }
public int cols(){ return this.numCols; }
// Class Methods
// ...
public void printDimensions()
{
// [A] Using private members
System.out.format("Matrix[%d*%d]\n", this.numRows, this.numCols);
// [B] Using accessors
System.out.format("Matrix[%d*%d]\n", this.rows(), this.cols());
}
The printDimensions() function illustrates two ways to get the same information, [A] using private members (this.numRows, this.numCols) or [B] via accessors (this.rows(), this.cols()).
On one hand, you may prefer using the accessors since there is no way you could inadvertently change the value of the private member variables. On the other, you may prefer accessing the private members directly in hopes that it would remove the unnecessary function call.
I guess my question is, is either the de-facto standard or preferred?
It's a style call. I prefer to use accessors, because IMHO the function call overhead is small enough that in most cases it doesn't matter, and this usage preserves the data abstraction. If i later want to change the way the data is stored, i only need to change the accessors, instead of hunting for all the places where i touched the variables.
I don't feel strongly about it, though, and i would break this "rule" if i thought i had a good reason to.
IMHO, accessors are more a matter of structure and data management rather than accessors per se. Sometimes, you need to preprocess some data before returning it. Think about this example:
public class Foo {
private List<Bar> bars = null;
//Methods and stuff
public List<Bar> getBars() {
if(bars == null)
bars = SomeClass.loadBars();
// You can also use
// setBars(SomeClass.loadBars());
return bars;
}
}
In this case, your getter is not only wrapping your field, but returning an initialized field whenever you invoke it. Using the accessors inside a class gives the same benefits that for outsiders, you abstract yourself from the particular details of a field and you can obtain it after processing it.
On the other hand, if your field is returned directly (say, a String) it doesn't matter if you use a get or you don't, but you might want to use a get to respect a standard in your code.
In the end, it all boils down to coding style.
I have other objects, including subclasses of the object, use the accessors, but have the object itself use the fields. That way there is a clear distinction between the internals and the interface with the rest of the world. Hiding the contents of the class from itself seems unnecessary and potentially confusing. If something really benefits from having its implementation hidden from other parts of the object then break it out into a separate object.

what's the point of java constructor?

So I'm learning java. I'm one month in and I just learned about constructors. But I don't see the whole purpose of creating one. Why and when would I ever want to use one? I get the whole idea that it does not have a main method and you can call a constructor from your main class. Anyone can enlighten me on this topic, it would help me a great deal.
Constructors are what you use to initialize/set up the instances of your classes.
If you have an object that needs some processing before it is usable (initializing members for instance), you should do that in the constructor.
Ideally, you should never have "partially built" objects (i.e. objects that are "live", that you hold a reference to, but that are not yet usable). Without constructors, you'd be permanently creating partially built objects, and that is very error-prone. (Theory and practice don't always match, but keep that idea in mind.)
You use a constructor to create new objects. Yes, you can write Java just using static methods - but then you're really not writing object-oriented code, and you'll have a hard time using much of the standard library, either.
Most of your time you should be working with and thinking in terms of objects - and they need to be constructed before they can be used... and that's where constructors come in. They create an object, often with parameters specifying the initial state or other important information about the object.
To be honest, it's probably not worth worrying about them just yet, if you don't see the point yet. It's likely that as you learn more, you'll naturally start using objects more (maybe collections to start with, for example) and you'll get the hang of it. Rest assured, it is important to have constructors in Java, but I'm sure you'll understand why in the course of time. (Of course, if this answer has helped you to appreciate their value already, I'm glad - but if not, don't worry :)
It might seem as if you're having trouble understanding the basic concepts of objects and object-oriented programming. An explanation by example; This class represents a type of thing, namely a car:
public class Car{
// Licence plate number. This is private, so it can
// not be accessed directly from outside the class.
private String hiddenRegNr = "";
private static String description = "This is a car".
// The constructor, which sets the value of hiddenRegNr
public Car(String regNr){
hiddenRegNr = regNr;
}
// Method for reading hiddenRegNr, the only
// way to access it after instantiation.
public String getRegNr(){
return hiddenRegNr;
}
// A static method. Can be used withouth instantiation.
public static String getDesc(){
return description;
}
}
From some other class, you could call this class, and make instances of it; actual representations of different cars. They represent different cars, but are based on the same "model", i.e., the class Car.
Car myFirstCar = new Car("SR12345");
Car myOtherCar = new Car("XZ54321");
Now you have two different cars, with two different registration numbers. These are independent instances of the type car. They exist in memory, and may contain different values (in this case, different registration numbers).
myFirstCar.getRegNr(); // Will return SR12345
mySecondCar.getRegNr(); // will return xz54321
The first thing to notice here, is that you can only specify the registration number once per car, namely upon creation. That is the point of the constructor: It sets values, and does other stuff that needs to be done when objects (instances) are created.
Now, note the difference between getRegNr() and getDesc(): The keyword "Static" means that the second method is related directly to the class, and not to each instance. This means that:
Calls to getDesc() is made on the class, not an instance:
Car.getDesc();
Calls to getDesc() will return the same value for all instances of the class car
The variable description (which is also static) will be the same for all instances of Car
The static method getDesc() CAN NOT access the variable hiddenRegNr, since that variable is related to a specific instance. Trying to refer to a variable in an instance from a static context (such as getDesc()) will cause an exception to be thrown. You might say that hiddenRegNr will not have been set when you call
Car.getDesc();
because the constructor was never called, so it was never given any value.
Constructors are used to initialize a class and give parameters to a class. What is important is that they let you set the class state on creation. This allows you to use specific instances of a class with different data field values instead of relying on purely static information. Take the following example:
class Obj {
private int state = 0;
public Obj(int state) {
this.state = state;
}
public Obj() {
state = 1;
}
}
Now in main (or wherever) you can have:
Obj obj1 = new Obj();
Obj obj2 = new Obj(2);
The two objects have different states (one is at state 1, the other is at state 2). If you were relying on static methods and members, the objects would share one state and would not be independent of each other.
It is also important to note that constructors (specifically the new keyword) allocate memory for a given object internally so you don't have to worry about using malloc and other memory management. So they are important in that sense as well.
It is used to create objects. Objects are the main concept in OOP, so creating them is an important step. The main class method is just an entry point to your program. If you don't create objects your program will be procedural rather than object-oriented. This is why to use a constructor.
And why to create a constructor - sometimes you need to construct an object with some required parameters. There is also a default no-argument constructor, but if you want to initialize your object with additional arguments - you create a constructor taking those arguments.
Actually constructor is needed IF you need to assign unique initial state to an instance of a class. In Java i only just realized (by a friend) that we can do this:
public class MyClass1 {
private class MyClass2 {}
private MyClass2 myobj2 = new MyClass2();
}
So no need for implicit constructor.
But if something like follows, you need constructor.
public class MyClass1 {
private class MyClass2 {
private int id_ = 0;
public MyClass2(int id) { id_ = id; } // how to reach this?
}
private MyClass2 myobj2 = new MyClass2(1); // (this doesn't work. Not unique)
public MyClass1(int id) { myobj2 = new MyClass2(id); } // by this!
}
MyClass1 obj1 = new MyClass1(100);
MyClass1 obj2 = new MyClass1(200);
I will give you an example, imagine you have a car class.. when you call the constructor of the car class you have an car object. on this car object is possible to use diffent methods. And you could create as many as car objects as you want.

Categories