Project Based Learning in Java

Operators, Expressions, Casting, and Scanner Input

Operator families, precedence, widening, narrowing, casting, and Scanner.

Foundation Topic CO1 aligned Unit 1

Learning outcome: Build expressions, apply operators, predict precedence, cast values safely, and read typed input from the keyboard.

An expression is any combination of values, variables, and operators that produces a result.

int total = price * quantity + 50;

In this expression, price, quantity, and 50 are operands. The symbols * and + are operators.

Operator Families

The six main families of Java operators Java Operators Arithmetic + - * / % Assignment = += -= *= Increment / Decrement ++ -- Relational == != < > <= >= Logical && || ! Bitwise & | ^ ~ << >>
Figure 1. Java operators are grouped by purpose.

Arithmetic Operators

Operator Meaning Example when a = 7, b = 2
+ Addition a + b gives 9
- Subtraction a - b gives 5
* Multiplication a * b gives 14
/ Division a / b gives 3 because both are integers
% Modulus, remainder a % b gives 1

The + operator also joins strings:

System.out.println("Age: " + 19);

Output:

Age: 19

Assignment and Compound Assignment

The assignment operator stores a value in a variable.

int x = 10;
x += 5;   // same as x = x + 5; result: 15
x -= 3;   // same as x = x - 3; result: 12
x *= 2;   // same as x = x * 2; result: 24
x %= 5;   // same as x = x % 5; result: 4

For ordinary examples these comments describe the result, but a compound assignment is not always identical to writing the expanded form: Java evaluates its left side once and performs an implicit cast back to the left-side type. For example, byte value = 10; value += 1; compiles, while value = value + 1; needs a cast because value + 1 has type int.

Common compound assignment operators:

Operator Meaning
+= Add and assign
-= Subtract and assign
*= Multiply and assign
/= Divide and assign
%= Remainder and assign

Increment and Decrement

The ++ operator adds 1. The -- operator subtracts 1.

In simple terms: i++ hands over the value and then increases it; ++i increases first and then hands it over. On a line of its own the two are identical — inside a larger expression they are not.

Prefix changes the value before it is used. Postfix uses the old value first, then changes it.

int a = 5;
int b = a++;   // b gets 5, then a becomes 6
int c = ++a;   // a becomes 7, then c gets 7

System.out.println(a); // 7
System.out.println(b); // 5
System.out.println(c); // 7

Relational Operators

Relational operators compare two values and return a boolean.

In simple terms: These answer a yes-or-no question and produce a boolean. A single = assigns a value; a double == asks a question.

Operator Meaning
== Equal to
!= Not equal to
> Greater than
< Less than
>= Greater than or equal to
<= Less than or equal to

Example:

int marks = 65;
boolean passed = marks >= 40;

Use == for comparing primitive values. When comparing the content of strings, use .equals().

String a = "Java";
String b = "Java";

System.out.println(a.equals(b)); // true

Logical Operators

Logical operators combine boolean values.

In simple terms: && and || stop as soon as the answer is settled: if the left side of && is false, the right side is never evaluated. That short-circuit is what makes if (s != null && s.length() > 0) safe.

Operator Name True when
&& AND Both sides are true
|| OR At least one side is true
! NOT The value is false; it flips the value

Example:

int age = 20;
int marks = 65;

boolean eligible = (age >= 18) && (marks >= 50);

&& and || short-circuit:

Operator Short-circuit rule
&& If the left side is false, the right side is not evaluated.
|| If the left side is true, the right side is not evaluated.

Bitwise Operators

Bitwise operators work on the individual bits of integral types (byte, short, int, long, and char, with smaller operands promoted to int). They are useful for low-level tasks such as flags and masks. The binary operators &, |, and ^ also accept boolean operands; unlike && and ||, they evaluate both sides.

Operator Name Meaning
& AND Bit is 1 only if both bits are 1
\| OR Bit is 1 if at least one bit is 1
^ XOR Bit is 1 if the two bits differ
~ Complement Flips every bit (unary)
<< Left shift Shifts bits left, filling with 0
>> Signed right shift Shifts bits right, keeping the sign bit
>>> Unsigned right shift Shifts bits right, filling with 0

Example with a = 6 (binary 0110) and b = 3 (binary 0011):

int a = 6;   // 0110
int b = 3;   // 0011

System.out.println(a & b);  // 2  -> 0010
System.out.println(a | b);  // 7  -> 0111
System.out.println(a ^ b);  // 5  -> 0101
System.out.println(~a);     // -7 (all bits flipped)

Shifting moves bits left or right:

System.out.println(6 << 1); // 12  -> multiply by 2
System.out.println(6 >> 1); // 3   -> divide by 2

With Boolean operands, && and || short-circuit, while & and | always evaluate both operands. With integral operands, &, |, and ^ operate on bits. There are no integral forms of && or ||.

Operator Precedence

When several operators appear in one expression, Java follows precedence rules. Higher-precedence operators are evaluated first.

In simple terms: Precedence is the order the language reads an expression, just as multiplication is read before addition in arithmetic. Brackets overrule it — and spare the next reader from having to guess.

Operator precedence in the expression 2 plus 3 times 4 2 + 3 * 4 Step 1 3 * 4 = 12 Step 2 2 + 12 = 14 Multiplication has higher precedence than addition.
Figure 2. 2 + 3 * 4 evaluates to 14, not 20.

Simplified precedence order:

Level Operators Group
1 ++, --, !, ~, unary +, unary - Unary
2 *, /, % Multiplicative
3 +, - Additive
4 <<, >>, >>> Shift
5 <, >, <=, >= Relational
6 ==, != Equality
7 & Bitwise AND
8 ^ Bitwise XOR
9 \| Bitwise OR
10 && Logical AND
11 || Logical OR
12 ?: Conditional
13 =, +=, -=, *=, /=, %= Assignment

When in doubt, use parentheses:

int a = 2 + 3 * 4;     // 14
int b = (2 + 3) * 4;   // 20

Type Conversion and Casting

Java sometimes needs to convert a value from one type to another.

In simple terms: Widening is pouring a small glass into a large one: nothing spills, and Java does it silently. Narrowing is the reverse, so Java makes you write the cast as a signed acknowledgement that you accept the spill.

There are two main cases:

  1. Widening primitive conversion: a conversion Java permits implicitly, such as int to long or double.
  2. Narrowing primitive conversion: a conversion such as double to int. It normally requires an explicit cast and may lose range or precision.

“Widening” is a language category, not a promise that every value remains exact. Converting an int or long to float, or a long to double, can lose low-order precision even though no cast is required. Also, char widens to int, long, float, or double; it does not widen to byte or short.

Widening conversion is automatic, narrowing conversion needs a cast Numeric conversion direction byte short int long float double widening: automatic narrowing: explicit cast required
Figure 3. Java permits these widening conversions implicitly; some integer-to-floating conversions can still lose precision. Narrowing normally requires an explicit cast.

Widening Conversion

int i = 100;
double d = i;       // automatic: int to double

System.out.println(d); // 100.0

Narrowing Conversion

double pi = 3.99;
int n = (int) pi;   // explicit cast: double to int

System.out.println(n); // 3

Casting from double to int truncates the fractional part. It does not round.

This explains integer division:

System.out.println(7 / 2);          // 3
System.out.println((double) 7 / 2); // 3.5
System.out.println(7.0 / 2);        // 3.5

Scanner Input

Use Scanner to read values typed by the user.

import java.util.Scanner;

public class InputDemo {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        System.out.print("Enter age: ");
        int age = sc.nextInt();

        System.out.print("Enter name: ");
        String name = sc.next();

        System.out.println(name + " is " + age + " years old.");
        sc.close();
    }
}

Common Scanner methods:

Method Reads
nextInt() An integer
nextDouble() A decimal number
next() One word
nextLine() The rest of the current line

Scanner pitfall:

After nextInt() or nextDouble(), a newline may remain in the input buffer. If the next call is nextLine(), it may read that leftover newline as an empty line.

Fix:

int age = sc.nextInt();
sc.nextLine();             // consume leftover newline
String fullName = sc.nextLine();

Worked Example: Two-Number Calculator

import java.util.Scanner;

public class Calculator {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        System.out.print("Enter first number: ");
        int a = sc.nextInt();

        System.out.print("Enter second number: ");
        int b = sc.nextInt();

        System.out.println("Sum        = " + (a + b));
        System.out.println("Difference = " + (a - b));
        System.out.println("Product    = " + (a * b));

        if (b == 0) {
            System.out.println("Quotient   = undefined (division by zero)");
            System.out.println("Remainder  = undefined (division by zero)");
        } else {
            System.out.println("Quotient   = " + ((double) a / b));
            System.out.println("Remainder  = " + (a % b));
        }

        sc.close();
    }
}

Sample run:

Enter first number: 17
Enter second number: 5
Sum        = 22
Difference = 12
Product    = 85
Quotient   = 3.4
Remainder  = 2

Practice

Problem 1: Celsius to Fahrenheit

Read a Celsius temperature and convert it using:

F = C * 9 / 5 + 32
import java.util.Scanner;

public class TempConvert {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        System.out.print("Enter temperature in Celsius: ");
        double c = sc.nextDouble();

        double f = c * 9 / 5 + 32;
        System.out.println(c + " C = " + f + " F");

        sc.close();
    }
}

Problem 2: Prefix vs Postfix

Predict the output:

public class IncDemo {
    public static void main(String[] args) {
        int a = 5;
        int b = a++;
        int c = ++a;

        System.out.println("a = " + a);
        System.out.println("b = " + b);
        System.out.println("c = " + c);
    }
}

Problem 3: Eligibility Check

import java.util.Scanner;

public class Eligibility {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        System.out.print("Enter age: ");
        int age = sc.nextInt();

        System.out.print("Enter marks: ");
        int marks = sc.nextInt();

        boolean eligible = (age >= 18) && (marks >= 50);
        System.out.println("Eligible to apply? " + eligible);

        sc.close();
    }
}

Common Mistakes

Mistake Correction
Expecting 7 / 2 to produce 3.5 Cast one operand or use a decimal value.
Thinking (int) 3.99 rounds It truncates to 3.
Writing = when comparison needs == Use = for assignment and == for equality comparison.
Comparing strings with == Use .equals() for string content.
Forgetting the Scanner newline issue Add sc.nextLine() after numeric reads when needed.
Assuming a++ and ++a are always the same They differ inside larger expressions.
Assuming every widening conversion is exact int or long to a floating-point type can lose low-order precision.
Calling & and | only bitwise operators They also accept Boolean operands and evaluate both sides.

Quick Check

  1. What is the value of 2 + 3 * 4, and why?
  2. After int a = 5; int b = a++;, what are a and b?
  3. Is int to double widening or narrowing?
  4. What does (int) 3.99 produce?
  5. Why can nextLine() return an empty string after nextInt()?

Summary

Operators combine operands into expressions. Precedence decides the order of evaluation, and parentheses make intent clear. Widening conversions are automatic, narrowing conversions require a cast, and Scanner lets Java programs read typed input from the keyboard.