Java static initializers, initializers for instance variables, constructors, regular methods and static factory methods - when to use them with examples.
Q. What are “static initializers” or “static blocks with no function names” in Java?
A. When a class is loaded, all blocks that are declared static and don’t have function name (i.e. static initializers) are executed even before the constructors are executed. As the name suggests they are typically used to initialize static fields.
public class StaticInitializer { public static final int A = 5; public static final int B; //note that since final above line cannot do --> public static final int B = null; //Static initializer block, which is executed only once when the class is loaded. static { if(A == 5) B = 10; else B = 5; } public StaticInitilaizer(){} //constructor is called only after static initializer block }
The following code gives an Output of A=5, B=10.
public class Test { System.out.println("A =" + StaticInitilaizer.A + ", B =" + StaticInitilaizer.B); }
Q. How will you initialize an instance variable say dueDate to first day of next month?
A. Like static initializers, you can use an initializer block for instance variables. Initializer blocks for instance variables look just like static initializer blocks, but without the 'static' keyword.
public class Initilization { private Date dueDate; //initializer block { Calendar cal = GregorianCalendar.getInstance( ); cal.add(Calendar.MONTH, 1); cal.set(Calendar.DAY_OF_MONTH, 1); dueDate = cal.getTime( ); //dueDate defaults to first day of next month } //... public static void main(String[ ] args) { Initilization init = new Initilization( ); System.out.println("dueDate = " + init.dueDate); // first day of next month } }
Q. What is the difference between constructors and other regular methods? What happens if you do not provide a constructor? Can you call one constructor from another? How do you call the superclass’ constructor?
A.
Constructors | Regular methods |
Constructors must have the same name as the class name and cannot return a value. The constructors are called only once per creation of an object while regular methods can be called many times. E.g. for a Pet.classpublic Pet() {} // constructor |
Regular methods can have any name and can be called any number of times. E.g. for a Pet.class.// regular method has a void or other return types. public void Pet(){} Note: method name is shown starting with an uppercase to differentiate a constructor from a regular method. Better naming convention is to have a meaningful name starting with a lowercase like: // regular method has a void return type public Pet createPet(){} |
Q. What happens if you do not provide a constructor?
A. Java does not actually require an explicit constructor in the class description. If you do not include a constructor, the Java compiler will create a default constructor in the byte code with an empty argument. This default constructor is equivalent to the explicit “Pet( ){ }”. If a class includes one or more explicit constructors like “public Pet(int id)” or “Pet(){ }” etc, the java compiler does not create the default constructor “Pet( ){ }”.
Q. Can you call one constructor from another?
A. Yes, by using this( ) syntax. E.g.
public Pet(int id) { this.id = id; // “this” means this object } public Pet (int id, String type) { this(id); // calls constructor public Pet(int id) this.type = type; // ”this” means this object }
Q. How to call the superclass constructor?
A. If a class called “SpecialPet” extends your “Pet” class then you can use the keyword “super()” to invoke the superclass’s constructor. E.g.
public SpecialPet(int id) { super(id); //must be the very first statement in the constructor. }
To call a regular method in the super class use: “super.myMethod();”. This can be called at any line. Some frameworks based on JUnit add their own initialization code, and not only do they need to remember to invoke their parent's setUp method, you, as a user, need to remember to invoke them after you wrote your initialization code:
public class DBUnitTestCase extends TestCase { public void setUp() { super.setUp(); // do my own initialization } } public void cleanUp() throws Throwable { try { … // Do stuff here to clean up your object(s). } catch (Throwable t) {} finally{ super.cleanUp(); //clean up your parent class. Unlike constructors // super.regularMethod() can be called at any line. } }
Q. Why do super(..) and this(..) calls need to be in the first line of a constructor?
A. The parent class' constructor needs to be called before the subclass' constructor. This will ensure that if you call any methods on the parent class in your constructor, the parent class has already been set up correctly.
In cases where a parent class has a default constructor the call to super is inserted for you automatically by the compiler. Enforcing super to appear first, enforces that constructor bodies are executed in the correct order. Object --> Pet --> SuperPet
The compiler also forces you to declare this(..) as the first statement within a constructor, otherwise, you will get compile-time error.
Q. Can constructors have private access modifiers? If yes, can you give an example?
A. Yes. Singleton (i.e design pattern) classes use private constructors as shown below.
public final class MySingletonFactory { private static final MySingletonFactory instance = new MySingletonFactory( ); private MySingletonFactory( ){} public static MySingletonFactory getInstance( ) { return instance; } }
Use cases for private constructors:
- The classes with a private constructor cannot be extended from outside even if not declared as final.
- The classes with a private method cannot be invoked from outside. Only the factory methods within that class like getInstance( ), deepCopy(...), etc can access a private constructor.
Q. What are static factory methods in Java?
A. The factory method pattern is a way to encapsulate object creation. Without a factory method, you would simply call the class' constructor directly:
Pet p = new Pet( );
With this pattern, you would instead call the factory method:
Pet p = Pet.getInstance();
The constructors are marked private, so they cannot be called except from inside the class, and the factory method is marked as static so that it can be called without first having an object.
Java API have many factory methods like Calendar.getInstance( ), Integer.valueOf( 5), DriverManager.getConnection( ), Class.forName( ), etc.
Q. What are the benefits of static factory methods over using constructors directly?
A.
- Factory can choose from many subclasses (or implementations of an interface) to return. This allows the caller to specify the behavior desired via parameters, without having to know or understand a potentially complex class hierarchy.
- The factory can apply the fly weight design pattern to cache objects and return cached objects instead of creating a new object every time. In other words, objects can be pooled and reused. This is the reason why you should favor using Integer.valuOf(6) as opposed to new Integer(6).
- The factory methods have more meaningful names than the constructors. For example, getInstance( ), valueOf( ), getConnection( ), deepCopy( ), etc.
Here is a factory method example to deeply clone a list of objects.
public static List<Car> deepCopy(List<Car> listCars) { List<Car> copiedList = new ArrayList<Car>(10); for (Car car : listCars) { //JDK 1.5 for each loop Car carCopied = new Car(); //instantiate a new Car object carCopied.setColor((car.getColor())); copiedList.add(carCopied); } return copiedList; }
Labels: Core Java
0 Comments:
Post a Comment
Subscribe to Post Comments [Atom]
<< Home