Java 5 (new Features)
Java 5, also known as Java 1.5 or JDK 5, introduced several
significant language and library features that made Java easier to
use and more powerful. Here are some key features, along with
explanations and examples:
1. Generics
Generics allow for type-safe data structures and methods. They
let you specify the type of object that a collection (like a List) can
hold, eliminating the need for explicit casting
Without Generics
import java.util.ArrayList;
import java.util.List;
public class TestGenerics {
public static void main(String[] args) { List list = new
ArrayList(); // No type safety
list.add("Hello");
list.add(10); // Allows adding different types
String s = (String) list.get(0);
// Requires casting
System.out.println(s);
}
}
With Generics
import java.util.ArrayList;
import java.util.List;
public class TestGenerics {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
// Type-safe list
list.add("Hello");
// list.add(10); // Compilation error: Type mismatch
String s = list.get(0); // No casting required
System.out.println(s);
}
}
2. Enhanced for-loop
The enhanced for-loop, or "for-each" loop, simplifies looping
through arrays or collections.
Without Enhanced for loop -
public class TestEnhancedForLoop {
public static void main(String[] args) {
int[] numbers = {1, 2, 3, 4, 5};
for (int i = 0; i < numbers.length; i++) {
System.out.println(numbers[i]);
}
}
}
With Enhanced for loop -
public class TestEnhancedForLoop {
public static void main(String[] args) {
int[] numbers = {1, 2, 3, 4, 5};
for (int number : numbers) {
System.out.println(number);
}
}
}
Why for - each loop -
1. Improved Readability and Conciseness
int[] numbers = {1, 2, 3, 4, 5};
// Traditional for loop
for (int i = 0; i < numbers.length; i++) {
System.out.println(numbers[i]);
}
// Enhanced for loop
for (int number : numbers) {
System.out.println(number);
}
2. Prevents Common Errors
Since there's no need for loop counters or manual index
management, the enhanced for loop avoids common errors like
ArrayIndexOutOfBoundsException due to incorrect loop bounds.
3. Simplifies Working with Collections
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// Traditional iteration with an Iterator
for (Iterator<String> it = names.iterator(); it.hasNext(); ) {
System.out.println(it.next());
}
// Enhanced for loop
for (String name : names) {
System.out.println(name);
}
4. Reduced Complexity in nested loops
int[][] matrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
// Enhanced for loop for nested arrays
for (int[] row : matrix) {
for (int value : row) {
System.out.print(value + " ");
}
System.out.println();
}
3. Autoboxing and Unboxing
Autoboxing automatically converts primitive types to their
corresponding wrapper classes, while unboxing does the reverse.
Without Autoboxing and Unboxing -
import java.util.ArrayList;
import java.util.List;
public class TestAutoboxing {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(new Integer(5)); // Manual boxing
int num = list.get(0).intValue(); // Manual unboxing
System.out.println(num);
}
}
With Autoboxing and Unboxing -
import java.util.ArrayList;
import java.util.List;
public class TestAutoboxing {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(5); // Autoboxing
int num = list.get(0); // Unboxing
System.out.println(num);
}
}
4. Typesafe Enumerations
Without enums
public class TestEnumWithout {
public static final int MONDAY = 0;
public static final int TUESDAY = 1;
public static final int WEDNESDAY = 2;
public static void main(String[] args) {
int today = WEDNESDAY;
System.out.println("Today is: " + today); // Outputs integer
value
}
}
With enums -
enum Day {
MONDAY, TUESDAY, WEDNESDAY
}
public class TestEnum {
public static void main(String[] args) {
Day today = Day.WEDNESDAY;
System.out.println("Today is: " + today); // Outputs enum
name
}
}
5. Varargs (Variable-Length Arguments)
Without Varargs:
public class TestVarargs {
public static int sum(int[] numbers) {
int sum = 0;
for (int number : numbers) {
sum += number;
}
return sum;
}
public static void main(String[] args) {
int[] nums = {1, 2, 3, 4};
System.out.println(sum(nums));
}
}
With Varargs:
public class TestVarargs {
public static int sum(int... numbers) {
int sum = 0;
for (int number : numbers) {
sum += number;
}
return sum;
}
public static void main(String[] args) {
System.out.println(sum(1, 2, 3, 4)); // Pass numbers directly
}
}
6. Static Import
Without Static Import -
import java.lang.Math;
public class TestStaticImport {
public static void main(String[] args) {
double result = Math.sqrt(25); // Need to use Math class
name
System.out.println(result);
}
}
With static import -
import static java.lang.Math.sqrt;
public class TestStaticImport {
public static void main(String[] args) {
double result = sqrt(25); // No need to use Math class name
System.out.println(result);
}
}
7. Metadata (Annotations)
Without Annotations:
public class TestAnnotation {
public String toString() {
return "This is a test annotation";
}
public void oldMethod() {
System.out.println("This method is outdated");
}
}
With Annotations -
public class TestAnnotation {
@Override
public String toString() {
return "This is a test annotation";
}
@Deprecated
public void oldMethod() {
System.out.println("This method is deprecated");
}
}
In Java, annotations are prefixed with the @ symbol. This symbol
is used to declare metadata annotations above classes, methods,
fields, and other elements in Java code.
Common Examples:
@Override: Indicates that a method overrides a method in a
superclass.
@Deprecated: Marks a method, class, or field as deprecated (i.e.,
it's no longer recommended for use).
@SuppressWarnings: Suppresses specific compiler warnings
Each feature introduced in Java 5 simplifies code, increases type
safety, and provides more flexible options for developers.