Java Advanced Topics
Wrapper Classes, Command Line Arguments & Extended Concepts
Chapter 14: Supplementary Java Topics
Completing the comprehensive Java programming curriculum
Wrapper Classes in Java
What are Wrapper Classes?
Wrapper classes provide a way to use primitive data types as objects. They "wrap" primitive values in an object so they can be used where objects are required.
Primitive to Wrapper Mapping
| Primitive Type | Wrapper Class |
|---|---|
| byte | Byte |
| short | Short |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
| char | Character |
| boolean | Boolean |
Why Use Wrapper Classes?
- Collections: Can store only objects, not primitives
- Generics: Work only with objects
- Utility Methods: Conversion, parsing, comparison methods
- Null Values: Can represent null, primitives cannot
- Synchronization: Can be used in synchronized collections
Basic Example
// Creating wrapper objects
Integer num1 = new Integer(10); // Deprecated
Integer num2 = Integer.valueOf(20); // Preferred
Integer num3 = 30; // Autoboxing
// Converting back to primitive
int primitive = num1.intValue(); // Unboxing
int auto = num2; // Auto-unboxing
Autoboxing and Unboxing
Autoboxing
Automatic conversion of primitive types to their corresponding wrapper class objects.
// Autoboxing examples
Integer num = 100; // int to Integer
Double d = 3.14; // double to Double
Boolean b = true; // boolean to Boolean
Character c = 'A'; // char to Character
// In collections
List<Integer> numbers = new ArrayList<>();
numbers.add(10); // Autoboxing: int to Integer
numbers.add(20);
numbers.add(30);
// In method calls
public void processNumber(Integer num) {
System.out.println("Number: " + num);
}
processNumber(42); // Autoboxing: int to Integer
Unboxing
Automatic conversion of wrapper class objects to their corresponding primitive types.
// Unboxing examples
Integer num = new Integer(100);
int primitive = num; // Integer to int
// In arithmetic operations
Integer a = 10;
Integer b = 20;
int sum = a + b; // Both unboxed, then sum calculated
// In conditional statements
Boolean flag = Boolean.valueOf(true);
if (flag) { // Boolean unboxed to boolean
System.out.println("Flag is true");
}
// In array operations
Integer[] wrapperArray = {1, 2, 3, 4, 5};
int total = 0;
for (int value : wrapperArray) { // Unboxing
total += value;
}
⚠️ Performance Consideration
Autoboxing/unboxing can impact performance in loops. Use primitives when possible for intensive operations.
Wrapper Class Utility Methods
Integer Class Methods
// Parsing strings to numbers
int num1 = Integer.parseInt("123");
int num2 = Integer.parseInt("1010", 2); // Binary
int num3 = Integer.parseInt("FF", 16); // Hexadecimal
// Creating Integer objects
Integer obj1 = Integer.valueOf(100);
Integer obj2 = Integer.valueOf("200");
// Conversion methods
String binary = Integer.toBinaryString(10); // "1010"
String hex = Integer.toHexString(255); // "ff"
String octal = Integer.toOctalString(8); // "10"
// Comparison
Integer a = 100, b = 200;
int result = a.compareTo(b); // -1 (a < b)
// Min/Max values
int maxInt = Integer.MAX_VALUE; // 2147483647
int minInt = Integer.MIN_VALUE; // -2147483648
// Utility methods
Integer.max(10, 20); // Returns 20
Integer.min(10, 20); // Returns 10
Integer.sum(10, 20); // Returns 30
Character Class Methods
// Character testing methods
char ch = 'A';
Character.isLetter(ch); // true
Character.isDigit('5'); // true
Character.isWhitespace(' '); // true
Character.isUpperCase('A'); // true
Character.isLowerCase('a'); // true
// Character conversion
Character.toUpperCase('a'); // 'A'
Character.toLowerCase('Z'); // 'z'
Character.toString('X'); // "X"
// Numeric value
Character.getNumericValue('5'); // 5
Character.getNumericValue('A'); // 10 (hex)
// Creating Character objects
Character charObj = Character.valueOf('B');
Boolean Class Methods
// Parsing strings to boolean
Boolean.parseBoolean("true"); // true
Boolean.parseBoolean("false"); // false
Boolean.parseBoolean("TRUE"); // true (case insensitive)
// Creating Boolean objects
Boolean b1 = Boolean.valueOf(true);
Boolean b2 = Boolean.valueOf("false");
// Logical operations
Boolean.logicalAnd(true, false); // false
Boolean.logicalOr(true, false); // true
Boolean.logicalXor(true, false); // true
// Comparison
Boolean a = true, b = false;
a.compareTo(b); // 1 (true > false)
Command Line Arguments
What are Command Line Arguments?
Command line arguments are parameters passed to a Java program when it is executed from the command line. They are stored in the String array parameter of the main method.
Basic Example
// CommandLineExample.java
public class CommandLineExample {
public static void main(String[] args) {
System.out.println("Number of arguments: " + args.length);
// Display all arguments
for (int i = 0; i < args.length; i++) {
System.out.println("Argument " + i + ": " + args[i]);
}
// Enhanced for loop
System.out.println("\nAll arguments:");
for (String arg : args) {
System.out.println(arg);
}
}
}
Running the Program
Output
Practical Calculator Example
// Calculator.java
public class Calculator {
public static void main(String[] args) {
if (args.length != 3) {
System.out.println("Usage: java Calculator ");
System.out.println("Example: java Calculator 10 + 5");
return;
}
try {
double num1 = Double.parseDouble(args[0]);
String operator = args[1];
double num2 = Double.parseDouble(args[2]);
double result = 0;
switch (operator) {
case "+":
result = num1 + num2;
break;
case "-":
result = num1 - num2;
break;
case "*":
case "x":
result = num1 * num2;
break;
case "/":
if (num2 == 0) {
System.out.println("Error: Division by zero!");
return;
}
result = num1 / num2;
break;
default:
System.out.println("Error: Invalid operator " + operator);
return;
}
System.out.println(num1 + " " + operator + " " + num2 + " = " + result);
} catch (NumberFormatException e) {
System.out.println("Error: Invalid number format!");
}
}
}
Advanced Command Line Processing
File Processing Example
// FileProcessor.java
import java.io.*;
import java.util.Scanner;
public class FileProcessor {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("Usage: java FileProcessor [options]");
System.out.println("Options:");
System.out.println(" -c Count lines");
System.out.println(" -w Count words");
System.out.println(" -s Show file size");
return;
}
String filename = args[0];
boolean countLines = false;
boolean countWords = false;
boolean showSize = false;
// Process options
for (int i = 1; i < args.length; i++) {
switch (args[i]) {
case "-c":
countLines = true;
break;
case "-w":
countWords = true;
break;
case "-s":
showSize = true;
break;
default:
System.out.println("Unknown option: " + args[i]);
}
}
processFile(filename, countLines, countWords, showSize);
}
private static void processFile(String filename, boolean countLines,
boolean countWords, boolean showSize) {
try {
File file = new File(filename);
if (!file.exists()) {
System.out.println("File not found: " + filename);
return;
}
if (showSize) {
System.out.println("File size: " + file.length() + " bytes");
}
if (countLines || countWords) {
Scanner scanner = new Scanner(file);
int lineCount = 0;
int wordCount = 0;
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
lineCount++;
if (countWords) {
String[] words = line.trim().split("\\s+");
if (!line.trim().isEmpty()) {
wordCount += words.length;
}
}
}
scanner.close();
if (countLines) {
System.out.println("Lines: " + lineCount);
}
if (countWords) {
System.out.println("Words: " + wordCount);
}
}
} catch (FileNotFoundException e) {
System.out.println("Error reading file: " + e.getMessage());
}
}
}
Configuration-Based Application
// ConfigApp.java
public class ConfigApp {
private static String host = "localhost";
private static int port = 8080;
private static boolean debug = false;
private static String logLevel = "INFO";
public static void main(String[] args) {
parseArguments(args);
System.out.println("Application Configuration:");
System.out.println("Host: " + host);
System.out.println("Port: " + port);
System.out.println("Debug: " + debug);
System.out.println("Log Level: " + logLevel);
// Start application with configuration
startApplication();
}
private static void parseArguments(String[] args) {
for (int i = 0; i < args.length; i++) {
switch (args[i]) {
case "--host":
case "-h":
if (i + 1 < args.length) {
host = args[++i];
}
break;
case "--port":
case "-p":
if (i + 1 < args.length) {
try {
port = Integer.parseInt(args[++i]);
} catch (NumberFormatException e) {
System.err.println("Invalid port number: " + args[i]);
}
}
break;
case "--debug":
case "-d":
debug = true;
break;
case "--log-level":
case "-l":
if (i + 1 < args.length) {
logLevel = args[++i].toUpperCase();
}
break;
case "--help":
showHelp();
System.exit(0);
break;
default:
System.err.println("Unknown argument: " + args[i]);
}
}
}
private static void showHelp() {
System.out.println("Usage: java ConfigApp [options]");
System.out.println("Options:");
System.out.println(" -h, --host Set host (default: localhost)");
System.out.println(" -p, --port Set port (default: 8080)");
System.out.println(" -d, --debug Enable debug mode");
System.out.println(" -l, --log-level Set log level (default: INFO)");
System.out.println(" --help Show this help");
}
private static void startApplication() {
System.out.println("Starting application...");
// Application logic here
}
}
Inner Classes - Detailed Coverage
Regular Inner Classes
// OuterClass.java
public class OuterClass {
private String outerField = "Outer Field";
// Regular inner class
public class InnerClass {
private String innerField = "Inner Field";
public void display() {
System.out.println("Outer field: " + outerField);
System.out.println("Inner field: " + innerField);
// Can access outer class methods
outerMethod();
}
}
private void outerMethod() {
System.out.println("Outer method called");
}
public void createInner() {
InnerClass inner = new InnerClass();
inner.display();
}
public static void main(String[] args) {
OuterClass outer = new OuterClass();
outer.createInner();
// Creating inner class from outside
OuterClass.InnerClass inner = outer.new InnerClass();
inner.display();
}
}
Method Local Inner Classes
public class MethodLocalExample {
private String outerField = "Outer";
public void methodWithInnerClass() {
final String localVar = "Local Variable";
// Method local inner class
class LocalInnerClass {
public void display() {
System.out.println("Outer field: " + outerField);
System.out.println("Local variable: " + localVar);
}
}
LocalInnerClass local = new LocalInnerClass();
local.display();
}
public static void main(String[] args) {
MethodLocalExample example = new MethodLocalExample();
example.methodWithInnerClass();
}
}
Static Nested Classes
public class OuterClass {
private static String staticField = "Static Field";
private String instanceField = "Instance Field";
// Static nested class
public static class StaticNestedClass {
public void display() {
// Can access static members of outer class
System.out.println("Static field: " + staticField);
// Cannot directly access instance members
// System.out.println(instanceField); // Compilation error
// Need outer class instance to access instance members
OuterClass outer = new OuterClass();
System.out.println("Instance field: " + outer.instanceField);
}
}
public static void main(String[] args) {
// Creating static nested class instance
OuterClass.StaticNestedClass nested = new OuterClass.StaticNestedClass();
nested.display();
}
}
Anonymous Inner Classes
interface Greeting {
void sayHello();
}
public class AnonymousExample {
public static void main(String[] args) {
// Anonymous inner class implementing interface
Greeting greeting = new Greeting() {
@Override
public void sayHello() {
System.out.println("Hello from anonymous class!");
}
};
greeting.sayHello();
// Anonymous inner class extending class
Thread thread = new Thread() {
@Override
public void run() {
System.out.println("Running in anonymous thread class");
}
};
thread.start();
// Using lambda (Java 8+) - modern alternative
Greeting lambdaGreeting = () -> System.out.println("Hello from lambda!");
lambdaGreeting.sayHello();
}
}
Garbage Collection in Detail
How Garbage Collection Works
Garbage Collection (GC) is Java's automatic memory management feature that reclaims memory used by objects that are no longer reachable.
Memory Areas
- Young Generation: Where new objects are allocated
- Old Generation: Long-lived objects
- Permanent Generation: Class metadata (Java 7 and earlier)
- Metaspace: Class metadata (Java 8+)
GC Process
- Mark: Identify which objects are still in use
- Sweep: Remove unmarked (unreachable) objects
- Compact: Defragment memory
// Objects eligible for garbage collection
public class GCExample {
public static void main(String[] args) {
// Creating objects
String str1 = new String("Hello");
String str2 = new String("World");
// str1 becomes eligible for GC
str1 = null;
// Both str1 and str2 become eligible for GC
str1 = str2 = null;
// Suggesting GC (not guaranteed)
System.gc();
// Creating objects in loop
for (int i = 0; i < 1000; i++) {
String temp = new String("Temporary " + i);
// temp becomes eligible for GC at end of each iteration
}
}
}
Making Objects Eligible for GC
public class GCEligibility {
// Method 1: Nullifying references
public void nullifyReference() {
String str = new String("Test");
str = null; // Now eligible for GC
}
// Method 2: Reassigning references
public void reassignReference() {
String str1 = new String("First");
String str2 = new String("Second");
str1 = str2; // "First" object eligible for GC
}
// Method 3: Objects created in method scope
public void methodScope() {
String localStr = new String("Local");
// localStr eligible for GC when method ends
}
// Method 4: Island of isolation
class Node {
Node next;
String data;
Node(String data) {
this.data = data;
}
}
public void islandOfIsolation() {
Node node1 = new Node("Node1");
Node node2 = new Node("Node2");
node1.next = node2;
node2.next = node1; // Circular reference
node1 = null;
node2 = null;
// Both nodes eligible for GC despite circular reference
}
}
finalize() Method
public class FinalizeExample {
private String name;
public FinalizeExample(String name) {
this.name = name;
}
// Called by GC before object destruction
@Override
protected void finalize() throws Throwable {
System.out.println("Finalizing: " + name);
// Cleanup operations can be performed here
// But avoid relying on finalize() for critical cleanup
super.finalize();
}
public static void main(String[] args) {
FinalizeExample obj1 = new FinalizeExample("Object1");
FinalizeExample obj2 = new FinalizeExample("Object2");
obj1 = null;
obj2 = null;
System.gc(); // Request garbage collection
try {
Thread.sleep(1000); // Give GC time to run
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
⚠️ Important Notes about finalize()
- finalize() method is deprecated in Java 9+
- Not guaranteed to be called
- Can cause performance issues
- Use try-with-resources or explicit cleanup methods instead
Summary: Advanced Java Topics
Wrapper Classes
- Convert primitives to objects
- Enable collection storage
- Provide utility methods
- Support autoboxing/unboxing
- Essential for generics
Command Line Arguments
- Pass parameters to programs
- Configure application behavior
- Process user input
- Support scripting and automation
- Enable flexible program execution
Inner Classes
- Regular inner classes (instance-based)
- Static nested classes (class-based)
- Method local inner classes
- Anonymous inner classes
- Encapsulation and organization benefits
Garbage Collection
- Automatic memory management
- Mark-sweep-compact algorithm
- Generational garbage collection
- Object lifecycle management
- Performance optimization
🎯 Learning Outcomes
You now understand the complete Java programming ecosystem including advanced memory management, flexible program configuration, and sophisticated class organization techniques that are essential for professional Java development.

