December Code

Java data types and operators interview questions, with answers

Java's data types look simple until an interviewer asks what a line of arithmetic prints. The questions are about the rules underneath: how big each primitive is, what happens when an int overflows, how integer division rounds, when a value is widened automatically and when it must be cast, why a char behaves like a number, and what i++ really returns. Most are asked as two or three lines of code and 'what does this print?', so every answer below comes with code, and every output shown was produced by compiling and running it.

The questions start with the primitive types, move through arithmetic and conversions, and end with the operators that trip people up. Then take the free Java diagnostic — ten questions across every Java topic in the bank — to see which of these you can explain but not yet predict.

The questions, with answers

  1. 1.What are the primitive data types in Java, and how big is each?

    In short: Eight: byte, short, int and long are 8-, 16-, 32- and 64-bit signed integers, float and double are 32- and 64-bit floating point, char is a 16-bit unsigned code unit, and boolean is true or false.

    The sizes are fixed by the language specification, not by the machine, which is part of what makes Java portable: an int is 32 bits on every platform. Everything else, including String, arrays and your own classes, is a reference type. Interviewers follow up in three directions. Defaults: fields and array elements get a default value, but a local variable has none, and reading one before assigning it is a compile error. Literals: a whole-number literal is an int and a decimal one is a double, so a long beyond the int range needs an L suffix, as below, and a float needs an f. And boolean: its size is left to the JVM, and unlike C it is not a number, so if (1) does not compile.

    long a = 3_000_000_000L;
    long b = 3_000_000_000;
    // does not compile
  2. 2.What happens when an int overflows in Java?

    In short: It wraps around silently: int arithmetic keeps only the low 32 bits, so Integer.MAX_VALUE + 1 is Integer.MIN_VALUE, and no exception is thrown unless you ask for one.

    Integer arithmetic in Java never checks for overflow. The result keeps the low 32 bits of the true answer, which for values past the top of the range means wrapping round to large negative numbers. The classic place this bites is the midpoint in binary search: (lo + hi) / 2 goes negative once lo + hi passes about 2.1 billion, which is why the safe form is lo + (hi - lo) / 2. The second trap is below: multiplying two ints overflows before the result is widened to long, so the product must be computed in long from the start, with an L on one operand. Math.addExact, multiplyExact and toIntExact throw ArithmeticException instead of wrapping, for code where a wrong answer is worse than a crash.

    int max = Integer.MAX_VALUE;
    System.out.println(max + 1);
    // -2147483648
    int d = 30;
    long ms = d * 86_400_000;
    System.out.println(ms);
    // -1702967296
    long ok = d * 86_400_000L;
    System.out.println(ok);
    // 2592000000
  3. 3.How does integer division round in Java, and what sign does % give?

    In short: Integer division truncates toward zero, so -7 / 2 is -3, and % takes the sign of the left operand, so -7 % 2 is -1; Math.floorDiv and Math.floorMod round down instead.

    Java defines a / b for integers as the true quotient with its fractional part dropped, which rounds toward zero for a negative result, and defines % so that (a / b) * b + a % b == a always holds. The remainder therefore has the sign of the left operand. This is where Java differs from Python, whose // floors and whose % follows the divisor. It matters in practice: n % 2 == 1 is not a correct odd test, because it is -1 for a negative odd number, so test n % 2 != 0 instead. For wrapping an index around a circular buffer, Math.floorMod always returns a value from 0 to k - 1 for a positive k. Dividing an int by zero throws ArithmeticException, but a double divided by zero gives Infinity or NaN.

    System.out.println(-7 / 2);
    // -3
    System.out.println(-7 % 2);
    // -1
    int m = Math.floorMod(-7, 2);
    System.out.println(m);
    // 1
    System.out.println(1.0 / 0);
    // Infinity
  4. 4.What is the difference between widening and narrowing conversions in Java?

    In short: Widening, such as int to long or double, happens automatically because the value always fits; narrowing, such as double to int, needs an explicit cast and can lose information.

    Java converts implicitly only in the direction that cannot overflow: byte to short to int to long to float to double, and char to int. Going the other way needs a cast, which truncates a floating-point value toward zero, keeps only the low bits when a large integer is squeezed into a smaller type, and clamps a double that is out of the int range to the nearest limit. Two widening conversions still lose precision: int to float and long to float or double, because a float's 24-bit significand cannot hold every int, as the second example shows. In expressions, operands smaller than int are promoted to int first, which is why this page's sample, adding to a byte, fails to compile with = but compiles with +=: compound assignment casts back to the variable's type.

    double d = 9.99;
    int i = (int) d;
    System.out.println(i);
    // 9
    int big = 16_777_217;
    float f = big;
    System.out.println((int) f);
    // 16777216
  5. 5.Why does adding two chars in Java print a number?

    In short: Because char is an integer type: in arithmetic both operands are promoted to int, so 'a' + 'b' is 195, and + means concatenation only when one operand is a String.

    A char holds a 16-bit UTF-16 code unit, which Java treats as an unsigned number: 'a' is 97 and 'b' is 98. Binary numeric promotion turns both chars into ints before adding, so the result is an int and println prints its value. + concatenates only when one of its two operands is a String, and it is evaluated left to right, so starting the expression with an empty string makes both + operators concatenate. Casting a number back with (char) gives the character for that code. The same promotion rule makes c = c + 1 fail to compile for a char c, while c++ and c += 1 work, because increment and compound assignment cast back. A frequent real use is digit arithmetic: ch - '0' turns the character '7' into the int 7.

    System.out.println('a' + 'b');
    // 195
    String s = "" + 'a' + 'b';
    System.out.println(s);
    // ab
    char c = '7';
    System.out.println(c - '0');
    // 7
  6. 6.What is the difference between i++ and ++i in Java?

    In short: Both add one to i; the difference is the value of the expression: i++ gives the old value and ++i the new one, which matters only when that value is used.

    As a statement on its own line, i++ and ++i do exactly the same thing, and in a for loop header they are interchangeable. The difference appears when the expression's value is used: int a = i++ stores the value before the increment, and int b = ++j the value after it. Java defines evaluation order precisely — operands are evaluated left to right, and an increment takes effect as soon as its operand is evaluated — so unlike C, an expression that changes and reads the same variable has one defined answer. The classic trap is i = i++: the right side evaluates to the old value, the increment happens, and then the assignment writes the old value back, so i never changes, as the last lines below show.

    int i = 3, j = 3;
    int a = i++;
    int b = ++j;
    System.out.println(a);
    // 3
    System.out.println(b);
    // 4
    i = i++;
    System.out.println(i);
    // 4
  7. 7.What is the difference between && and & in Java?

    In short: && and || skip the right operand when the left one already decides the result; & and | always evaluate both sides, and on integers they are bitwise operators.

    For booleans, && and || short-circuit: false && x never evaluates x, and neither does true || x. That is what makes a guard such as s != null && s.isEmpty() safe, because the method call runs only when s is not null. & and | also accept booleans and give the same true or false result, but they evaluate both operands every time, so the same guard written with a single & throws NullPointerException for a null s, as the last line below does. On int and long operands, &, |, ^ and ~ are bitwise operators, and <<, >> and >>> are shifts: >> copies the sign bit into the vacated positions, while >>> fills them with zeros, which is why -1 >>> 28 is 15 but -1 >> 28 is still -1.

    String s = null;
    boolean e = s != null
        && s.isEmpty();
    System.out.println(e);
    // false
    System.out.println(-1 >>> 28);
    // 15
    if (s != null & s.isEmpty()) {}
    // throws NullPointerException
  8. 8.Why is 0.1 + 0.2 not equal to 0.3 in Java, and how should money be handled?

    In short: double stores binary fractions, so 0.1 and 0.2 are approximations and their sum is 0.30000000000000004; use BigDecimal built from strings, or whole paise in a long, for money.

    float and double follow IEEE 754, the same binary floating point that nearly every language uses. A decimal fraction such as 0.1 has no exact binary form, so each is stored as the nearest representable value, and the error shows once values are combined. Comparing doubles with == is therefore a bug; compare with a tolerance, Math.abs(a - b) < 1e-9, when an approximate answer is acceptable. For money, the standard answers are java.math.BigDecimal, created from a String or with BigDecimal.valueOf, since new BigDecimal(0.1) captures the binary error exactly, or keeping amounts as whole paise in a long. BigDecimal's equals also compares scale, so 2.0 and 2.00 are not equal; compareTo returns 0 for them.

    System.out.println(0.1 + 0.2);
    // 0.30000000000000004
    var a = new BigDecimal("0.1");
    var b = new BigDecimal("0.2");
    System.out.println(a.add(b));
    // 0.3

How the diagnostic asks it

One question from the Java bank, exactly as a sitting would show it. The bank has 3 on data types & operators and 30 across Java.

Data Types & Operators · mediumJAVA-003

Which of the two marked lines fails to compile?

byte b = 10;
b += 5;      // line 1
b = b + 5;   // line 2
  1. 1Line 2 onlycorrect
  2. 2Neither line
  3. 3Line 1 only
  4. 4Both lines

b + 5 promotes the byte to int, so line 2 assigns an int to a byte, a narrowing conversion that needs an explicit cast: it is a compile error, "possible lossy conversion from int to byte". Line 1 compiles because a compound assignment is defined as b = (byte) (b + 5), with the cast built in. So neither line is wrong only if you expect the compiler to narrow automatically, which it does for += but not for =. Line 1 only reverses the rule, and both lines would require += to lack its implicit cast.

Measure it

Reading answers tells you what’s true. A diagnostic tells you what you get wrong.

10 Java questions across its topics, easy to hard, about fifteen minutes. You get a readiness figure with the arithmetic shown, the topics you missed named, and a practice set sized for today. Free: 1 diagnostic a month and 15 problems a day. No card.

What the readiness test measures · how the score is computed

By Harshit · updated