Tuesday, 14 January 2014

String Class and StringBuffer Class

String
Generally string is a sequence of characters. But in java, string is an object. String class is used to create string object.

How to create String object?
There are two ways to create String object:
  • By string literal
  • By new keyword
  1. String literal
String literal is created by double quote.For Example:
String s="Hello"; 
Each time you create a string literal, the JVM checks the string constant pool first. If the string already exists in the pool, a reference to the pooled instance returns. If the string does not exist in the pool, a new String object instantiates, then is placed in the pool.For example:
String s1="Welcome"; 
String s2="Welcome";//no new object will be created 

In the above example only one object will be created.First time JVM will find no string object with the name "Welcome" in string constant pool,so it will create a new object.Second time it will find the string with the name "Welcome" in string constant pool,so it will not create new object whether will return the reference to the same instance.
String objects are stored in a special memory area known as string constant pool inside the Heap memory.

Why java uses concept of string literal?
  • To make Java more memory efficient (because no new objects are created if it exists already in string constant pool).
  • String objects are immutable. Immutable simply means unmodifiable or unchangeable.
  • Once string object is created its data or state can't be changed but a new string object is created.
Methods of String class
java.lang.String class provides a lot of methods to work on string. Some of them are as follows: 
  1. public boolean equals(Object anObject):     Compares this string to the specified object.
  2. public boolean equalsIgnoreCase(String another):    Compares this String to another String, ignoring case.
  3. public String concat(String str):     Concatenates the specified string to the end of this string.
  4. public int compareTo(String str):     Compares two strings and returns int
  5. public int compareToIgnoreCase(String str):    Compares two strings, ignoring case differences.
  6. public String substring(int beginIndex):    Returns a new string that is a substring of this string.
  7. public String substring(int beginIndex,int endIndex):    Returns a new string that is a substring of this string.
  8. public String toUpperCase():    Converts all of the characters in this String to upper case
  9. public String toLowerCase():    Converts all of the characters in this String to lower case.
  10. public String trim():    Returns a copy of the string, with leading and trailing whitespace omitted.
  11. public boolean startsWith(String prefix):    Tests if this string starts with the specified prefix.
  12. public boolean endsWith(String suffix):    Tests if this string ends with the specified suffix.
  13. public char charAt(int index):    Returns the char value at the specified index.
  14. public int length():     Returns the length of this string.
  15. public String intern():    Returns a canonical representation for the string object.
StringBuffer class:

  • The StringBuffer class is used to created mutable (modifiable) string. The StringBuffer class is same as String except it is mutable i.e. it can be changed.
  • StringBuffer class is thread-safe i.e. multiple threads cannot access it simultaneously .So it is safe and will result in an order.

Commonly used Constructors of StringBuffer class:


StringBuffer(): creates an empty string buffer with the initial capacity of 16.
StringBuffer(String str): creates a string buffer with the specified string.
StringBuffer(int capacity): creates an empty string buffer with the specified capacity as length.

Commonly used methods of StringBuffer class:
  1. public synchronized StringBuffer append(String s): is used to append the specified string with this string. The append() method is overloaded like append(char), append(boolean), append(int), append(float), append(double) etc.
  2. public synchronized StringBuffer insert(int offset, String s): is used to insert the specified string with this string at the specified position. The insert() method is overloaded like insert(int, char), insert(int, boolean), insert(int, int), insert(int, float), insert(int, double) etc.
  3. public synchronized StringBuffer replace(int startIndex, int endIndex, String str): is used to replace the string from specified startIndex and endIndex.
  4. public synchronized StringBuffer delete(int startIndex, int endIndex): is used to delete the string from specified startIndex and endIndex.
  5. public synchronized StringBuffer reverse(): is used to reverse the string.
  6. public int capacity(): is used to return the current capacity.
  7. public void ensureCapacity(int minimumCapacity): is used to ensure the capacity at least equal to the given minimum.
  8. public char charAt(int index): is used to return the character at the specified position.
  9. public int length(): is used to return the length of the string i.e. total number of characters.
  10. public String substring(int beginIndex): is used to return the substring from the specified beginIndex.
  11. public String substring(int beginIndex, int endIndex): is used to return the substring from the specified beginIndex and endIndex.

What is mutable string?

A string that can be modified or changed is known as mutable string. StringBuffer and StringBuilder classes are used for creating mutable string.

Example of StringBuffer class by append() method

The append() method concatenates the given argument with this string.
class A{ 
public static void main(String args[]){ 
 
StringBuffer sb=new StringBuffer("Hello "); 
sb.append("Java");//now original string is changed 
 
System.out.println(sb);//prints Hello Java 

Object Class

  • The Object class is the parent/cosmic class(ancestor) of all the classes in java by default. In other words, it is the topmost class of java.
  • The Object class is beneficial if you want to refer any object whose type you don't know. Notice that parent class reference variable can refer the child class object, know as upcasting.
For example, there is getObject() method that returns an object but it can be of any type like Employee,Student etc, we can use Object class reference to refer that object. Example:

Object obj=getObject();//we don't know what object would be returned from this method 
The Object class provides some common behaviors to all the objects such as object can be compared, object can be cloned, object can be notified etc.

Methods of Object class

The Object class provides many methods. They are as follows:
Method    Description

  1. public final ClassgetClass() :     returns the Class class object of this object. The Class class can further be used to get the metadata of this class.
  2. public int hashCode() :     returns the hashcode number for this object.
  3. public boolean equals(Object obj):     compares the given object to this object.
  4. protected Object clone() throws CloneNotSupportedException:     creates and returns the exact copy (clone) of this object.
  5. public String toString():     returns the string representation of this object.
  6. public final void notify():     wakes up single thread, waiting on this object's monitor.
  7. public final void notifyAll():     wakes up all the threads, waiting on this object's monitor.
  8. public final void wait(long timeout)throws InterruptedException:     causes the current thread to wait for the specified milliseconds, until another thread notifies (invokes notify() or notifyAll() method).
  9. public final void wait(long timeout,int nanos)throws InterruptedException:    causes the current thread to wait for the specified miliseconds and nanoseconds, until another thread notifies (invokes notify() or notifyAll() method).
  10. public final void wait()throws InterruptedException: causes the current thread to wait, until another thread notifies (invokes notify() or notifyAll() method).
  11. protected void finalize()throws Throwable:     is invoked by the garbage collector before object is being garbage collected.

Abstract

Abstract class
  • A class that is declared as abstract is known as abstract class. It needs to be extended and its method implemented. It cannot be instantiated.
  • An abstract class is a class that is declared abstract—it may or may not include abstract methods. Abstract classes cannot be instantiated, but they can be subclassed(inherited).
  • Syntax to declare the abstract class: 
             abstract class <class_name>{}
  • When an abstract class is subclassed(inherited), the subclass usually provides implementations for all of the abstract methods in its parent class. However, if it does not, the subclass must also be declared abstract.
  • An abstract class can have data member, abstract method, method body, constructor and even main() method.
  • If there is any abstract method in a class, that class must be abstract.
  • If you are extending any abstract class that have abstract method, you must either provide the implementation of the method or make this class abstract.
Abstract method

A method that is declared as abstract and does not have implementation is known as abstract method.

Syntax to define the abstract method

abstract return_type <method_name>();//no braces{}  
Example:

public abstract class Shape(){

int area;
 public abstract void area();

}
If a class includes abstract methods, the class itself must be declared abstract, as in:

public abstract class Rectangle {
   int length,breadth;
   abstract void draw();
}

Abstract Class & Method Important Points:


  • An abstract class may also have concrete (complete) methods.
  • For design purpose, a class can be declared abstract even if it does not contain any abstract methods.
  • Reference of an abstract class can point to objects of its sub-classes thereby achieving run-time polymorphism Ex: Shape obj = new Rectangle();
  • A class must be compulsorily labelled abstract , if it has one or more abstract methods.

Sunday, 12 January 2014

Diffrence between overloading and overriding

  • First difference is, in case of method overloading in Java, Signature of method changes while in case of method overriding it remains same.
  • Second difference is that you can overload method in one class but overriding can only be done on subclass.
  • You can not override static, final and private method in Java but you can overload static, final or private method in Java.
  • Overloaded method in Java is bonded by static binding and overridden methods are subject to dynamic binding.
  • Private and final method can also be not overridden in Java.

Notes: 
  • The final keyword is mostly used to guarantee a good usage of the code. For instance (non-static) methods, this allows the compiler to expand the method (similar to an inline function) if the method is small enough. Sometimes it is required to use it. For instance, a nested class can only access to the members of the top-level class if they are final.
  • Java does not support multiple inheritance ie derived class(subclass) cannot have two or more base classes.
  • Java has only public inheritance.
  • Overloading is achieved using inheritance and overloading is achieved using polymorphism.
  • Dynamic data types governs the method selection.
Example:  clsA a1 = new clsB();
                 a.mtd();
clsA is the base class and clsB is subclass, here object of clsB is created which is referenced by a1, so when we call mtd() then mth() of clsB will be called not of clsA.

Super and Final

Super: 
Super is a reference variable that is used to refer immediate parent class object.

Syntax:

super.<method-name>();

Whenever you create the instance of subclass, an instance of parent class is created implicitly i.e. referred by super reference variable.


Usage of super Keyword:
 

  • Super is used to refer immediate parent class instance variable. It is used inside a sub-class method definition to call a method defined in the super class. Private methods of the super-class cannot be called. Only public and protected methods can be called by the super keyword. 
  • Super() is used to invoke immediate parent class constructor. It is also used by class constructors to invoke constructors of its parent class. 
  • Super is used to invoke immediate parent class method.

1) super is used to refer immediate parent class instance variable.
 

Problem without super keyword

    class Vehicle{ 
      int speed=50; 
    } 
     
    class Bike extends Vehicle{ 
      int speed=100; 
         
      void display(){ 
       System.out.println(speed);//will print speed of Bike  
      } 
      public static void main(String args[]){ 
       Bike b=new Bike(); 
       b.display(); 
        
    } 
    } 

Output:100

In the above example Vehicle and Bike both class have a common property speed. Instance variable of current class is refered by instance bydefault, but if

parent class instance variable is to be referred then we use super keyword to distinguish between parent class instance variable and current class instance variable.

Solution by super keyword
    //example of super keyword 
     
    class Vehicle{ 
      int speed=50; 
    } 
     
    class Bike extends Vehicle{ 
      int speed=100; 
         
      void display(){ 
       System.out.println(super.speed);//will print speed of Vehicle now 
      } 
      public static void main(String args[]){ 
       Bike b=new Bike(); 
       b.display(); 
        
    } 
    } 

Output:50

2) super is used to invoke parent class constructor.The super keyword can also be used to invoke the parent class constructor as given below:

    class Vehicle{ 
      Vehicle(){System.out.println("Vehicle is created");} 
    } 
     
    class Bike extends Vehicle{ 
      Bike(){ 
       super();//will invoke parent class constructor 
       System.out.println("Bike is created"); 
      } 
      public static void main(String args[]){ 
       Bike b=new Bike(); 
           
    } 
    } 

Output:Vehicle is created
       Bike is created

super() is added in each class constructor automatically by compiler.

Another example of super keyword where super() is provided by the compiler implicitly.

    class Vehicle{ 
      Vehicle(){System.out.println("Vehicle is created");} 
    } 
     
    class Bike extends Vehicle{ 
      int speed; 
      Bike(int speed){ 
        this.speed=speed; 
        System.out.println(speed); 
      } 
      public static void main(String args[]){ 
       Bike b=new Bike(10); 
     } 
    } 

Output:Vehicle is created
       10

3) super can be used to invoke parent class method.
The super keyword can also be used to invoke parent class method. It should be used in case subclass contains the same method as parent class as in the example given below:

    class Person{ 
    void message(){System.out.println("welcome");} 
    } 
     
    class Student extends Person{ 
    void message(){System.out.println("welcome to java");} 
     
    void display(){ 
    message();//will invoke current class message() method 
    super.message();//will invoke parent class message() method 
    } 
     
    public static void main(String args[]){ 
    Student s=new Student(); 
    s.display(); 
    } 
    } 

Output:welcome to java
       welcome

In the above example Student and Person both classes have message() method if we call message() method from Student class, it will call the message() method of Student class not of Person class because priority is given to local.

Final: 

Final is  used for 
  • Variable
  • Method
  • Class 
For a variable

The final keyword only allows a single assignment for the variable. That is to say, once the variable has been assigned, its value is in read-only. If the variable is a primitive type, its value will no longer change. If it is an object, only its reference will no longer change. Keep in mind that its value can still be changed.

For a class

The final keyword forbids to create a subclass(stops inheritance). It is the case of the Integer or String class.

A final class cannot be abstract. The final keyword is similar to sealed keyword in C#.

For a method

The final keyword forbids to override the method in a subclass. It is useless if the class is already final and a private method is implicitly final. A final method cannot be abstract.

Saturday, 11 January 2014

Containment and Inheritance


Containment & inheritance are ways of code re-usability. Containment is a 'has-a' relationship while Inheritance is a 'is-a' relationship. Containment means use of object of one class in another while inheritance means reusing the features of a class in its derived class.

Containment:
Containment relationship means the use of an object of a class as a member of another class. Containment is a 'has-a' relation. e.g. an employee 'has-a' joining date.
Example:
class Employee
{
  int emp_id;
  String emp_name;
  MyDate date;   //MyDate is a class having date, month and year

  Emp()
  {
    emp_id=0;
    emp_name="abc";
    date=new MyDate();
  }

  Emp(int id, String name, MyDate d)
  {
    emp_id=id;
    emp_name=name;
    date=d;
  }

public static void main(String args[])
{
  Emp e1=new Emp();
  Emp e2=new Emp(123,"java", new MyDate(23,5,2012));
//to execute this,one needs to write MyDate class
}
}

Inheritance:
Inheritance involves deriving a class from a parent or base class. Inheritance is a 'is-a' relation. e.g.a car 'is-a' vehicle. Inheritance can be used only if one class has ability to behave like other class
Example:
package test;

import date.Date;
public class Employee {
int emp_id,emp_phno,emp_sal;
Date dob;
String name,city;
public Employee(int id,int phno,int sal,String nm,String ct,Date d) {
emp_id = id;
emp_phno = phno;
emp_sal = sal;
name = nm;
city = ct;
dob = d;
}
public void getsal(int sal) {
emp_sal = sal;
}
public String toString() {
return "ID:"+emp_id+"\tName:"+name+"\tContact No:"+emp_phno+"\tCity:"+city+"\tDate of joining:"+dob;
}
public static void main(String[] args) {
Employee emp = new Employee(1, 223323, 30000, "Reshma", "Pune", new Date(1,2,2013));
emp.getsal(30000);
System.out.println(emp+"\tSalary:"+emp.emp_sal);
}
}
----
package test;
import date.Date;
public class Manager extends Employee{

int target, incentives,mgr_sal;
Employee e;
public Manager(int trgt, int inc) {
super(2, 5, 400, "Xyz", "Mnb", new Date(12,3,2012));
target = trgt;
incentives = inc;
mgr_sal = 0;
e = new Employee(2, 332244, 40000, "Shweta", "Mumbai", new Date(12,3,2000));
}
public void getsal(int sal) {
mgr_sal = sal+incentives; 
}
public String toString() {
return e+"\tSalary:"+mgr_sal;
}
public static void main(String[] args) {
Manager mgr = new Manager(100000, 20000);
mgr.getsal(50000);
System.out.println(mgr);
}
}

Garbage Collection

Garbage Collection: 
Garbage collection (GC) is the process that aims to free up occupied memory that is no longer referenced by any reachable Java object, and is an essential part of the Java virtual machine's (JVM's) dynamic memory management system. In a typical garbage collection cycle all objects that are still referenced, and thus reachable, are kept. The space occupied by previously referenced objects is freed and reclaimed to enable new object allocation.

Garbage collection and the Java platform memory model

When you specify the startup option -Xmx on the command line of your Java application (for instance: java -Xmx:2g MyApp) memory is assigned to a Java process. This memory is referred to as the Java heap (or just heap). This is the dedicated memory address space where all objects created by your Java program (or sometimes the JVM) will be allocated. As your Java program keeps running and allocating new objects, the Java heap (meaning that address space) will fill up.

Eventually, the Java heap will be full, which means that an allocating thread is unable to find a large-enough consecutive section of free memory for the object it wants to allocate. At that point, the JVM determines that a garbage collection needs to happen and it notifies the garbage collector. A garbage collection can also be triggered when a Java program calls System.gc(). Using System.gc() does not guarantee a garbage collection. Before any garbage collection can start, a GC mechanism will first determine whether it is safe to start it. It is safe to start a garbage collection when all of the application's active threads are at a safe point to allow for it, e.g. simply explained it would be bad to start garbage collecting in the middle of an ongoing object allocation, or in the middle of executing a sequence of optimized CPU instructions, as you might lose context and thereby mess up end results.

A garbage collector should never reclaim an actively referenced object; to do so would break the Java virtual machine specification. A garbage collector is also not required to immediately collect dead objects. Dead objects are eventually collected during subsequent garbage collection cycles. While there are many ways to implement garbage collection, these two assumptions are true for all varieties. The real challenge of garbage collection is to identify everything that is live (still referenced) and reclaim any unreferenced memory, but do so without impacting running applications any more than necessary. A garbage collector thus has two mandates:

  1. To quickly free unreferenced memory in order to satisfy an application's allocation rate so that it doesn't run out of memory.
  2. To reclaim memory while minimally impacting the performance (e.g., latency and throughput) of a running application.

Two kinds of garbage collection

Reference counting collectors

Reference counting collectors keep track of how many references are pointing to each Java object. Once the count for an object becomes zero, the memory can be immediately reclaimed. This immediate access to reclaimed memory is the major advantage of the reference-counting approach to garbage collection. There is very little overhead when it comes to holding on to un-referenced memory. Keeping all reference counts up to date can be quite costly, however.

The main difficulty with reference counting collectors is keeping the reference counts accurate. Another well-known challenge is the complexity associated with handling circular structures. If two objects reference each other and no live object refers to them, their memory will never be released. Both objects will forever remain with a non-zero count. Reclaiming memory associated with circular structures requires major analysis, which brings costly overhead to the algorithm, and hence to the application.

Tracing collectors

Tracing collectors are based on the assumption that all live objects can be found by iteratively tracing all references and subsequent references from an initial set of known to be live objects. The initial set of live objects (called root objects or just roots for short) are located by analyzing the registers, global fields, and stack frames at the moment when a garbage collection is triggered. After an initial live set has been identified, the tracing collector follows references from these objects and queues them up to be marked as live and subsequently have their references traced. Marking all found referenced objects live means that the known live set increases over time. This process continues until all referenced (and hence all live) objects are found and marked. Once the tracing collector has found all live objects, it will reclaim the remaining memory.

Tracing collectors differ from reference-counting collectors in that they can handle circular structures. The catch with most tracing collectors is the marking phase, which entails a wait before being able to reclaim non-referenced memory.

Tracing collectors are most commonly used for memory management in dynamic languages; they are by far the most common for the Java language and have been commercially proven in production environments for many years. 

Tracing collector algorithms

Copying and mark-and-sweep garbage collection are not new, but they're still the two most common algorithms that implement tracing garbage collection today.

Copying collectors

Traditional copying collectors use a from-space and a to-space -- that is, two separately defined address spaces of the heap. At the point of garbage collection, the live objects within the area defined as from-space are copied into the next available space within the area defined as to-space. When all the live objects within the from-space are moved out, the entire from-space can be reclaimed. When allocation begins again it starts from the first free location in the to-space.

In older implementations of this algorithm the from-space and to-space switch places, meaning that when the to-space is full, garbage collection is triggered again and the to-space becomes the from-space.


More modern implementations of the copying algorithm allow for arbitrary address spaces within the heap to be assigned as to-space and from-space. In these cases they do not necessarily have to switch location with each other; rather, each becomes another address space within the heap.

One advantage of copying collectors is that objects are allocated together tightly in the to-space, completely eliminating fragmentation. Fragmentation is a common issue that other garbage collection algorithms struggle with.
Downsides of copying collectors

Copying collectors are usually stop-the-world collectors, meaning that no application work can be executed for as long as the garbage collection is in cycle. In a stop-the-world implementation, the larger the area you need to copy, the higher the impact on your application performance will be. This is a disadvantage for applications that are sensitive to response time. With a copying collector you also need to consider the worst-case scenario, when everything is live in the from-space. You always have to leave enough headroom for live objects to be moved, which means the to-space must be large enough to host everything in the from-space. The copying algorithm is slightly memory inefficient due to this constraint.

Mark-and-sweep collectors

Most commercial JVMs deployed in enterprise production environments run mark-and-sweep (or marking) collectors, which do not have the performance impact that copying collectors do. Some of the most famous marking collectors are CMS, G1, GenPar, and DeterministicGC.
A mark-and-sweep collector traces references and marks each found object with a "live" bit. Usually a set bit corresponds to an address or in some cases a set of addresses on the heap. The live bit can, for instance, be stored as a bit in the object header, a bit vector, or a bit map.

After everything has been marked live, the sweep phase will kick in. If a collector has a sweep phase it basically includes some mechanism for traversing the heap again (not just the live set but the entire heap length) to locate all the non-marked chunks of consecutive memory address spaces. Unmarked memory is free and reclaimable. The collector then links together these unmarked chunks into organized free lists. There can be various free lists in a garbage collector -- usually organized by chunk sizes. Some JVMs (such as JRockit Real Time) implement collectors with heuristics that dynamically size-range lists based on application profiling data and object-size statistics.

When the sweep phase is complete allocation will begin again. New allocation areas are allocated from the free lists and memory chunks could be matched to object sizes, object size averages per thread ID, or the application-tuned TLAB sizes. Fitting free space more closely to the size of what your application is trying to allocate optimizes memory and could help reduce fragmentation.

Downsides of mark-and-sweep collectors

The mark phase is dependent on the amount of live data on your heap, while the sweep phase is dependent on the heap size. Since you have to wait until both the mark and sweep phases are complete to reclaim memory, this algorithm causes pause-time challenges for larger heaps and larger live data sets.

One way that you can help heavily memory-consuming applications is to use GC-tuning options that accommodate various application scenarios and needs. Tuning can, in many cases, help at least postpone either of these phases from becoming a risk to your application or service-level agreements (SLAs). (An SLA specifies that the application will meet certain application response times -- i.e., latency.) Tuning for every load change and application modification is a repetitive task, however, as the tuning is only valid for a specific workload and allocation rate.

Implementations of mark-and-sweep

There are at least two commercially available and proven approaches for implementing mark-and-sweep collection. One is the parallel approach and the other is the concurrent (or mostly concurrent) approach.

Parallel collectors

Parallel collection means that resources assigned to the process are used in parallel for the purpose of garbage collection. Most commercially implemented parallel collectors are monolithic stop-the-world collectors -- all application threads are stopped until the entire garbage collection cycle is complete. Stopping all threads allows all resources to be efficiently used in parallel to finish the garbage collection through the mark and sweep phases. This leads to a very high level of efficiency, usually resulting in high scores on throughput benchmarks such as SPECjbb. If throughput is essential for your application, the parallel approach is an excellent choice.

The cost of most parallel collection -- and do consider this, especially for production environments -- is that application threads cannot do any work during a GC, just like with copying collectors. Using a parallel collector that implements stop-the-world collection will have a major impact on response-time sensitive applications, especially if you have a lot of references to trace, which will happen with many live or complex data structures on the heap. (Remember that for mark-and-sweep collectors the time to free up new memory is dependent on the time it takes to trace the live data set plus the time to traverse the heap during the sweep phase.) For a monolithic parallel approach using all resources in parallel, this entire time will be a pause, and that pause corresponds to the entire GC cycle.

Concurrent collectors

A concurrent collector is a much better fit for applications that are sensitive to response time. Concurrent means that some (or most) garbage collection work is performed concurrently with the running application threads. As not all resources are used for GC, you will have the challenge of deciding when to start a garbage collection in order to allow enough time for the cycle to end. You need enough time to trace the live set and reclaim the memory before the application runs out of memory. If the garbage collection doesn't complete in time the application will throw an out-of-memory error. You don't want to do garbage collection all the time because that would consume application resources, thus impacting throughput. It can be extra tricky to keep that balance in very dynamic environments, so heuristics have been designed to determine when to start garbage collection and when to do various GC optimizing tasks and how much at a time, etc.