Assertion in Java
Assertion facility is added in J2SE 1.4. In order to support this facility J2SE 1.4 added the keyword assert to the language, and AssertionError class. An assertion checks a boolean-typed expression that must be true during program runtime execution. The assertion facility can be enabled or disable at runtime.
Declaring Assertion
Assertion statements have two forms as given below
assert expression;
assert expression1 : expression2;
The first form is simple form of assertion, while second form takes another expression. In both of the form boolean expression represents condition that must be evaluate to true runtime.
If the condition evaluates to false and assertions are enabled, AssertionError will be thrown at runtime.
Some examples that use simple assertion form are as follows.
assert value > 5 ;
assert accontBalance > 0;
assert isStatusEnabled();
The expression that has to be asserted runtime must be boolean value. In third example isStatusEnabled() must return boolean value. If condition evaluates to true, execution continues normally, otherwise the AssertionError is thrown.
Following program uses simple form of assertion
//AssertionDemo.java
Class AssertionDemo{
Public static void main(String args[]){
System.out.println( withdrawMoney(1000,500) );
System.out.println( withdrawMoney(1000,2000) );
}
public double withdrawMoney(double balance , double amount){
assert balance >= amount;
return balance – amount;
}
}
In above given example, main method calls withdrawMoney method with balance and amount as arguments. The withdrawMoney method has a assert statement that checks whether the balance is grater than or equal to amount to be withdrawn. In first call the method will execute without any exception, but in second call it AssertionError is thrown if the assertion is enabled at runtime.
Enable/Disable Assertions
By default assertion are not enabled, but compiler complains if assert is used as an identifier or label. The following command will compile AssertionDemo with assertion enabled.
javac –source 1.4 AssertionDemo.java
The resulting AssertionDemo class file will contain assertion code.
By default assertion are disabled in Java runtime environment. The argument –eanbleassertion or –ea will enables assertion, while –disableassertion or –da will disable assertions at runtime.
The following command will run AssertionDemo with assertion enabled.
Java –ea AssertionDemo
or
Java –enableassertion AssertionDemo
Second form of Assertion
The second form of assertion takes another expression as an argument.
The syntax is,
assert expression1 : expression2;
where expression1 is the condition and must evaluate to true at runtime.
This statement is equivalent to
assert expression1 : throw new AssertionError(expression2);
Note: AssertionError is unchecked exception, because it is inherited from Error class.
Here, expression2 must evaluate to some value.
By default AssertionError doesn’t provide useful message so this form can be helpful to display some informative message to the user.
---------------------------------------------------------
links
http://download.oracle.com/docs/cd/E17476_01/javase/1.4.2/docs/guide/lang/assert.html
---------------------------------------------------------
1. How do I get the assert statement to work?
2. How do I get line numbers?
3. How do I get soft tabs?
4. How do I run Javadoc?
5. How do I see the javadoc for Sun-supplied classes?
6. Why are my JUnit results not showing up?
7. How do I create a test suite?
8. In JUnit, what's the difference between a "failure" and an "error"?
9. Why does Source->Format really mess up my formatting?
10. How do I import an existing program into Eclipse?
1. How do I get the assert statement to work?
In Eclipse 3.1, go to Window -> Preferences -> Java -> Compiler and set the Compiler Compliance Level to 1.4 or 5.0. Also check Use Default compliance settings. This tells the compiler to recognize and allow assert statements, but does not enable them.
In Eclipse 3.0 (Java 1.4), the settings are a little fussier. Go to Window -> Preferences -> Java -> Compiler -> Compliance and Classfiles and set:
Compiler Compliance Level: to 1.4
Use default compliance settings to unchecked
Generated .class files compatibility: to 1.4
Source compatibility: to 1.4
Disallow identifiers called 'assert': to Error
Compiler Compliance Level to 1.4
To enable (make active) assert statements, you must set a flag to the compiler. Go to Run -> Run... -> Arguments, and in the box labeled VM arguments:, enter either -enableassertions or just -ea. Accept the changes and close the dialog.
To get Javadoc to recognize the assert statement, see How do I run Javadoc?
2. How do I get line numbers?
Go to Window -> Preferences -> General -> Editors -> All Text Editors and check Show line numbers.
3. How do I get soft tabs?
To get soft tabs (tabs replaced by spaces) as you type, go to Window -> Preferences -> Java -> Code style-> Formatter and select the profile Java Conventions [built-in]. This should be set correctly to give soft tabs.
You can create your own profile by clicking Show...; for soft tabs, go to Indentation uncheck Use tab characters. After making your changes, you will be prompted for a name for your new profile.
4. How do I run Javadoc?
1. In the Package Explorer window, choose the package or file for which you want to generate documentation.
2. Choose File -> Export... -> Javadoc -> Next>
1. If the dialog box displays the message The Javadoc command does not exist, then you need to click the Configure... button and locate javadoc.exe. You already have this file--it is probably in YourJavaDirectory/jdk1.5.0/bin/.
3. Select the project, and the destination for the Javadoc files. Normally, you should only generate documentation for public fields and methods.
4. If you have no assert statements, you can click Finish at this point.
5. Click Next >.
6. Click Next > again.
7. Check JRE 1.4 source compatibility (otherwise your assert statements will be treated as errors). [See also How do I get the assert statement to work?]
8. Click Finish.
5. How do I see the javadoc for Sun-supplied classes?
If you hover (don't click) your mouse over the name of a method, you should see a simplified Javadoc explanation. If this doesn't work for Sun-supplied methods, then you don't have the source code installed. Here's how to install the source code:
1. Go to http://java.sun.com/j2se/1.5.0/download.jsp and choose to download the JDK 5.0 Source Code (I don't know what SCSL and JRL are, but SCSL worked for me).
2. For JDK 5.0, select Download(SCSL source) .
3. Register. This is relatively painless, especially if you either ignore or enjoy reading license agreements.
4. Download JDK (SCSL) 5.0 (1.5.0). This will give you a file jdk-1_5_0-src.scsl.zip. You do not need to unzip this file; Eclipse likes it the way it is.
5. In Eclipse, go to Projects -> Properties -> Java Build Path -> Libraries and expand JRE System Library [jre 1.5.0], then rt.jar. Select Source attachment and click Edit....
6. Select the above zip file.
7. Finish by exiting the dialog boxes.
6. Why are my JUnit results not showing up?
Maybe it's because all your tests succeeded. For more satisfying results, go to Window -> Preferences -> Java -> JUnit and uncheck Show the JUnit results view only when an error or failure occurs.
7. How do I create a test suite?
Go to File -> New -> Other... -> Java -> JUnit -> TestSuite, and click Next>. Select all the classes, and click Finish.
You can run this test suite the same way you run other JUnit tests.
8. In JUnit, what's the difference between a "failure" and an "error"?
A failure is when one of your assertions fails--that is, your program does something wrong, and your JUnit test notices and reports the fact. An error is when some other Exception occurs--one you haven't tested for and didn't expect, such as a NullPointerException or an ArrayIndexOutOfBoundsException.
9. Why does Source->Format really mess up my formatting?
You have unmatched brackets, braces, or parentheses, and the code reformatter is doing the best it can. Find the syntax error (somewhere near the beginning of the messed up formatting), fix it, and reformat.
10. How do I import an existing program into Eclipse?
Here are two ways that work. First,
1. In your workspace folder, create a new folder, and put your files into that folder.
2. Ask Eclipse to create a new project (File -> New -> Project...) and, for the name of the project, type in the exact name of your new folder.
3. Click Finish.
The second way is very similar:
1. Ask Eclipse to create a new project (File -> New -> Project...) with any suitable name.
2. Copy your files into the new folder.
3. In Eclipse's Package Explorer pane, right-click on the new project and choose Refresh from the pull-down menu.
---------------------------------------------------------
package com;
public class AssertTest {
/**
* @param args
*/
public boolean myErrorDisplay(){
System.out.println("here error");
return false;
}
public static void main(String[] args) {
// The following assert statement will stop execution
// with a message if assertions are turned on.
assert 1<10;
assert true;
assert 1>10 : new AssertTest().myErrorDisplay();
assert 1<10;
assert true;
// The following statement will only be printed if
// assertions are turned off because assertions
// were not allowed at run time by the -ea parameter.
System.out.println("Assertions are not active.");
}
}
Monday, July 19, 2010
Anonymous and Inner Class - example
an example of a simple anonymous class
public class MainClass {
public static void main(String[] args) {
Ball b = new Ball() {
public void hit() {
System.out.println("You hit it!");
}
};
b.hit();
}
interface Ball {
void hit();
}
}
and
-------------------------------------------------------
package com;
public class AnuClass {
/**
* @param args
*/
public static void myanmethod(){
Ball b = new Ball(){
public void hit() {
System.out.println("You hit it!");
}
};
b.hit();
}
interface Ball {
void hit();
}
public static void main(String[] args) {
AnuClass.myanmethod();
}
}
-------------------------------------------------------
Access inner class from outside
public class Main {
public static void main(String[] args) {
Outer outer = new Outer();
outer.new Inner().hello();
}
}
class Outer {
public class Inner {
public void hello(){
System.out.println("Hello from Inner()");
}
}
}
------------------------------------------------------
Access inner class from outside
public class Main {
public static void main(String[] args) {
Outer outer = new Outer();
outer.new Inner().hello();
}
}
class Outer {
public class Inner {
public void hello(){
System.out.println("Hello from Inner()");
}
}
}
--------------------------------------------------------
package com;
public class InOutClass {
/**
* @param args
*/
public static void main(String[] args) {
Outer outer = new Outer();
outer.new Inner().hello();
new Thread(new Thread(){
int i=0;
public void run() {
try {
while (i<10) {
sleep(1000); System.out.print("1");
i++;
}
}
catch(InterruptedException ex) {}
}
}).start();
// second option
Thread t = new Thread(new Thread(){
public void run() {
int i=0;
try {
while (i<10) {
sleep(1000); System.out.print("2");
i++;
}
}
catch(InterruptedException ex) {}
}
});
t.start();
new Thread(new Runnable() {
public void run() {
int i=0;
while (i<10) { //sleep(1000); //sleep is not a method of Runnable Interface,its in Thread class
System.out.print("3");
}
}
}).start();
}
}
class Outer {
public class Inner {
public void hello(){
System.out.println("Hello from Inner()");
}
}
}
public class MainClass {
public static void main(String[] args) {
Ball b = new Ball() {
public void hit() {
System.out.println("You hit it!");
}
};
b.hit();
}
interface Ball {
void hit();
}
}
and
-------------------------------------------------------
package com;
public class AnuClass {
/**
* @param args
*/
public static void myanmethod(){
Ball b = new Ball(){
public void hit() {
System.out.println("You hit it!");
}
};
b.hit();
}
interface Ball {
void hit();
}
public static void main(String[] args) {
AnuClass.myanmethod();
}
}
-------------------------------------------------------
Access inner class from outside
public class Main {
public static void main(String[] args) {
Outer outer = new Outer();
outer.new Inner().hello();
}
}
class Outer {
public class Inner {
public void hello(){
System.out.println("Hello from Inner()");
}
}
}
------------------------------------------------------
Access inner class from outside
public class Main {
public static void main(String[] args) {
Outer outer = new Outer();
outer.new Inner().hello();
}
}
class Outer {
public class Inner {
public void hello(){
System.out.println("Hello from Inner()");
}
}
}
--------------------------------------------------------
package com;
public class InOutClass {
/**
* @param args
*/
public static void main(String[] args) {
Outer outer = new Outer();
outer.new Inner().hello();
new Thread(new Thread(){
int i=0;
public void run() {
try {
while (i<10) {
sleep(1000); System.out.print("1");
i++;
}
}
catch(InterruptedException ex) {}
}
}).start();
// second option
Thread t = new Thread(new Thread(){
public void run() {
int i=0;
try {
while (i<10) {
sleep(1000); System.out.print("2");
i++;
}
}
catch(InterruptedException ex) {}
}
});
t.start();
new Thread(new Runnable() {
public void run() {
int i=0;
while (i<10) { //sleep(1000); //sleep is not a method of Runnable Interface,its in Thread class
System.out.print("3");
}
}
}).start();
}
}
class Outer {
public class Inner {
public void hello(){
System.out.println("Hello from Inner()");
}
}
}
Comparable,Comparator - sample
package com;
import java.io.Serializable;
import java.util.Comparator;
@SuppressWarnings("serial")
public class Emp implements Comparable, Comparator , Serializable {
private int empId;
private String name;
private int age;
/**
* Compare a given Employee with this object.
* If employee id of this object is
* greater than the received object,
* then this object is greater than the other.
*/
@Override
public int compareTo(Emp arg0) {
if (!(arg0 instanceof Emp))
throw new ClassCastException("A Person object expected.");
return this.getName().compareTo(arg0.getName()) ;
}
public Emp(int empId, String name, int age) {
this.empId = empId;
this.name = name;
this.age = age;
}
public int getEmpId() {
return empId;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public int compare(Emp arg0, Emp arg1) {
return arg0.compareTo(arg1);
}
}
---------------------------------------------------
package com;
import java.util.ArrayList;
import java.util.List;
public class Util {
public static List getEmployees() {
List col = new ArrayList();
col.add(new Emp(5, "Frank", 28));
col.add(new Emp(1, "Jorge", 19));
col.add(new Emp(6, "Bill", 34));
col.add(new Emp(3, "Michel", 10));
col.add(new Emp(7, "Simpson", 8));
col.add(new Emp(4, "Clerk",16 ));
col.add(new Emp(8, "Lee", 40));
col.add(new Emp(2, "Mark", 30));
return col;
}
}
------------------------------------------
package com;
import java.util.Collections;
import java.util.List;
public class TestEmployeeSort {
/**
* @param args
*/
@SuppressWarnings("unchecked")
public static void main(String[] args) {
List coll = Util.getEmployees();
//Collections.sort(coll);
//use Comparator implementation
Collections.sort(coll);
// Arrays.sort(coll , Emp.nameComparator);
printList(coll);
}
private static void printList(List list) {
System.out.println("EmpId\tName\tAge");
for (Emp e: list) {
System.out.println(e.getEmpId() + "\t" + e.getName() + "\t" + e.getAge());
}
}
}
--------------------------------------
import java.io.Serializable;
import java.util.Comparator;
@SuppressWarnings("serial")
public class Emp implements Comparable
private int empId;
private String name;
private int age;
/**
* Compare a given Employee with this object.
* If employee id of this object is
* greater than the received object,
* then this object is greater than the other.
*/
@Override
public int compareTo(Emp arg0) {
if (!(arg0 instanceof Emp))
throw new ClassCastException("A Person object expected.");
return this.getName().compareTo(arg0.getName()) ;
}
public Emp(int empId, String name, int age) {
this.empId = empId;
this.name = name;
this.age = age;
}
public int getEmpId() {
return empId;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public int compare(Emp arg0, Emp arg1) {
return arg0.compareTo(arg1);
}
public static Comparator> nameComparator = new Comparator >() {
public int compare(Emp emp1, Emp emp2) { String name1 = emp1.getName().toUpperCase(); String name2 = emp2.getName().toUpperCase(); //ascending order return name1.compareTo(name2); //descending order //return name2.compareTo(name1); } };
---------------------------------------------------
package com;
import java.util.ArrayList;
import java.util.List;
public class Util {
public static List
List
col.add(new Emp(5, "Frank", 28));
col.add(new Emp(1, "Jorge", 19));
col.add(new Emp(6, "Bill", 34));
col.add(new Emp(3, "Michel", 10));
col.add(new Emp(7, "Simpson", 8));
col.add(new Emp(4, "Clerk",16 ));
col.add(new Emp(8, "Lee", 40));
col.add(new Emp(2, "Mark", 30));
return col;
}
}
------------------------------------------
package com;
import java.util.Collections;
import java.util.List;
public class TestEmployeeSort {
/**
* @param args
*/
@SuppressWarnings("unchecked")
public static void main(String[] args) {
List coll = Util.getEmployees();
//Collections.sort(coll);
//use Comparator implementation
Collections.sort(coll);
}
private static void printList(List
System.out.println("EmpId\tName\tAge");
for (Emp e: list) {
System.out.println(e.getEmpId() + "\t" + e.getName() + "\t" + e.getAge());
}
}
}
--------------------------------------
Shallow Copy and Deep CopyTest in Cloning
/*
Java provides a mechanism for creating copies of objects called cloning. There are two ways to make a copy of an object called shallow copy and deep copy.
Shallow copy is a bit-wise copy of an object. A new object is created that has an exact copy of the values in the original object. If any of the fields of the object are references to other objects, just the references are copied. Thus, if the object you are copying contains references to yet other objects, a shallow copy refers to the same subobjects.
Deep copy is a complete duplicate copy of an object. If an object has references to other objects, complete new copies of those objects are also made. A deep copy generates a copy not only of the primitive values of the original object, but copies of all subobjects as well, all the way to the bottom. If you need a true, complete copy of the original object, then you will need to implement a full deep copy for the object.
Java supports shallow and deep copy with the Cloneable interface to create copies of objects. To make a clone of a Java object, you declare that an object implements Cloneable, and then provide an override of the clone method of the standard Java Object base class. Implementing Cloneable tells the java compiler that your object is Cloneable. The cloning is actually done by the clone method.*/
package com.shallow;
class Person implements Cloneable {
//Lower-level object
private Car car;
private String name;
public Car getCar() {
return car;
}
public String getName() {
return name;
}
public void setName(String s) {
name = s;
}
public Person(String s, String t) {
name = s;
car = new Car(t);
}
public Object clone() {
//shallow copy
try {
return super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
}
class Car {
private String name;
public String getName() {
return name;
}
public void setName(String s) {
name = s;
}
public Car(String s) {
name = s;
}
}
public class ShallowCopyTest {
/**
* @param args
*/
public static void main(String[] args) {
//Original Object
Person p = new Person("Person-A", "Civic");
System.out.println("Original (orginal values): " + p.getName() + " - "
+ p.getCar().getName());
//Clone as a shallow copy
Person q = (Person) p.clone();
System.out.println("Clone (before change): " + q.getName() + " - "
+ q.getCar().getName());
//change the primitive member
q.setName("Person-B");
//change the lower-level object
q.getCar().setName("Accord");
System.out.println("Clone (after change): " + q.getName() + " - "
+ q.getCar().getName());
System.out.println("Original (after clone is modified): " + p.getName()
+ " - " + p.getCar().getName());
}
}
--------------------------------------------------
package com.deep;
class Person implements Cloneable {
//Lower-level object
private Car car;
private String name;
public Car getCar() {
return car;
}
public String getName() {
return name;
}
public void setName(String s) {
name = s;
}
public Person(String s, String t) {
name = s;
car = new Car(t);
}
public Object clone() {
/*//Deep copy
Person p = new Person(name, car.getName());
return p;*/
try {
Person copy = (Person)super.clone();
copy.car = (Car)car.clone();
return copy;
} catch (CloneNotSupportedException e) {
throw new Error("This should not occur since we implement Cloneable");
}
}
}
class Car implements Cloneable{
private String name;
public String getName() {
return name;
}
public void setName(String s) {
name = s;
}
public Car(String s) {
name = s;
}
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
}
public class DeepCopyTest {
public static void main(String[] args) {
//Original Object
Person p = new Person("Person-A", "Civic");
System.out.println("Original (orginal values): " + p.getName() + " - "
+ p.getCar().getName());
//Clone as a shallow copy
Person q = (Person) p.clone();
System.out.println("Clone (before change): " + q.getName() + " - "
+ q.getCar().getName());
//change the primitive member
q.setName("Person-B");
//change the lower-level object
q.getCar().setName("Accord");
System.out.println("Clone (after change): " + q.getName() + " - "
+ q.getCar().getName());
System.out.println("Original (after clone is modified): " + p.getName()
+ " - " + p.getCar().getName());
}
}
---------------------------------
//from web site
Shallow Copy Test
class Person implements Cloneable {
//Lower-level object
private Car car;
private String name;
public Car getCar() {
return car;
}
public String getName() {
return name;
}
public void setName(String s) {
name = s;
}
public Person(String s, String t) {
name = s;
car = new Car(t);
}
public Object clone() {
//shallow copy
try {
return super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
}
class Car {
private String name;
public String getName() {
return name;
}
public void setName(String s) {
name = s;
}
public Car(String s) {
name = s;
}
}
public class ShallowCopyTest {
public static void main(String[] args) {
//Original Object
Person p = new Person("Person-A", "Civic");
System.out.println("Original (orginal values): " + p.getName() + " - "
+ p.getCar().getName());
//Clone as a shallow copy
Person q = (Person) p.clone();
System.out.println("Clone (before change): " + q.getName() + " - "
+ q.getCar().getName());
//change the primitive member
q.setName("Person-B");
//change the lower-level object
q.getCar().setName("Accord");
System.out.println("Clone (after change): " + q.getName() + " - "
+ q.getCar().getName());
System.out.println("Original (after clone is modified): " + p.getName()
+ " - " + p.getCar().getName());
}
}
//
in shallow copy , the obj having ref var of any other class, then if u try to change the value of that ref var value in cloned obj of original obj, we can find changed value in ref var.but other instance var values will remain same.
it means , in shallow cpoy,
change in clone obj may effect the ref variable which r there in the original obj.
out put
--------
Original (orginal values): Person-A - Civic
Clone (before change): Person-A - Civic
Clone (after change): Person-B - Accord
Original (after clone is modified): Person-A - Accord
//----------------------------------------------------------------
Deep Copy Test
/*
Correct Output:
Original (orginal values): Person-A - Civic
Clone (before change): Person-A - Civic
Clone (after change): Person-B - Accord
Original (after clone is modified): Person-A - Civic
*/
/*
Software Architecture Design Patterns in Java
by Partha Kuchana
Auerbach Publications
*/
class Person implements Cloneable {
//Lower-level object
private Car car;
private String name;
public Car getCar() {
return car;
}
public String getName() {
return name;
}
public void setName(String s) {
name = s;
}
public Person(String s, String t) {
name = s;
car = new Car(t);
}
public Object clone() {
//Deep copy
Person p = new Person(name, car.getName());
return p;
}
}
class Car {
private String name;
public String getName() {
return name;
}
public void setName(String s) {
name = s;
}
public Car(String s) {
name = s;
}
}
public class DeepCopyTest {
public static void main(String[] args) {
//Original Object
Person p = new Person("Person-A", "Civic");
System.out.println("Original (orginal values): " + p.getName() + " - "
+ p.getCar().getName());
//Clone as a shallow copy
Person q = (Person) p.clone();
System.out.println("Clone (before change): " + q.getName() + " - "
+ q.getCar().getName());
//change the primitive member
q.setName("Person-B");
//change the lower-level object
q.getCar().setName("Accord");
System.out.println("Clone (after change): " + q.getName() + " - "
+ q.getCar().getName());
System.out.println("Original (after clone is modified): " + p.getName()
+ " - " + p.getCar().getName());
}
}
Java provides a mechanism for creating copies of objects called cloning. There are two ways to make a copy of an object called shallow copy and deep copy.
Shallow copy is a bit-wise copy of an object. A new object is created that has an exact copy of the values in the original object. If any of the fields of the object are references to other objects, just the references are copied. Thus, if the object you are copying contains references to yet other objects, a shallow copy refers to the same subobjects.
Deep copy is a complete duplicate copy of an object. If an object has references to other objects, complete new copies of those objects are also made. A deep copy generates a copy not only of the primitive values of the original object, but copies of all subobjects as well, all the way to the bottom. If you need a true, complete copy of the original object, then you will need to implement a full deep copy for the object.
Java supports shallow and deep copy with the Cloneable interface to create copies of objects. To make a clone of a Java object, you declare that an object implements Cloneable, and then provide an override of the clone method of the standard Java Object base class. Implementing Cloneable tells the java compiler that your object is Cloneable. The cloning is actually done by the clone method.*/
package com.shallow;
class Person implements Cloneable {
//Lower-level object
private Car car;
private String name;
public Car getCar() {
return car;
}
public String getName() {
return name;
}
public void setName(String s) {
name = s;
}
public Person(String s, String t) {
name = s;
car = new Car(t);
}
public Object clone() {
//shallow copy
try {
return super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
}
class Car {
private String name;
public String getName() {
return name;
}
public void setName(String s) {
name = s;
}
public Car(String s) {
name = s;
}
}
public class ShallowCopyTest {
/**
* @param args
*/
public static void main(String[] args) {
//Original Object
Person p = new Person("Person-A", "Civic");
System.out.println("Original (orginal values): " + p.getName() + " - "
+ p.getCar().getName());
//Clone as a shallow copy
Person q = (Person) p.clone();
System.out.println("Clone (before change): " + q.getName() + " - "
+ q.getCar().getName());
//change the primitive member
q.setName("Person-B");
//change the lower-level object
q.getCar().setName("Accord");
System.out.println("Clone (after change): " + q.getName() + " - "
+ q.getCar().getName());
System.out.println("Original (after clone is modified): " + p.getName()
+ " - " + p.getCar().getName());
}
}
--------------------------------------------------
package com.deep;
class Person implements Cloneable {
//Lower-level object
private Car car;
private String name;
public Car getCar() {
return car;
}
public String getName() {
return name;
}
public void setName(String s) {
name = s;
}
public Person(String s, String t) {
name = s;
car = new Car(t);
}
public Object clone() {
/*//Deep copy
Person p = new Person(name, car.getName());
return p;*/
try {
Person copy = (Person)super.clone();
copy.car = (Car)car.clone();
return copy;
} catch (CloneNotSupportedException e) {
throw new Error("This should not occur since we implement Cloneable");
}
}
}
class Car implements Cloneable{
private String name;
public String getName() {
return name;
}
public void setName(String s) {
name = s;
}
public Car(String s) {
name = s;
}
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
}
public class DeepCopyTest {
public static void main(String[] args) {
//Original Object
Person p = new Person("Person-A", "Civic");
System.out.println("Original (orginal values): " + p.getName() + " - "
+ p.getCar().getName());
//Clone as a shallow copy
Person q = (Person) p.clone();
System.out.println("Clone (before change): " + q.getName() + " - "
+ q.getCar().getName());
//change the primitive member
q.setName("Person-B");
//change the lower-level object
q.getCar().setName("Accord");
System.out.println("Clone (after change): " + q.getName() + " - "
+ q.getCar().getName());
System.out.println("Original (after clone is modified): " + p.getName()
+ " - " + p.getCar().getName());
}
}
---------------------------------
//from web site
Shallow Copy Test
class Person implements Cloneable {
//Lower-level object
private Car car;
private String name;
public Car getCar() {
return car;
}
public String getName() {
return name;
}
public void setName(String s) {
name = s;
}
public Person(String s, String t) {
name = s;
car = new Car(t);
}
public Object clone() {
//shallow copy
try {
return super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
}
class Car {
private String name;
public String getName() {
return name;
}
public void setName(String s) {
name = s;
}
public Car(String s) {
name = s;
}
}
public class ShallowCopyTest {
public static void main(String[] args) {
//Original Object
Person p = new Person("Person-A", "Civic");
System.out.println("Original (orginal values): " + p.getName() + " - "
+ p.getCar().getName());
//Clone as a shallow copy
Person q = (Person) p.clone();
System.out.println("Clone (before change): " + q.getName() + " - "
+ q.getCar().getName());
//change the primitive member
q.setName("Person-B");
//change the lower-level object
q.getCar().setName("Accord");
System.out.println("Clone (after change): " + q.getName() + " - "
+ q.getCar().getName());
System.out.println("Original (after clone is modified): " + p.getName()
+ " - " + p.getCar().getName());
}
}
//
in shallow copy , the obj having ref var of any other class, then if u try to change the value of that ref var value in cloned obj of original obj, we can find changed value in ref var.but other instance var values will remain same.
it means , in shallow cpoy,
change in clone obj may effect the ref variable which r there in the original obj.
out put
--------
Original (orginal values): Person-A - Civic
Clone (before change): Person-A - Civic
Clone (after change): Person-B - Accord
Original (after clone is modified): Person-A - Accord
//----------------------------------------------------------------
Deep Copy Test
/*
Correct Output:
Original (orginal values): Person-A - Civic
Clone (before change): Person-A - Civic
Clone (after change): Person-B - Accord
Original (after clone is modified): Person-A - Civic
*/
/*
Software Architecture Design Patterns in Java
by Partha Kuchana
Auerbach Publications
*/
class Person implements Cloneable {
//Lower-level object
private Car car;
private String name;
public Car getCar() {
return car;
}
public String getName() {
return name;
}
public void setName(String s) {
name = s;
}
public Person(String s, String t) {
name = s;
car = new Car(t);
}
public Object clone() {
//Deep copy
Person p = new Person(name, car.getName());
return p;
}
}
class Car {
private String name;
public String getName() {
return name;
}
public void setName(String s) {
name = s;
}
public Car(String s) {
name = s;
}
}
public class DeepCopyTest {
public static void main(String[] args) {
//Original Object
Person p = new Person("Person-A", "Civic");
System.out.println("Original (orginal values): " + p.getName() + " - "
+ p.getCar().getName());
//Clone as a shallow copy
Person q = (Person) p.clone();
System.out.println("Clone (before change): " + q.getName() + " - "
+ q.getCar().getName());
//change the primitive member
q.setName("Person-B");
//change the lower-level object
q.getCar().setName("Accord");
System.out.println("Clone (after change): " + q.getName() + " - "
+ q.getCar().getName());
System.out.println("Original (after clone is modified): " + p.getName()
+ " - " + p.getCar().getName());
}
}
Sunday, July 18, 2010
Performance Tuning of Java Applications
Ever since the first version of Java Technology hit the streets, performance has been an important issue for Java developers. Java has improved dramatically and continually but, performance tuning is very essential to get the best results, especially when we think of J2EE applications.
Sponsored Links
Introduction:
Java Performance Tuning (abbreviated as JPT), 2nd edition provides a comprehensive guide to eliminate all the types of performance problems. By considering real-life examples JPT shows how to get rid off all the types of performances problems. For example JPT shows tricks such as how to minimize object creation and replacing strings with arrays can really pay off in improving code performance.
Few of important fundamentals and guidelines included in Java Performance Tuning are….
* Tuning tips for object creation.
* Tuning in JDBC.
* Web services performance tips.
* Tuning in EJB.
* Tuning in J2EE.
* Tuning in JMS.
* Tuning in RMI.
Guidelines for tuning java code without destroying program’s skeleton is efficiently presented in second edition of Java Performance Tuning. It includes how to use threads effectively, how to optimize the use of strings, minimizing the creation of objects in program, avoiding bottleneck operation by including all the important fundamentals of Software Engineering to re-pioneer the code, issues of speed of Servlets and JSPs etc. That provides very crucial guidelines in performance tuning for java developers.
Tuning Tips for Object Creation:
Object Creation is one of the most basic and essential thing while developing a Java Application, as such; object defines the physical reality of class. Pay proper attention while declaring class’ methods and variables because careless work carried out at this stage, can cost you in terms of speed and performance because variables and methods unwontedly declared and initialize can create overhead in overall speed. Object should always be created early when there is spare time in the application, object once created should be in hold position until it is required. Care should be taken while defining methods that can accept the reusable objects to be filled with the data rather than methods that return objects holding that data, immutable objects can also be used here. Object should be created only when class logically needs. Constructor of class should always be simple. Methods that alter objects directly should always be preferred. Use classes that handle primitive data types rather than wrapping the primitive data types.
Performance Tuning in JDBC:
Java Database Connectivity (JDBC) is mainly used in most of the Java application. To keep trace on performance tuning in JDBC becomes very crucial and prime issue when Java developer realizes that most of the processing time should not be wasted behind data processing over the network.
Here are few of the tuning tips for JDBC that can improve the over all performance in Java application.
* SQL statements should be tuned to minimize the data that is return from the database.
* Use of prepared statements and parameterized SQL statements can speed up the over all process in data processing.
* Transaction conflicts should always be avoided.
* Usage of stored procedures, connection pooling, selection of fastest JDBC driver should be encouraged.
* Any of the open resources that is not in use in Java application can keep processor engaged unwontedly, any of the resource that is open and not required to perform any of database activity should be closed like Connections, Statements, ResultSet etc.
Web Services performance tips:
Because of Java’s outstanding performance in web services there are few of the performance tips that are to be considered while developing a web service application. Here are few of the tips given for improving the web services performance.
* Avoid using XML messaging, this helps to achieve fine-grained RPC.
* Frequency of the messaging should be taken into consideration with the replication of the data as necessary.
* Always try to retrieve data during off-hours this helps in course gained transactions.
* Overall system performance should never be neglected and optimized until we know where the bottlenecks are present.
* Asynchronous messaging model should always be taken into account when transport is slow or / and unreliable, or when processing is complex and long running.
Tips for Quality of services for Web Services
* The main requirements in quality of service for web services are:
o Availability and accessibility.
o Integrity and reliability. This ensures that weather program will crash or not while it is running, if so, how often can it crash.
o Number of simultaneous request that can be made to application by the user i.e. “throughput” and what will be the response time to process this request by application i.e. “latency”.
o Security issues.
* HTTP is a best-effort delivery service as far as web services issue is concerned. The main reason behind this is that request could simply be dropped. Messaging in web services should always be Asynchronous because Asynchronous messaging can improve throughput no matter at the cost of latency.
* DOM based parsers are slower than SAX based ones.
* Requests results should be cached whenever it is possible.
* Extreme care should be taken to make sure that resources are not locked for long periods of time to avoid serious scalability problems.
* Other factor that affects web service performance are:
o Response time of web server.
o Availability of web server.
o Execution time of web application.
o Backend database.
Scaling web services Tips
Use of faster communication protocol, like plain socket, should always be preferred. Whenever there is requirement of sending large number of documents over the network, basic load-balancing scheme should be achieved, all the documents to be sent should have different URL hosts i.e. binding addresses. For scalability of server better and speedy hardware should be preferred though there is limitation of scalability of server is that most application performance does not scale linearly with increases in the hardware power. Most of the times in web related services cluster of more than one server is used.
Performance Tuning tips for EJB:
While developing an EJB application if EJB services for an object is not required than plain Java object should be replaced in place of EJB object. Multiple remote method calls should be changed into one remote method call with all the data combined into a parameter object to enhance the overall process. There should be proper tuning in EJB Server thread count; Use Stateless session beans pool size to minimize the creation and destruction of the beans. When multiple EJB remote calls have to be changed into one session bean remote call and several local calls(SessionFacade), wrap multiple entity beans in a session bean. Transactional time-out should be set previously. Use HttpSession object rather than Stateful session bean to maintain client state. Bulk updating should be used to reduce the overall database calls to fetch and retrieving the data. When dealing with large amounts of data such as searching large database JDBC should be directly used rather than using entity beans.
J2EE Performance tuning tips:
Here few of the important tuning tips for J2EE in points.
* Entity beans from session beans should always be accessed.
* When you no longer need to use session call HttpSession.invalidate() to clean up a session.
* Save resources by turning off automatic session creation using < % @page session=”false” % > for web pages that don’t require session tracking.
* Use compile time directive < % @include file=”copyleft.html” % > where possible.
* Whenever beans are co-located in the same JVM, use local entity beans.
* Proprietary stubs can be used for caching and batching data.
* To generate unique primary keys dedicated remote object should be used.
* Whenever possible use cache tagging.
* User JDBC directly instead of using an entity bean only for data access.
Tuning tips for JMS:
For developing an efficient JMS application transient variables should be used to reduce serialization overheads. For receiving messages asynchronously implement MessageListener. To avoid persistency overhead choose non-durable (NON_PERSISTENT) messages wherever appropriate. It is practically efficient to use DUPS_OK_ACKNOWLEDGE AND AUTO_ACKNOWLEDGE than CLIENT_ACKNOWLEDGE as far as issue of performance is concerned. Separate transactional sessions and non-transactional sessions for transactional and non-transactional messages should be used separately. Because of the fact that “ a higher redelivery delay and lower redelivery limit reduces the overhead” remember to tune the destination parameters. Open java resources can claim for more system resources never forget to close all the resources whenever they are not in use. The last point to be kept while developing a JMS application is that consumer should always start before we start the producer so that the initial messages do not need to be queued up.
Sponsored Links
RMI tuning performance tips:
To improve the performance in RMI application always consider altering the Tcp WindowSize parameter. To measure the bandwidth of network netp erf should be used. By setting the properties sun.rmi.dgc.client.gcInterval and sun.rmi.dgc.server.gcInterval RMI garbage collection should be configured in a proper manner. Since sending the object over network may consume much of the time in a big application sending groups of objects together rather than one object at a time is advisable. To speed up the transfers, implement Externalize interface. To handle special cases such as singleton or reusable objects use special codes. To improve overall development quality never try to add the extra complications once the performance target have been met
.
Sponsored Links
Introduction:
Java Performance Tuning (abbreviated as JPT), 2nd edition provides a comprehensive guide to eliminate all the types of performance problems. By considering real-life examples JPT shows how to get rid off all the types of performances problems. For example JPT shows tricks such as how to minimize object creation and replacing strings with arrays can really pay off in improving code performance.
Few of important fundamentals and guidelines included in Java Performance Tuning are….
* Tuning tips for object creation.
* Tuning in JDBC.
* Web services performance tips.
* Tuning in EJB.
* Tuning in J2EE.
* Tuning in JMS.
* Tuning in RMI.
Guidelines for tuning java code without destroying program’s skeleton is efficiently presented in second edition of Java Performance Tuning. It includes how to use threads effectively, how to optimize the use of strings, minimizing the creation of objects in program, avoiding bottleneck operation by including all the important fundamentals of Software Engineering to re-pioneer the code, issues of speed of Servlets and JSPs etc. That provides very crucial guidelines in performance tuning for java developers.
Tuning Tips for Object Creation:
Object Creation is one of the most basic and essential thing while developing a Java Application, as such; object defines the physical reality of class. Pay proper attention while declaring class’ methods and variables because careless work carried out at this stage, can cost you in terms of speed and performance because variables and methods unwontedly declared and initialize can create overhead in overall speed. Object should always be created early when there is spare time in the application, object once created should be in hold position until it is required. Care should be taken while defining methods that can accept the reusable objects to be filled with the data rather than methods that return objects holding that data, immutable objects can also be used here. Object should be created only when class logically needs. Constructor of class should always be simple. Methods that alter objects directly should always be preferred. Use classes that handle primitive data types rather than wrapping the primitive data types.
Performance Tuning in JDBC:
Java Database Connectivity (JDBC) is mainly used in most of the Java application. To keep trace on performance tuning in JDBC becomes very crucial and prime issue when Java developer realizes that most of the processing time should not be wasted behind data processing over the network.
Here are few of the tuning tips for JDBC that can improve the over all performance in Java application.
* SQL statements should be tuned to minimize the data that is return from the database.
* Use of prepared statements and parameterized SQL statements can speed up the over all process in data processing.
* Transaction conflicts should always be avoided.
* Usage of stored procedures, connection pooling, selection of fastest JDBC driver should be encouraged.
* Any of the open resources that is not in use in Java application can keep processor engaged unwontedly, any of the resource that is open and not required to perform any of database activity should be closed like Connections, Statements, ResultSet etc.
Web Services performance tips:
Because of Java’s outstanding performance in web services there are few of the performance tips that are to be considered while developing a web service application. Here are few of the tips given for improving the web services performance.
* Avoid using XML messaging, this helps to achieve fine-grained RPC.
* Frequency of the messaging should be taken into consideration with the replication of the data as necessary.
* Always try to retrieve data during off-hours this helps in course gained transactions.
* Overall system performance should never be neglected and optimized until we know where the bottlenecks are present.
* Asynchronous messaging model should always be taken into account when transport is slow or / and unreliable, or when processing is complex and long running.
Tips for Quality of services for Web Services
* The main requirements in quality of service for web services are:
o Availability and accessibility.
o Integrity and reliability. This ensures that weather program will crash or not while it is running, if so, how often can it crash.
o Number of simultaneous request that can be made to application by the user i.e. “throughput” and what will be the response time to process this request by application i.e. “latency”.
o Security issues.
* HTTP is a best-effort delivery service as far as web services issue is concerned. The main reason behind this is that request could simply be dropped. Messaging in web services should always be Asynchronous because Asynchronous messaging can improve throughput no matter at the cost of latency.
* DOM based parsers are slower than SAX based ones.
* Requests results should be cached whenever it is possible.
* Extreme care should be taken to make sure that resources are not locked for long periods of time to avoid serious scalability problems.
* Other factor that affects web service performance are:
o Response time of web server.
o Availability of web server.
o Execution time of web application.
o Backend database.
Scaling web services Tips
Use of faster communication protocol, like plain socket, should always be preferred. Whenever there is requirement of sending large number of documents over the network, basic load-balancing scheme should be achieved, all the documents to be sent should have different URL hosts i.e. binding addresses. For scalability of server better and speedy hardware should be preferred though there is limitation of scalability of server is that most application performance does not scale linearly with increases in the hardware power. Most of the times in web related services cluster of more than one server is used.
Performance Tuning tips for EJB:
While developing an EJB application if EJB services for an object is not required than plain Java object should be replaced in place of EJB object. Multiple remote method calls should be changed into one remote method call with all the data combined into a parameter object to enhance the overall process. There should be proper tuning in EJB Server thread count; Use Stateless session beans pool size to minimize the creation and destruction of the beans. When multiple EJB remote calls have to be changed into one session bean remote call and several local calls(SessionFacade), wrap multiple entity beans in a session bean. Transactional time-out should be set previously. Use HttpSession object rather than Stateful session bean to maintain client state. Bulk updating should be used to reduce the overall database calls to fetch and retrieving the data. When dealing with large amounts of data such as searching large database JDBC should be directly used rather than using entity beans.
J2EE Performance tuning tips:
Here few of the important tuning tips for J2EE in points.
* Entity beans from session beans should always be accessed.
* When you no longer need to use session call HttpSession.invalidate() to clean up a session.
* Save resources by turning off automatic session creation using < % @page session=”false” % > for web pages that don’t require session tracking.
* Use compile time directive < % @include file=”copyleft.html” % > where possible.
* Whenever beans are co-located in the same JVM, use local entity beans.
* Proprietary stubs can be used for caching and batching data.
* To generate unique primary keys dedicated remote object should be used.
* Whenever possible use cache tagging.
* User JDBC directly instead of using an entity bean only for data access.
Tuning tips for JMS:
For developing an efficient JMS application transient variables should be used to reduce serialization overheads. For receiving messages asynchronously implement MessageListener. To avoid persistency overhead choose non-durable (NON_PERSISTENT) messages wherever appropriate. It is practically efficient to use DUPS_OK_ACKNOWLEDGE AND AUTO_ACKNOWLEDGE than CLIENT_ACKNOWLEDGE as far as issue of performance is concerned. Separate transactional sessions and non-transactional sessions for transactional and non-transactional messages should be used separately. Because of the fact that “ a higher redelivery delay and lower redelivery limit reduces the overhead” remember to tune the destination parameters. Open java resources can claim for more system resources never forget to close all the resources whenever they are not in use. The last point to be kept while developing a JMS application is that consumer should always start before we start the producer so that the initial messages do not need to be queued up.
Sponsored Links
RMI tuning performance tips:
To improve the performance in RMI application always consider altering the Tcp WindowSize parameter. To measure the bandwidth of network netp erf should be used. By setting the properties sun.rmi.dgc.client.gcInterval and sun.rmi.dgc.server.gcInterval RMI garbage collection should be configured in a proper manner. Since sending the object over network may consume much of the time in a big application sending groups of objects together rather than one object at a time is advisable. To speed up the transfers, implement Externalize interface. To handle special cases such as singleton or reusable objects use special codes. To improve overall development quality never try to add the extra complications once the performance target have been met
.
==, .equals(), compareTo(), and compare()
Equality comparison: One way for primitives, Four ways for objects
Comparison Primitives Objects
a == b, a != b Equal values Compares references, not values. The use of == with object references is generally limited to the following:
* Comparing to see if a reference is null.
* Comparing two enum values. This works because there is only one object for each enum constant.
* You want to know if two references are to the same object
a.equals(b) N/A Compares values for equality. Because this method is defined in the Object class, from which all other classes are derived, it's automatically defined for every class. However, it doesn't perform an intelligent comparison for most classes unless the class overrides it. It has been defined in a meaningful way for most Java core classes. If it's not defined for a (user) class, it behaves the same as ==.
It turns out that defining equals() isn't trivial; in fact it's moderately hard to get it right, especially in the case of subclasses. The best treatment of the issues is in Horstmann's Core Java Vol 1. [TODO: Add explanation and example]
a.compareTo(b) N/A Comparable interface. Compares values and returns an int which tells if the values compare less than, equal, or greater than. If your class objects have a natural order, implement the Comparable interface and define this method. All Java classes that have a natural ordering implement this (String, Double, BigInteger, ...).
compare(a, b) N/A Comparator interface. Compares values of two objects. This is implemented as part of the Comparator interface, and the typical use is to define one or more small utility classes that implement this, to pass to methods such as sort() or for use by sorting data structures such as TreeMap and TreeSet. You might want to create a Comparator object for the following.
* Multiple comparisions. To provide several different ways to sort somthing. For example, you might want to sort a Person class by name, ID, age, height, ... You would define a Comparator for each of these to pass to the sort() method.
* System class. To provide comparison methods for classes that you have no control over. For example, you could define a Comparator for Strings that compared them by length.
* Strategy pattern. To implement a Strategey pattern, which is a situation where you want to represent an algorithm as an object that you can pass as a parameter, save in a data structure, etc.
If your class objects have one natural sorting order, you may not need this.
Comparing Object references with the == and != Operators
The two operators that can be used with object references are comparing for equality (==) and inequality (!=). These operators compare two values to see if they refer to the same object. Although this comparison is very fast, it is often not what you want.
Usually you want to know if the objects have the same value, and not whether two objects are a reference to the same object. For example,
if (name == "Mickey Mouse") // Legal, but ALMOST SURELY WRONG
This is true only if name is a reference to the same object that "Mickey Mouse" refers to. This will be false if the String in name was read from input or computed (by putting strings together or taking the substring), even though name really does have exactly those characters in it.
Many classes (eg, String) define the equals() method to compare the values of objects.
Comparing Object values with the equals() Method
Use the equals() method to compare object values. The equals() method returns a boolean value. The previous example can be fixed by writing:
if (name.equals("Mickey Mouse")) // Compares values, not refererences.
Because the equals() method makes a == test first, it can be fairly fast when the objects are identical. It only compares the values if the two references are not identical.
Other comparisons - Comparable interface
The equals method and == and != operators test for equality/inequality, but do not provide a way to test for relative values. Some classes (eg, String and other classes with a natural ordering) implement the Comparable interface, which defines a compareTo method. You will want to implement Comparable in your class if you want to use it with Collections.sort() or Arrays.sort() methods.
Defining a Comparator object
As described in the table above on compare(), you can create Comparators to sort any arbitrary way for any class. For example, the String class defines the CASE_INSENSITIVE_ORDER comparator.
If you override equals, you should also override hashCode()
Overriding hashCode(). The hashCode() method of a class is used for hashing in library data structures such as HashSet and HashMap. If you override equals(), you should override hashCode() or your class will not work correctly in these (and some other) data structures.
Shouldn't .equals and .compareTo produce same result?
The general advice is that if a.equals(b) is true, then a.compareTo(b) == 0 should also be true. Curiously, BigDecimal violates this. Look at the Java API documentation for an explanation of the difference. This seems wrong, although their implementation has some plausibiliby.
Other comparison methods
String has the specialized equalsIgnoreCase() and compareToIgnoreCase(). String also supplies the constant String.CASE_INSENSITIVE_ORDER Comparator.
The === operator (Doesn't exist - yet?)
Comparing objects is somewhat awkward, so a === operator has been proposed. One proposal is that
a === b would be the same as ((a == b) || ((a != null) && a.equals(b)))
Common Errors
Using == instead of equals() with Objects
When you want to compare objects, you need to know whether you should use == to see if they are the same object, or equals() to see if they may be a different object, but have the same value. This kind of error can be very hard to find.
Comparison Primitives Objects
a == b, a != b Equal values Compares references, not values. The use of == with object references is generally limited to the following:
* Comparing to see if a reference is null.
* Comparing two enum values. This works because there is only one object for each enum constant.
* You want to know if two references are to the same object
a.equals(b) N/A Compares values for equality. Because this method is defined in the Object class, from which all other classes are derived, it's automatically defined for every class. However, it doesn't perform an intelligent comparison for most classes unless the class overrides it. It has been defined in a meaningful way for most Java core classes. If it's not defined for a (user) class, it behaves the same as ==.
It turns out that defining equals() isn't trivial; in fact it's moderately hard to get it right, especially in the case of subclasses. The best treatment of the issues is in Horstmann's Core Java Vol 1. [TODO: Add explanation and example]
a.compareTo(b) N/A Comparable interface. Compares values and returns an int which tells if the values compare less than, equal, or greater than. If your class objects have a natural order, implement the Comparable
compare(a, b) N/A Comparator interface. Compares values of two objects. This is implemented as part of the Comparator
* Multiple comparisions. To provide several different ways to sort somthing. For example, you might want to sort a Person class by name, ID, age, height, ... You would define a Comparator for each of these to pass to the sort() method.
* System class. To provide comparison methods for classes that you have no control over. For example, you could define a Comparator for Strings that compared them by length.
* Strategy pattern. To implement a Strategey pattern, which is a situation where you want to represent an algorithm as an object that you can pass as a parameter, save in a data structure, etc.
If your class objects have one natural sorting order, you may not need this.
Comparing Object references with the == and != Operators
The two operators that can be used with object references are comparing for equality (==) and inequality (!=). These operators compare two values to see if they refer to the same object. Although this comparison is very fast, it is often not what you want.
Usually you want to know if the objects have the same value, and not whether two objects are a reference to the same object. For example,
if (name == "Mickey Mouse") // Legal, but ALMOST SURELY WRONG
This is true only if name is a reference to the same object that "Mickey Mouse" refers to. This will be false if the String in name was read from input or computed (by putting strings together or taking the substring), even though name really does have exactly those characters in it.
Many classes (eg, String) define the equals() method to compare the values of objects.
Comparing Object values with the equals() Method
Use the equals() method to compare object values. The equals() method returns a boolean value. The previous example can be fixed by writing:
if (name.equals("Mickey Mouse")) // Compares values, not refererences.
Because the equals() method makes a == test first, it can be fairly fast when the objects are identical. It only compares the values if the two references are not identical.
Other comparisons - Comparable
The equals method and == and != operators test for equality/inequality, but do not provide a way to test for relative values. Some classes (eg, String and other classes with a natural ordering) implement the Comparable
Defining a Comparator object
As described in the table above on compare(), you can create Comparators to sort any arbitrary way for any class. For example, the String class defines the CASE_INSENSITIVE_ORDER comparator.
If you override equals, you should also override hashCode()
Overriding hashCode(). The hashCode() method of a class is used for hashing in library data structures such as HashSet and HashMap. If you override equals(), you should override hashCode() or your class will not work correctly in these (and some other) data structures.
Shouldn't .equals and .compareTo produce same result?
The general advice is that if a.equals(b) is true, then a.compareTo(b) == 0 should also be true. Curiously, BigDecimal violates this. Look at the Java API documentation for an explanation of the difference. This seems wrong, although their implementation has some plausibiliby.
Other comparison methods
String has the specialized equalsIgnoreCase() and compareToIgnoreCase(). String also supplies the constant String.CASE_INSENSITIVE_ORDER Comparator.
The === operator (Doesn't exist - yet?)
Comparing objects is somewhat awkward, so a === operator has been proposed. One proposal is that
a === b would be the same as ((a == b) || ((a != null) && a.equals(b)))
Common Errors
Using == instead of equals() with Objects
When you want to compare objects, you need to know whether you should use == to see if they are the same object, or equals() to see if they may be a different object, but have the same value. This kind of error can be very hard to find.
Tuesday, July 13, 2010
Subscribe to:
Posts (Atom)