Essential Java Programming Concepts: Syntax, Objects, and Arrays

Java Fundamentals and Core Concepts

Method Signature Syntax

A typical Java method is structured as follows:

accessModifier staticOrInstance returnType methodName(parameterType parameterName, ...) {
    // method body
}

API (Application Programming Interface)

An API is a collection of predefined classes, interfaces, and methods, often referred to as libraries.

Key Features of Java

Java is a versatile and powerful language known for the following characteristics:

  • Simple: It is designed to be easy to learn.
  • Object-Oriented: It is fundamentally based on the use of objects and classes.
  • Distributed: It has built-in support for network-based applications.
  • Interpreted: Java bytecode is interpreted and run by the Java Virtual Machine (JVM).
  • Robust: It features strong error handling and memory management.
  • Secure: It includes built-in security features to protect against threats.
  • Architecture-Neutral: Code can run on any platform that has a JVM.
  • Portable: Code can be executed on different platforms without modification.
  • Performance: It offers good performance, optimized with Just-In-Time (JIT) compilers.
  • Multithreaded: It supports concurrent execution to handle multiple tasks at once.
  • Dynamic: It can load code and classes at runtime.

JDK and JRE

The JDK (Java Development Kit) provides separate programs invoked from the command line to compile, run, and test Java applications. To run Java programs, you need the Java Runtime Environment (JRE).

Basic Program Structure

public class Hello {
    public static void main(String[] args) {
        System.out.println("Welcome to Java!");
    }
}

Java Editions

  • SE (Standard Edition): For desktop applications.
  • EE (Enterprise Edition): For web and server-side applications.
  • ME (Micro Edition): For mobile and embedded devices.

Types of Errors

  • Syntax Error: Detected by the compiler (e.g., a missing semicolon).
  • Runtime Error: Causes the program to crash during execution.
  • Logic Error: Produces an incorrect result without crashing the program.

Java I/O, Variables, and Data Types

Input/Output with Scanner

To read input from the console, you can use the Scanner class.

import java.util.Scanner;

Scanner input = new Scanner(System.in);
System.out.print("Enter a double value: ");
double d = input.nextDouble();

Implicit vs. Explicit Imports

An explicit import (e.g., import java.util.Scanner;) tells the compiler exactly where to find a class. An implicit import (e.g., import java.util.*;) imports all classes from a package. There is no performance difference between them.

Identifiers

Rules for naming variables, methods, and classes:

  • Must start with a letter, an underscore (_), or a dollar sign ($).
  • Cannot be a reserved keyword (e.g., public, class).
  • Cannot be true, false, or null.

Primitive Data Types

Java has eight primitive data types: byte, short, int, long, float, double, char, and boolean.

Constants

A constant variable’s value cannot be changed. It must be declared and initialized in the same statement using the final keyword.

final datatype CONSTANTNAME = VALUE;
final double PI = 3.14159;
final int SIZE = 3;

Type Casting

You can always assign a value to a numeric variable whose type supports a larger range (widening). You cannot assign a value to a variable of a type with a smaller range unless you use explicit type casting (narrowing). You cannot cast between boolean and int.

  • Implicit Casting (Widening): double d = 3;
  • Explicit Casting (Narrowing): int i = (int)3.9; // i becomes 3

Integer Literals

Underscores can be placed between digits for readability (e.g., 1_000_000). An underscore cannot be at the beginning or end (e.g., _45 or 45_ is incorrect).

Increment/Decrement Operators

  • Pre-increment/decrement (++var, --var): The variable is incremented or decremented first, and then the new value is used in the statement.
  • Post-increment/decrement (var++, var--): The original value of the variable is used in the statement, and then it is incremented or decremented.

Numeric Conversion Rules

When an operation involves two numeric operands:

  1. If one operand is a double, the other is converted to a double.
  2. Else, if one is a float, the other is converted to a float.
  3. Else, if one is a long, the other is converted to a long.
  4. Otherwise, both operands are converted to an int.

Control Flow and Logical Operators

Boolean Type and Expressions

A boolean expression evaluates to either true or false. For example: boolean result = (a > b);

If-Else Statements

  • One-Way If Statement:
    if (radius >= 0) area = radius * radius * Math.PI;
  • Two-Way If-Else Statement:
    if (x > 0) System.out.println("Positive");
    else System.out.println("Non-positive");

Logical Operators

  • && (AND) and || (OR) are short-circuit operators.
  • & (AND) and | (OR) always evaluate both sides of the expression.
  • ^ is the exclusive OR operator.

Switch Statements

switch (day) {
    case 1:
        System.out.println("Monday");
        break;
    case 2:
        System.out.println("Tuesday");
        break;
    default:
        System.out.println("Invalid day");
}

Operator Precedence

A simplified order of precedence is: ++ --* / %+ -< >== !=&&||=

Conditional (Ternary) Operator

This is a shorthand for an if-else statement. The statement if (x > 0) y = 1; else y = -1; is equivalent to:

y = (x > 0) ? 1 : -1;
// (boolean-expression) ? expression1 : expression2

Characters, Strings, and Formatting

Generating Random Numbers

A better approach than System.currentTimeMillis() for generating random numbers is using Math.random(), which returns a random double between 0.0 and 1.0.

// Generates a random integer from 0 to 9
int num = (int)(Math.random() * 10);

Escape Sequences

  • \n: Newline
  • \t: Tab
  • \\: Backslash
  • \": Double quote

Character and String Types

  • Character: char letter = 'A'; or char unicodeChar = '\u0041'; // Unicode for 'A'
  • String: String msg = "Welcome to Java";

You can access a character in a string using charAt(): System.out.println(msg.charAt(0)); // Prints 'W'

Reading a String from the Console

Scanner input = new Scanner(System.in);
String s = input.nextLine();
char ch = s.charAt(0);

Converting Between Strings and Numbers

If a string is not a valid number, attempting to parse it will cause a runtime error.

  • String to Number:
    int n = Integer.parseInt("123");
    double d = Double.parseDouble("45.6");
  • Number to String:
    String s = n + "";

Formatted Output with printf

The printf method allows for formatted output using specifiers. By default, output is right-justified.

int count = 5;
double amount = 45.5;
System.out.printf("count is %d and amount is %f", count, amount);
// Output: count is 5 and amount is 45.500000

Loops in Java

The while Loop

int count = 0;
while (count < 10) {
    System.out.println("Hello");
    count++;
}

Sentinel Values

A sentinel value is a special input value used to signify the end of a loop.

int num = input.nextInt();
while (num != 0) { // 0 is the sentinel value
    sum += num;
    num = input.nextInt();
}

The do-while Loop

This loop executes its body at least once.

do {
    System.out.println("This runs at least once");
} while (condition);

The for Loop

for (int i = 0; i < 10; i++) {
    System.out.println(i);
}

Break and Continue

  • break: Exits the current loop early.
  • continue: Skips the rest of the current iteration and proceeds to the next one.

Working with Methods

Defining and Invoking Methods

A method is a collection of statements grouped together to perform an operation.

public static int square(int n) {
    return n * n;
}

The return Statement

A return statement is required for a value-returning method. All possible execution paths must lead to a return statement.

Passing Parameters by Value

Java passes arguments to methods by value. The arguments must match the parameters in order, number, and compatible type. A compatible type means you can pass an argument without explicit casting (e.g., passing an int to a double parameter).

Method Overloading

Overloaded methods share the same name but must have different parameter lists (i.e., different number or types of parameters). You cannot overload methods based only on different modifiers or return types.

int max(int a, int b);
double max(double a, double b);

Scope of Local Variables

A local variable is a variable defined inside a method. Its scope is the part of the program where it can be referenced, which starts from its declaration and continues to the end of its containing block. A local variable must be declared before it can be used. You can declare local variables with the same name in different, non-nested blocks.

Single-Dimensional Arrays

Declaring and Creating Arrays

You can declare and create an array in one step:

datatype[] arrayRefVar = new datatype[arraySize];
double[] myList = new double[10];

Arrays and the Heap

The JVM stores arrays in a memory area called the heap, which is used for dynamic memory allocation.

Array Length and Default Values

Once an array is created, its size is fixed. When created, its elements are assigned default values: 0 for numeric types, '\u0000' for char, and false for boolean.

Array Initializers

You can declare, create, and initialize an array in a single statement:

double[] myList = {1.9, 2.9, 3.4, 3.5};

Processing Arrays

Common array operations include:

  1. Initializing with input values
  2. Initializing with random values
  3. Printing arrays
  4. Summing all elements
  5. Finding the largest element
  6. Finding the smallest index of the largest element

The Enhanced for Loop (For-Each)

This loop simplifies iterating over an array. You must use a traditional indexed loop if you need to modify elements or traverse in a different order.

for (elementType value : arrayRefVar) {
    // Process the value
}

// Example
for (double val : myList) {
    System.out.println(val);
}

Copying Arrays

The assignment operator (list2 = list1;) only copies the reference, not the array itself. To create a true copy, use a loop or the System.arraycopy utility.

// Using System.arraycopy
System.arraycopy(sourceArray, src_pos, targetArray, tar_pos, length);

// Example
int[] newList = new int[oldList.length];
System.arraycopy(oldList, 0, newList, 0, oldList.length);

Passing Arrays to Methods

public static void printArray(int[] array) {
    for (int i = 0; i < array.length; i++) {
        System.out.print(array[i] + " ");
    }
}

// Invoking the method
int[] list = {3, 1, 2, 6, 4, 2};
printArray(list);
printArray(new int[]{3, 1, 2, 6, 4, 2});

Variable-Length Arguments (Varargs)

You can pass a variable number of arguments of the same type to a method. The parameter is treated as an array inside the method.

public static void printMax(double... numbers) { ... }
// typeName... parameterName

Utility Methods in the Arrays Class

The Arrays.binarySearch Method

To work correctly, the array must be pre-sorted in increasing order.

int[] list = {2, 4, 7, 10, 11, 45, 50, 59, 60, 66, 69, 70, 79};
System.out.println("Index is " + java.util.Arrays.binarySearch(list, 11));

The Arrays.sort Method

double[] numbers = {6.0, 4.4, 1.9, 2.9, 3.4, 3.5};
java.util.Arrays.sort(numbers);

The Arrays.toString Method

int[] list = {2, 4, 7, 10};
System.out.println(java.util.Arrays.toString(list)); // [2, 4, 7, 10]

Processing Command-Line Arguments

If you run a program with no command-line arguments, the args array is created as new String[0]. The array is empty (args.length is 0), but it is not null.

Multidimensional Arrays

Declaring and Creating 2D Arrays

A 2D array can be thought of as a table or a matrix.

// Declaration
dataType[][] refVar;

// Creation
refVar = new dataType[10][10];

// Combined
dataType[][] refVar = new dataType[10][10];

// Alternative Syntax
dataType refVar[][] = new dataType[10][10];

Ragged Arrays

A ragged array is a 2D array where the rows can have different lengths.

int[][] array = {{1, 2, 3}, {4, 5}, {7}};

Processing 2D Arrays

Common operations include:

  1. Initializing with input values
  2. Printing arrays
  3. Summing all elements
  4. Summing elements by column
  5. Finding the row with the largest sum

Objects and Classes

Defining Classes and Creating Objects

A class is a template for creating objects. Only one class in a source file can be public, and its name must match the file name. Each class is compiled into a separate .class file.

class Circle {
    double radius = 1.0; // Data field

    Circle() { // Constructor
    }

    Circle(double newRadius) { // Constructor
        radius = newRadius;
    }

    double getArea() { // Method
        return radius * radius * 3.14159;
    }
}

Constructors

A constructor initializes an object when it is created. It must have the same name as the class and has no return type (not even void). A constructor with no parameters is a no-arg constructor. Constructors are invoked using the new operator.

Default Constructors

If a class is defined without any constructors, a no-arg constructor with an empty body is implicitly defined.

Data Field Default Values

Data fields are assigned default values if not explicitly initialized (e.g., 0 for numeric types, null for object references). Local variables inside methods are not assigned default values.

Accessing Objects

You declare and create an object in a single step:

ClassName objectRefVar = new ClassName();
Circle myCircle = new Circle();

The null Value and NullPointerException

A NullPointerException is a common runtime error that occurs when you try to invoke a method on a reference variable that holds a null value. To fix this, ensure the variable references an actual object before use.

Garbage Collection

When an object is no longer referenced by any variable, it becomes garbage. The JVM’s garbage collector automatically reclaims the memory used by these objects.

Instance vs. Static Members

  • Instance variables and methods belong to a specific instance (object) of a class and are invoked through an object reference.
  • Static variables and methods are shared by all instances of a class and are not tied to a specific object.

Static Variables, Constants, and Methods

Use ClassName.methodName(arguments) to invoke a static method and ClassName.staticVariable to access a static variable.

public class MathUtil {
    public static final double PI = 3.14159;

    public static double square(double x) {
        return x * x;
    }
}

Organizing Classes with Packages

Packages are used to organize classes. To place a class in a package, add a package statement as the first line of the source file: package packageName;. If a class has no package statement, it is in the default package.

Immutable Classes

For a class to be immutable, it must mark all data fields as private and provide no mutator (setter) methods or any accessor (getter) methods that would return a reference to a mutable data field object.

The ‘this’ Keyword

The this keyword is a reference to the current object itself. Common uses include:

  1. Referencing a class’s hidden data fields when a local variable has the same name.
  2. Enabling a constructor to invoke another constructor of the same class.
public Circle(double radius) {
    this.radius = radius;
}