Caution: A long post ahead!
Some of the features listed here may appear obvious to some of you. Many programmers I know who are not aware of all these features. If you have read the language specification of Java or you studied for SCJP exam, none of these would appear anything new to you. This is sad that not all of us care to read the language specification or the virtual machine specification of Java. Some of us don’t even have a clear idea on the API.
Instance Initializers
Consider the following class:
public class SomeClass {
public SomeClass () {
System.out.println("Constructor Invoked");
}
static {
System.out.println("Static Initializer Invoked");
}
{
System.out.println("Instance Initializer Invoked");
}
public static void main(String... args){
new SomeClass();
}
}
Output:
Static Initializer Invoked
Instance Initializer Invoked
Constructor Invoked
Note that static block gets executed first and it gets executed once. If you try to call SomeClass() several times, only the first call of SomeClass will execute that static block. So, if you call-
new SomeClass();
new SomeClass();
It will print-
Static Initializer Invoked
Instance Initializer Invoked
Constructor Invoked
Instance Initializer Invoked
Constructor Invoked
Static block is pretty good if in the beginning of the class, you want to load some default resources like drivers. Instance initializer is better than using an init() method since it can initialize final fields.
Anonymous Class with Initializer Block
This is also called Double-brace Initialization. It’s a fancy way of referring to this feature. This feature creates an anonymous inner class and then creates an initializer block inside it, which lets you execute methods from a static context at any time. Note that since it actually creates an anonymous subclass of the object, or in other words, you implicitly hold a reference to the outer object, it can cause some unexpected memory leaks. This example is taken from the link provided. Take a look.
To pass a set to a method:
Set validCodes = new HashSet();
validCodes.add("XZ13s");
validCodes.add("AB21/X");
validCodes.add("YYLEX");
validCodes.add("AR2D");
removeProductsWithCodeIn(validCodes);
Or, to initialize a set of constants:
private static final Set VALID_CODES = new HashSet();
static {
validCodes.add("XZ13s");
validCodes.add("AB21/X");
validCodes.add("YYLEX");
validCodes.add("AR2D");
}
You can create and initialize a new collection as an expression by using the “double-brace” syntax:
private static final Set VALID_CODES = new HashSet() {{
add("XZ13s");
add("AB21/X");
add("YYLEX");
add("AR2D");
}};
Or:
removeProductsWithCodeIn(new HashSet() {{
add("XZ13s");
add("AB21/X");
add("YYLEX");
add("AR5E");
}});
Labeled Blocks
This is surprising to me that many Java developers are not aware of this feature or some think it can only only be used with a loop. Take a look at the following snippet-
private String setSomehing(final List codesInFile) {
setCodeDesc: {
if (codesInFile.contains("PA")) {
break setCodeDesc;
}
if (codesInFile.contains("CA")) {
break setCodeDesc;
}
return "No Charge";
}
return "Invalid Code";
}
Or you can use continue-
private void continueLabel(){
someLabel:
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
System.out.println(i + " " + j);
if (i == j) {
continue someLabel;
}
}
}
}
If the above method gets executed, it would print-
0 0
1 0
1 1
Note that, you can only continue or break a label from within its scope. You cannot do this-
if (i ==0) {
continue someLabel;
} else {
//do something
}
someLabel: {
//do something
}
Arrays.asList
List<Integer> someList = Arrays.asList(12, 14, 18);
It’s a good combination of generic methods and autoboxing. Note that you cannot extend the size of this list. You cannot do someList.add(22); since the size is backed by the array as it is documented in the API. If you still want to add dynamically, you can wrap it with a constructor like-
List<Integer> someList = new ArrayList<Integer>(Arrays.asList(12, 14, 18));
Concurrency Tools
Concurrency tools have been introduced since JDK 1.5 which are cleverly implemented and robust, beyond just locks. You can find those in java.util.concurrent. A specifically interesting example is the java.util.concurrent.atomic subpackage that contains thread-safe primitives that implement the compare-and-swap operation and can map to actual native hardware-supported versions of these operations. Instead of using synchronized keyword, you can use Lock.lock() and Lock.unlock(). Instead of using wait() and notify() in the critical section use await() and signal() on condition variables. Take a look at the links provided. In DelayQueue, elements are made available after a specified delay. Also java.util.concurrent.TimeUnit is useful when converting between nanoseconds, microseconds, milliseconds and seconds.
Object Validation
String someString = null;
if( someString != null && someString instanceof String){
System.out.println("true");
} else {
System.out.println("false");
}
You can change if( someString != null && someString instanceof String) to if(someString instanceof String). The method instanceof checks for null automatically. The above code will print false.
Dynamic Proxy
Dynamic Proxy classes allow you to define a new type at runtime that conforms to an interface. It is handy to use a simple Class.forName(SomeClass).newInstance() where the class type is configurable.
VisualVM
If you are using JConsole, you might try /bin/jvisualvm.exe in your java installation directory. It is a new tool added to JDK 1.6_07+.
Enumeration
Enums are so object oriented that you can add methods and constructors to it. You can even use enums to implement an interface.
Examples:
public enum Color {
WHITE(21), BLACK(22), RED(23), YELLOW(24), BLUE(25);
private int code;
private Color(int c) {
code = c;
}
public int getCode() {
return code;
}
Enum can implement any interfaces. All enum types implicitly implements java.io.Serializable, and java.lang.Comparable.
public enum Color implements Runnable {
WHITE, BLACK, RED, YELLOW, BLUE;
public void run() {
System.out.println("name()=" + name() +
", toString()=" + toString());
}
public static void main(String... args){
for(Color c : Color.values()) {
c.run();
}
}
}
..and some stuff (not features) you may want to know about
The finally Block
As I mentioned in my earlier post, you should not use return statement in a finally block-
public static void someMethod() {
try {
throw new RuntimeException();
} finally {
return;
}
}
This RunTimeException will be lost because of the return statement in finally block.
Local Classes
A local class is a nested class that is not a member of any class and that has a name.
public class ClassInsideMethod {
public String someMethod(){
class Person {
private String getPerson(){
return "John";
}
}
return new Person().getPerson();
}
public static void main(String... args){
System.out.println(new ClassInsideMethod().someMethod());
}
}
Comparator and TreeSet
Comparator can change the Set semantics-
import java.util.*;
public class ComparatorSet {
public static void main(String[] args) {
Set set = new TreeSet(new ChangeSemantics());
set.add("Apple");
set.add("Bannana");
System.out.println(set);
}
public static class ChangeSemantics implements Comparator {
public int compare(String left, String right) {
return 0;
}
}
}
This will print- [Apple] Try changing the return value to 1 or -1 and see the result if you are confused. Note that TreeSet relies on Comparator to define equality. For instance, if you add System.out.println(set.contains(“Orange”)); in the main method, it will print true since you are returning 0 in compare(). If you return 1, it will print false obviously.
Integer.getInteger
The getInteger method confuses some developers. I ask this often to applicants during interviews. What would the following statement print-
System.err.println(Integer.getInteger("500"));
And no, it’s not gonna print 500! Check the API link provided.
Tricky
And this one (Taken from Joshua Bloch’s Effective Java), what would happen when the following snippet gets executed? I even get answer like – internet explorer would get launched?
System.out.print("iexplore:");
http://www.techhangout.com;
System.out.println(":maximize");
Highlight the text below to read the explanation if you haven’t figured it out.
JVM doesn’t see that as a url. It sees the colon after http which makes it think that it’s a label block followed by a comment because of //.
The Scripting API
With the Java Scripting API, it is possible to write customizable/extendable applications in the Java language and leave the customization scripting language choice to the end user.
System.out.println(new ScriptEngineManager().getEngineByName("JavaScript").eval(" 5 + 5"));
Note that the space before 5 was intentionally placed as it behaves like JavaScript. It will print 10.0.
I wanted to include a lot more but this is really getting too long. Enjoy coding in Java!