A Strategy For Defining Immutable Objects: Hashcode Map Keys and Set Elements

You might also like

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 14

A Strategy for Defining Immutable Objects

The following rules define a simple strategy for creating immutable objects. Not all classes documented
as "immutable" follow these rules. This does not necessarily mean the creators of these classes were
sloppy they may have good reason for believing that instances of their classes never change after
construction. However, such strategies require sophisticated analysis and are not for beginners.
1. Don't provide "setter" methods methods that modify fields or objects referred to by fields.
2. Make all fields final and private.
3. Don't allow subclasses to override methods. The simplest way to do this is to declare the
class asfinal. A more sophisticated approach is to make the constructor private and construct
instances in factory methods.
4. If the instance fields include references to mutable objects, don't allow those objects to be
changed:
o

Don't provide methods that modify the mutable objects.

Don't share references to the mutable objects. Never store references to external,
mutable objects passed to the constructor; if necessary, create copies, and store
references to the copies. Similarly, create copies of your internal mutable objects
when necessary to avoid returning the originals in your methods.

Benefits of making a class immutable


Lets first identify benefits of making a class immutable. Immutable classes are

1.
2.
3.
4.
5.
6.
7.

are simple to construct, test, and use


are automatically thread-safe and have no synchronization issues
do not need a copy constructor
do not need an implementation of clone
allow hashCode to use lazy initialization, and to cache its return value
do not need to be copied defensively when used as a field
make good Map keys and Set elements (these objects must not change state while in the
collection)
8. have their class invariant established once upon construction, and it never needs to be
checked again
9. always have failure atomicity (a term used by Joshua Bloch) : if an immutable object
throws an exception, its never left in an undesirable or indeterminate state

THREADS:
class A1 implements Runnable {
private int counter = 0;
@Override
public void run() {
counter++;
System.out.println("Running A1 -> " + counter);
}
}
class B1 extends Thread {
private int counter = 0;
@Override

public void run() {


counter++;
System.out.println("Running B1 -> " + counter);
}
}
public class ABMain {
public static void main(String[] args) throws InterruptedException {
A1 a = new A1(); // Create runnable instance
B1 b = new B1(); // Create Thread instance
new Thread(a).start();
Thread.sleep(1000);
new Thread(a).start();
Thread.sleep(1000);
new Thread(a).start();
Thread.sleep(1000);
new B1().start();
Thread.sleep(1000);
new B1().start();
Thread.sleep(1000);
new B1().start();
}
}
Output:
1
2
3
1
1
1
1) A1 a = new A1(); does not make a thread. Its just another class with no extra behavior. If you call
A1.run() then it is not new thread. And A1.start() is not available to this class.
2) Only way to create start a thread in java is calling its start method.
3) If you look at constructor of Thread class, no constructor takes parameter of Thread class itself. And
we know that Thread implements Runnable, effectively any call such as new Thread(a).start(); is
starting a thread with runnable mechanism.
4) Correct way to start thread (using extend) is calling its start method only directly.
e.g. new B1().start();
5) So effectively, in both techniques in your code, you are doing the same thing i.e. implementing
runnable.
Difference between Thread and Runnable I found is, Thread class provides apis to configure Thread
instance based on your need.If you extends Thread class, then1. you will have flexibility to set
priority to Thread instance,2. you can create daemon thread,3. you can check if thread is
terminated, alive etc.
SYNCRONIZATION:
//CLASS LOCK AND OBJECT LOCK
public class DemoClass
{
1.public synchronized static void demoMethod(){} Without static Object Lock.

2.
public void demoMethod(){
synchronized (DemoClass.class) //this object lock
{
//other thread safe code
}
}
3.
private final static Object lock = new Object(); // w/o static object lock.
public void demoMethod(){
synchronized (lock)
{
//other thread safe code
}
}

Method #1: Iterating over entries using For-Each loop.


This is the most common method and is preferable in most cases. Should be used if you need
both map keys and values in the loop.
Map<Integer,
Integer>
map
=
for
(Map.Entry<Integer,
Integer>
System.out.println("Key
= "
+
entry.getValue());
}

new
HashMap<Integer,
Integer>();
entry
:
map.entrySet())
{
entry.getKey() +
", Value
= "
+

Method #2: Iterating over keys or values using For-Each loop.


If you need only keys or values from the map, you can iterate over keySet or valuesinstead
of entrySet.
Map<Integer,
//iterating
for

Integer>

map

over
(Integer
key
System.out.println("Key

new

HashMap<Integer,

Integer>();

keys
map.keySet())
"
+

only
{
key);

values
map.values())
"
+

only
{
value);

}
//iterating
for

over
(Integer
value
System.out.println("Value

Method #3: Iterating using Iterator.


Using Generics:
Map<Integer,
Integer>
map
=
new
HashMap<Integer,
Integer>();
Iterator<Map.Entry<Integer,
Integer>>
entries
=
map.entrySet().iterator();
while
(entries.hasNext())
{
Map.Entry<Integer,
Integer>
entry
=
entries.next();
System.out.println("Key
= "
+
entry.getKey() +
", Value
= "
+

entry.getValue());
}

STRING SAFETY:
1) We know in java load classes using Class.forName(string). If Strings were mutable, then someone wrote the
code to load java.io.Writer. This string variable will be in pool. Now, some evil code can access this pool and
change the string to com.MakeHavocWriter and now when code gets executed, one can easily imagine the
consequences.
2) String pool is there so that one String instance can be referred from multiple reference variables. If string is
mutable, then one object can change the string content and other will see this undesired value.
3. Thread safe as immutable.

Using newInstance method of Class class


Class ref = Class.forName("DemoClass");
DemoClass obj = (DemoClass) ref.newInstance();

Class.forName() loads the class in memory. To create an instance of this class, we need to use newInstance().
Using class loaders loadClass()
Just like above mechanism, class loaders loadClass() method does the same thing.
instance.getClass().getClassLoader().loadClass("NewClass").newInstance();

Using clone() of java.lang.Object


This is also a way to have a new independent instance of a class.
NewClass obj = new NewClass();
NewClass obj2 = (NewClass) obj.clone();

Using Object serialization and deserialization


If you have gone through this article, you can understand that serialization and de-serialization is also a way
to have another instance of a class in system.
ObjectInputStream objStream = new ObjectInputStream(inputStream);
NewClass obj = (NewClass ) inStream.readObject();

Using Reflection
This is also a popular way to create new instances in most of available frameworks.
constructor.newInstance(); or
class.newInstance();

Static Methods
If a subclass defines a static method with the same signature as a static method in the superclass,
then the method in the subclass hides the one in the superclass.

The distinction between hiding a static method and overriding an instance method has important
implications:
The version of the overridden instance method that gets invoked is the one in the
subclass.
The version of the hidden static method that gets invoked depends on whether it is
invoked from the superclass or the subclass.
Consider an example that contains two classes. The first is Animal, which contains one instance
method and one static method:
public class Animal {
public static void testClassMethod() {
System.out.println("The static method in Animal");
}
public void testInstanceMethod() {
System.out.println("The instance method in Animal");
}
}

The second class, a subclass of Animal, is called Cat:


public class Cat extends Animal {
public static void testClassMethod() {
System.out.println("The static method in Cat");
}
public void testInstanceMethod() {
System.out.println("The instance method in Cat");
}
public static void main(String[] args) {
Cat myCat = new Cat();
Animal myAnimal = myCat;
Animal.testClassMethod();
myAnimal.testInstanceMethod();
}
}

The Cat class overrides the instance method in Animal and hides the static method in Animal.
The main method in this class creates an instance of Cat and invokes testClassMethod() on the
class andtestInstanceMethod() on the instance.
The output from this program is as follows:
The static method in Animal
The instance method in Cat

As promised, the version of the hidden static method that gets invoked is the one in the
superclass, and the version of the overridden instance method that gets invoked is the one in the
subclass.
Interface Methods

Default methods and abstract methods in interfaces are inherited like instance methods.
However, when the supertypes of a class or interface provide multiple default methods with the

same signature, the Java compiler follows inheritance rules to resolve the name conflict. These
rules are driven by the following two principles:
Instance methods are preferred over interface default methods.
Consider the following classes and interfaces:
public class Horse {
public String identifyMyself() {
return "I am a horse.";
}
}
public interface Flyer {
default public String identifyMyself() {
return "I am able to fly.";
}
}
public interface Mythical {
default public String identifyMyself() {
return "I am a mythical creature.";
}
}
public class Pegasus extends Horse implements Flyer, Mythical {
public static void main(String... args) {
Pegasus myApp = new Pegasus();
System.out.println(myApp.identifyMyself());
}
}

The method Pegasus.identifyMyself returns the string I

am a horse.

Methods that are already overridden by other candidates are ignored. This circumstance
can arise when supertypes share a common ancestor.
Consider the following interfaces and classes:
public interface Animal {
default public String identifyMyself() {
return "I am an animal.";
}
}
public interface EggLayer extends Animal {
default public String identifyMyself() {
return "I am able to lay eggs.";
}
}
public interface FireBreather extends Animal { }
public class Dragon implements EggLayer, FireBreather {
public static void main (String... args) {
Dragon myApp = new Dragon();
System.out.println(myApp.identifyMyself());
}
}

The method Dragon.identifyMyself returns the string I

am able to lay eggs.

I am just having hard time to understand concept behind putting wait() in object class For this questions sake
consider as if wait() and notifyAll() are in thread class
In the Java language, you wait() on a particular instance of an Object -- a monitor assigned to that object to be
precise. If you want to send a signal to a single thread that is waiting on that specific object instance then you

call notify() on that object. If you want to send a signal to all threads that are waiting on that object instance, you
use notifyAll() on that object.
If wait() and notify() were on the Thread instead then each thread would have to know the status of every other
thread. How would thread1 know that thread2 was waiting for access to a particular resource? If thread1 needed
to call thread2.notify() it would have to somehow find out that thread2 was waiting. There would need to be some
mechanism for threads to register the resources or actions that they need so others could signal them when stuff
was ready or available.
In Java, the object itself is the entity that is shared between threads which allows them to communicate with each
other. The threads have no specific knowledge of each other and they can run asynchronously. They run and they
lock, wait, and notify on the object that they want to get access to. They have no knowledge of other threads and
don't need to know their status. They don't need to know that it is thread2 which is waiting for the resource -they just notify on the resource and whomever it is that is waiting (if anyone) will be notified.
1. yield() 2. join() 3.sleep()
1.

yield() method pauses the currently executing thread temporarily for giving a chance to the remaining
waiting threads of the same priority to execute. If there is no waiting thread or all the waiting threads
have a lower priority then the same thread will continue its execution. The yielded thread when it will get
the chance for execution is decided by the thread scheduler whose behavior is vendor dependent.

2.

join() If any executing thread t1 calls join() on t2 i.e; t2.join() immediately t1 will enter into waiting state
until t2 completes its execution.

3.

sleep() Based on our requirement we can make a thread to be in sleeping state for a specified period of
time (hope not much explanation required for our favorite method). LOCK NOT RELEASED.
Write a program to swap two numbers with out using third variable?

Connection leak basically happens when we open a connection to the database from our application and forget to
close it, or for some reasons it doesnt get closed.
To implement connection pooling we basically use these connection string properties ;
1) Connection Lifetime (Default 0) - When a connection is returned to the pool, its creation time is compared
with the current time, and the connection is destroyed if that time span (in seconds) exceeds the value specified
by Connection Lifetime. This is useful in clustered configurations to force load balancing between a running server
and a server just brought online. A value of zero (0) will cause pooled connections to have the maximum time-out.
2) Pooling (Default true) -; When true, the connection is drawn from the appropriate pool, or if necessary,
created and added to the appropriate pool.
3) Max Pool Size (Default 100 ) -:The maximum number of connections allowed in the pool.
4) Min Pool Size (Default 0 ) -:The minimum number of connections allowed in the pool.
5) Connect Timeout or Connection Timeout (Default 15) -: The length of time (in seconds) to wait for a
connection to the server before terminating the attempt and generating an error.
Difference between save and persist method in Hibernate
First difference between save and persist is there return type. Similar to save method persist also INSERT records
into database but return type of persist is void while return type of save is Serializable object.

2) Another difference between persist and save is that both methods make a transient instance persistent.
However,persist() method doesn't guarantee that the identifier value will be assigned to the persistent instance
immediately, the assignment might happen at flush time.
3) persist() method guarantees that it will not execute an INSERT statement if it is called outside of transaction
boundaries. save() method does not guarantee the same, it returns an identifier, and if an INSERT has to be
executed to get the identifier (e.g. "identity" generator), this INSERT happens immediately, no matter if you are
inside or outside of a transaction.
4) Because of its above behavior of persist method outside transaction boundary, its useful in long-running
conversations with an extended Session context. On the other hand save method is not good in a long-running
conversation with an extended Session context.
Difference between get and load method
1. Behavior when Object is not found in Session CacheApart from performance this is another difference
between get and load which is worth remembering. get method of Hibernate Session class returns null if object is
not found in cache as well as on database while load() method throwsObjectNotFoundException if object is not
found on cache as well as on database but never return null.
2. Database hitGet method always hit database while load() method may not always hit the database, depending
upon which method is called. other than getId() is called on persistent or entity object.
3. Proxy Get method never returns a proxy, it either returns null or fully initialized Object, while load() method
may return proxy, which is the object with ID but without initializing other properties, which is lazily initialized. If
you are just using returned object for creating relationship and only need Id then load() is the way to go.
4. PerformanceBy far most important difference between get and load in my opinion. get method will return a
completely initialized object if Object is not on the cache but exists on Database, which may involve multiple
round-trips to database based upon object relational mappings while load() method of Hibernate can return
a proxy which can be initialized on demand (lazy initialization) when a non identifier method is accessed. Due to
above reason use of load method will result in slightly better performance, but there is a caveat that proxy
object will throw ObjectNotFoundException later if corresponding row doesnt exists in database, instead of failing
immediately so not a fail fast behavior.5. load method exists prior to get method which is added on user request.
When to use Session get() and load() in Hibernate
1. Use get method to determine if an instance exists or not because it can return null if instance doesnt exists in
cache and database and use load method to retrieve instance only if you think that instance should exists and non
availability is an error condition.
2. As stated in difference number 2 between get and load in Hibernate. get() method could suffer performance
penalty if only identifier method like getId() is accessed. So consider using load method if your code doesn't
access any method other than identifier or you are OK with lazy initialization of object, if persistent object is not in
Session Cache because load() can return proxy.
How to call get records in Hibernate using get and load method
If you look at below code , there is not much difference on calling get() and load() method, though both
are overloadednow and can accept few more parameters but the primary methods looks exactly identical. Its
there behavior which makes them different.
//Example of calling get method of Hiberante Session class
Session session = SessionFactory.getCurrentSession();
Employee Employee = (Employee) session.get(Employee.class, EmployeeID);
//Example of calling load method of Hiberante Session

Session session = SessionFactory.getCurrentSession();


Employee Employee = (Employee) session.load(Employee.class, EmployeeID);
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Employee" table="EMPLOYEE">
<meta attribute="class-description">
This class contains the employee detail.
</meta>
<id name="id" type="int" column="id">
<generator class="native"/>
</id>
<property name="firstName" column="first_name" type="string"/>
<property name="lastName" column="last_name" type="string"/>
<property name="salary" column="salary" type="int"/>
</class>
</hibernate-mapping>
public class ManageEmployee {
private static SessionFactory factory;
public static void main(String[] args) {
try{
factory = new Configuration().configure().buildSessionFactory();
}catch (Throwable ex) {
System.err.println("Failed to create sessionFactory object." + ex);
throw new ExceptionInInitializerError(ex);
}
ManageEmployee ME = new ManageEmployee();
/* Add few employee records in database */
Integer empID1 = ME.addEmployee("Zara", "Ali", 1000);
Integer empID2 = ME.addEmployee("Daisy", "Das", 5000);
Integer empID3 = ME.addEmployee("John", "Paul", 10000);
/* List down all the employees */
ME.listEmployees();
/* Update employee's records */
ME.updateEmployee(empID1, 5000);
/* Delete an employee from the database */
ME.deleteEmployee(empID2);
/* List down new list of the employees */
ME.listEmployees();
}
/* Method to CREATE an employee in the database */
public Integer addEmployee(String fname, String lname, int salary){
Session session = factory.openSession();
Transaction tx = null;
Integer employeeID = null;
try{
tx = session.beginTransaction();
Employee employee = new Employee(fname, lname, salary);
employeeID = (Integer) session.save(employee);
tx.commit();
}catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
}finally {
session.close();
}
return employeeID;
}
/* Method to READ all the employees */
public void listEmployees( ){
Session session = factory.openSession();
Transaction tx = null;
try{
tx = session.beginTransaction();

List employees = session.createQuery("FROM Employee").list();


for (Iterator iterator =
employees.iterator(); iterator.hasNext();){
Employee employee = (Employee) iterator.next();
System.out.print("First Name: " + employee.getFirstName());
System.out.print(" Last Name: " + employee.getLastName());
System.out.println(" Salary: " + employee.getSalary());
}
tx.commit();
}catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
}finally {
session.close();
}
}
/* Method to UPDATE salary for an employee */
public void updateEmployee(Integer EmployeeID, int salary ){
Session session = factory.openSession();
Transaction tx = null;
try{
tx = session.beginTransaction();
Employee employee =
(Employee)session.get(Employee.class, EmployeeID);
employee.setSalary( salary );
session.update(employee);
tx.commit();
}catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
}finally {
session.close();
}
}
/* Method to DELETE an employee from the records */
public void deleteEmployee(Integer EmployeeID){
Session session = factory.openSession();
Transaction tx = null;
try{
tx = session.beginTransaction();
Employee employee =
(Employee)session.get(Employee.class, EmployeeID);
session.delete(employee);
tx.commit();
}catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
}finally {
session.close();
}
}
}
What is difference between overloading and over ridding?
Over Loading

Over Ridding

It happens in same class

It happens in case of inheritance

Method name same and argument different

Method name and arguments same

Return type doesn't consider

Return type considers

It is known as compile time and static binding

Its known as runtime or dynamic binding

It can have any access level

But here same access level or widder. It can

What is Class Loader in java ?


Java Runtime Environment that dynamically loads Java classes into the Java Virtual Machine on demand .
There are three types of class loaders. There are

Bootstrap class loader


The bootstrap class loader loads the core Java libraries[5] located in the {JAVA_HOME}/lib directory
Extensions class loader
The extensions class loader loads the code in the extensions directories {JAVA_HOME}/lib/ext directory
System Class Path Loader
The system class loader loads code found on java.class.path, which maps to the system CLASSPATH
variable
What is the order of execution of Class Loader in java?
Java applications involve three classloaders Bootstrap, Extensions and System-Classpath classloaders
Bootstrap classloader is the parent of all classloaders ,extensions Classloader is the immediate child of Bootstrap
classloader and System-Classpath classloader is the immediate child of Extensions classloader. Generally Order of
execution happens from sub-sequent children to parent.
So order of execution is starts from System-classpath-loader then extension then Bootstrap Loader.
What is differenence between ClassNotFoundException and NoClassDefFoundError ?
ClassNotFoundException is generated by a call to Class.forName() with a String that contains a class not available
on the bundle's class path. For example when we are dynamically want to load the class using
Class.forName("oracle.jdbc.driver.OracleDriver"); if that class is not aviailable in runtion, it'll throw
ClassNotFoundException
NoClassDefFoundError is thrown if the Java Virtual Machine or a ClassLoader instance tries to load in the definition
of a class and that class or its dependancies are not available in run time. For example if Class x extends Class y
and Class y is extends class Z .When class loader tries to load class x if any of the depenacies is missing it'll give

Random

Key-

Duplicate

Null

Thread

Collection

Ordering

Access

Value

Elements

Element

Safety

ArrayList

Yes

Yes

No

Yes

Yes

No

LinkedList

Yes

No

No

Yes

Yes

No

HashSet

No

No

No

No

Yes

No

TreeSet

Yes

No

No

No

No

No

HashMap

No

Yes

Yes

No

Yes

No

TreeMap

Yes

Yes

Yes

No

No

No

Vector

Yes

Yes

No

Yes

Yes

Yes

Hashtable

No

Yes

Yes

No

No

Yes

Properties

No

Yes

Yes

No

No

Yes

Stack

Yes

No

No

Yes

Yes

Yes

CopyOnWriteArrayList

Yes

Yes

No

Yes

Yes

Yes

ConcurrentHashMap

No

Yes

Yes

No

No

Yes

CopyOnWriteArraySet

No

No

No

No

Yes

Yes

"What happens On HashMap in Java if the size of the HashMap exceeds a given threshold defined by
load factor ?". Until you know how HashMap works exactly you won't be able to answer this question. If the size

of the Map exceeds a given threshold defined by load-factor e.g. if load factor is .75 it will act to re-size the map
once it filled 75%. Similar to other collection classes like ArrayList, Java HashMap re-size itself by creating a new
bucket array of size twice of previous size of HashMap , and then start putting every old element into that new
bucket array. This process is called rehashingbecause it also applies hash function to find new bucket location.
2.

What is difference between poll() and remove() method of Queue interface?


Though both poll() and remove() method from Queue is used to remove object and returns head of the
queue, there is subtle difference between them. If Queue is empty() then a call toremove() method will
throw Exception, while a call to poll() method returns null. By the way, exactly which element is removed
from the queue depends upon queue's ordering policy and varies between different implementation, for
example PriorityQueue keeps lowest element as perComparator or Comparable at head position

fail-fast Iterators in Java


As name suggest fail-fast Iterators fail as soon as they realized that structure of Collection has been changed since
iteration has begun. Structural changes means adding, removing or updating any element from collection while
one thread is Iterating over that collection. fail-fast behavior is implemented by keeping a modification count and
if iteration thread realizes the change in modification count it throwsConcurrentModificationException.
fail-safe Iterator in java
Contrary to fail-fast Iterator, fail-safe iterator doesn't throw any Exception if Collection is modified structurally
while one thread is Iterating over it because they work on clone of Collection instead of original collection and
thats why they are called as fail-safe iterator. Iterator of CopyOnWriteArrayList is an example of fail-safe Iterator
also iterator written by ConcurrentHashMap keySet is also fail-safe iterator and never
throwConcurrentModificationException in Java.

You might also like