Object Construction
Instance Construction
Java is object-oriented language and as such the creation of new class instances (objects) is probably its most important concept. Constructors play a central role in the initialization of new class instance and Java offers a few favours to define them.
Implicit (Generated) Constructor
Java allows a class to be described without any constructors but that doesn't mean the class won't have any. Let us look, for example, at this class
This class does not have a constructor but Java compiler will implicitly generate one, and new class instances can be created using new keyword.Constructors without Arguments
The constructor without arguments (or no-arg constructor) is the simplest way to explicitly do the job for Java compiler
package com.cstopics.advanced.construction;
public class NoArgConstructor {
public NoArgConstructor() {
// Constructor body here
}
}
This constructor will be called once new instance of the class is created using the new keyword.
Construction Guarantee
Java offers other initialization assurances that developers can count on. Uninitialized instances and class (static) variables are automatically initialized to their default values.
Type | Default Value |
---|---|
boolean | False |
byte | 0 |
short | 0 |
int | 0 |
long | 0L |
char | u0000 |
float | 0.0f |
double | 0.0d |
object reference | null |
Visibility
Modifier | Package | Subclass | Everyone Else |
---|---|---|---|
public | accessible | accessible | accessible |
protected | accessible | accessible | not accessible |
\<no modifier> | accessible | not accessible | not accessible |
private | not accessible | not accessible | not accessible |
Finalizers
Java uses garbage collection to handle the lifecycle of artifacts and is responsible for
Garbage collector for removing useless objects and reclaiming memories.
However, there is one function in Java called finalisers that resembles the destroyers a bit but serves cleanup of differently. Finalisers are considered a dangerous function (which results in various side effects and efficiency problems). These are usually not required and can be avoided (except in very rare situations, which are often related to Local artefacts). A much better alternative is try-with-resources
Or AutoCloseable interface which allows clean code to be written like this:
Static initialization
Java supports initialization at the class level Constructions which are called static initializers. The initialization blocks are very similar, except for the additional static keyword:
You can include in the class definition any number of static initializer blocks, and they will be Executed in the order the code appears in:
public class StaticInitializationBlock {
static {
// static initialization code here
}
static {
// static initialization code here
}
}
Construction Patterns
Over the years a few well-understood and commonly applicable patterns of construction (or creation) have emerged within Java community. We will cover the most famous of them: * singleton * helpers * factory * dependency injection (AKA inversion of control)
Singleton
Singleton is one of the oldest and most controversial patterns in the community of software developers. The key idea is essentially to Ensure that at any given time only one instance of that class can be created. Singleton raised a lot of discussions about how to make things right, and particularly thread-safe. Here's how a simple singleton class could look like:
public class MySingleton {
private static MySingleton instance;
private MySingleton() {
}
public static MySingleton getInstance() {
if( instance == null ) {
instance = new MySingleton();
}
return instance;
}
}
Helper
Numerous Java developers use the utility or helper classes as quite popular pattern. This is, essentially, the uninstantiable Class (with builder declared as private), optionally declared as final.
public final class HelperClass {
private HelperClass() {
}
public static void helperMethod1() {
// Method body here
}
public static void helperMethod2() {
// Method body here
}
}
Factory
A factory is a tool for creating objects. It is used when it is not possible or useful to instantiate an object with the new operator alone - for example, because the object is difficult to construct or requires extensive configuration before it can be used. Sometimes objects have to be loaded from a file, via a network connection or from a database, or they are generated based on configuration information from modules close to the system. A factory is also used if the set of classes from which objects can be generated is dynamic and can be extended during runtime of the program.
public class Book {
private Book( final String title) {
}
public static Book newBook( final String title ) {
return new Book( title );
}
}
Another variance in factory pattern involves interfaces or abstract (abstract) classes.
public interface BookFactory {
Book newBook();
}
public class Library implements BookFactory {
@Override
public Book newBook() {
return new CommonBook();
}
}
public class UniversityLibrary implements BookFactory {
@Override
public Book newBook() {
return new CourseBook();
}
}
Dependency Injection
Dependence injection (also known as inversion of control) is considered a good practice for class designers: if any class Instance depends on the other instances of another class, those dependencies should be provided (injected) by the constructors (Or setters) but not the instance itself. Let us take a look at the following example:
import java.text.DateFormat; import java.util.Date; public class Dependant { private final DateFormat format = DateFormat.getDateInstance(); public String format( final Date date ) { return format.format( date ); } }
The class Dependant needs an instance of DateFormat
and it just creates one by calling DateFormat.getDateInstanc
e()
at construction time. The better design would be to use constructor argument to do the same thing:
import java.text.DateFormat;
import java.util.Date;
public class Dependant {
private final DateFormat format;
public Dependant( final DateFormat format ) {
this.format = format;
}
public String format( final Date date ) {
return format.format( date );
}
}
Exercise
- Exercise 1:
- write two differrent implementation of singletone pattern.
- explain the difference?
- write two differrent implementation of singletone pattern.
- Execise 2:
- write a Helper class for String processing (e.g. with one methods: concatenate two string), and use it in code.
- Exercise 3:
- write a factory pattern for different type of vehicles.