Variables and primitive types
Starting out11 min readLesson 3 of 3
3.1 Variables hold values under a name
A variable is a named storage location with a declared type. You declare it by writing the type, a name, and usually an initial value:
int age = 16;
The declaration both reserves the name and, in this form, assigns a value. A later line such as age = 17; assigns a new value to the existing variable. Java checks types at compile time, so assigning a string to an int fails before the program runs.
Local variables inside a method do not receive a default value. The compiler refuses to use one that has not been assigned. That rule keeps uninitialised values out of a calculation.
3.1.1 The eight primitive types
A primitive type stores a single value directly. Java has eight of them, and each has a defined set of values.
byteholds an 8-bit signed integer, from -128 to 127.shortholds a 16-bit signed integer.intholds a 32-bit signed integer and is the usual choice for whole numbers.longholds a 64-bit signed integer and needs anLsuffix on large literals.floatholds a 32-bit floating-point value and needs anfsuffix.doubleholds a 64-bit floating-point value and is the default for decimal literals.charholds one 16-bit Unicode character, written in single quotes.booleanholdstrueorfalse.
Use int for counts and ordinary quantities, long when the range may exceed about 2.1 billion, and double for most measurements. For money, storing whole paise as an int or long avoids most decimal surprises. String is a class, not a primitive, so it appears in a later lesson.
Do not choose a smaller type only to save memory in a beginner program. The range of a type is the first question, and readability comes next.
public class Main {
public static void main(String[] args) {
byte small = 100;
int count = 42;
long distance = 384_400_000L;
double price = 99.95;
char grade = 'A';
boolean passed = true;
System.out.println(small + " " + count + " " + distance);
System.out.println(price + " " + grade + " " + passed);
}
}Output
100 42 384400000 99.95 A true
3.1.2 Literals and suffixes
A literal is a value written directly in source code. 42 is an int literal, 42L is a long, 3.14 is a double, and 3.14f is a float. 'J' is a character literal, and true is a boolean literal.
Whole-number literals are int by default. A value above Integer.MAX_VALUE needs to be written as a long with an L suffix. Without the suffix, the compiler reports that the integer number is too large. The suffix is part of the literal, not part of the variable type.
You can put underscores between digits to improve readability: 1_000_000 and 384_400_000L. Underscores cannot start or end a literal, sit next to a decimal point, or appear at the end of a suffix.
3.1.3 Names, scope, and constants
A variable name starts with a letter, _, or $, and later characters may also include digits. By convention, ordinary variables and methods use camelCase, class names use PascalCase, and constants use UPPER_SNAKE_CASE. Java is case sensitive, and a keyword such as class or if cannot be a name.
A block is the code inside a pair of braces. A local variable can be used from its declaration to the end of the block that contains it. Using it after the block ends is a compile error. Keep declarations close to their first use so the scope stays small.
A constant is a variable marked final whose value cannot be reassigned. final double GST_RATE = 0.18; documents that the value should not change. If a later line assigns to GST_RATE, compilation fails.
public class Main {
public static void main(String[] args) {
final double GST_RATE = 0.18;
double price = 250.0;
double tax = price * GST_RATE;
System.out.printf("Tax: %.2f%n", tax);
System.out.printf("Total: %.2f%n", price + tax);
}
}Output
Tax: 45.00 Total: 295.00
3.1.4 Conversion and integer division
Java widens some types automatically. An int can be stored in a long or a double without a cast because the wider type can represent every value. Going the other way needs a cast, which tells the compiler that you accept the possible loss: (int) 9.7 produces 9.
Division follows the types of its operands. 17 / 5 produces 3 because both operands are integers; the fractional part is discarded. 17.0 / 5 produces 3.4. To get a decimal average from integer totals, cast one operand before the division: (double) total / count.
Exact decimal values such as prices are not represented perfectly by float or double. For ordinary practice calculations the difference is small, but avoid testing two floating-point values with ==.
Integer arithmetic also has limits. When an int passes Integer.MAX_VALUE, it wraps around to the minimum value and does not raise an error. Use a long for counts that can grow beyond about 2.1 billion, or check the value before adding to it.
public class Main {
public static void main(String[] args) {
int total = 17;
int people = 5;
System.out.println(total / people);
System.out.println(total % people);
System.out.println((double) total / people);
}
}Output
3 2 3.4
public class Main {
public static void main(String[] args) {
int max = Integer.MAX_VALUE;
int next = max + 1;
long wide = (long) max + 1;
System.out.println(max);
System.out.println(next);
System.out.println(wide);
}
}Output
2147483647 -2147483648 2147483648
3.1.5 Reading and naming values in output
You can print a variable directly, join it to text with +, or format it with printf. Joining converts the value to text for that expression; it does not change the variable's type. int count = 3; followed by System.out.println("Count: " + count); displays Count: 3.
Choose a type before choosing a display format. A price stored as an int number of paise can be shown with a decimal point at print time. A price stored as a double is easier to use in some formulas but can produce long decimal tails. Keep the unit in the variable name, such as pricePaise, so the meaning is clear.
3.1.6 Practice
- Create variables for a book title, page count, price, and whether it is available. Print one line that uses all four.
- Declare a
finaldiscount rate and calculate a sale price. - Calculate the average of three integer marks with a cast, then compare it with the result without the cast.
- Add
1toInteger.MAX_VALUEand explain the printed result. - Rename a variable to
totalCosteverywhere and fix any compiler errors caused by a missed occurrence.
For step 4, store the value in a long as well and compare the two outputs.
