Every program needs to remember things: a user's age, a price, a name, a yes/no answer. In Java, you do this with variables. But Java is strict. Before you store anything, you have to say what kind of thing it is.
That strictness confused me at first. Why can't I just put a decimal number into an int? Why does byte c = a + b give an error? In this post, we'll go through all of this step by step, with small examples you can run yourself.
What is a variable?
A variable is a named box in memory that holds a value. To make one, you write the type, then the name, then (optionally) the value.
int age = 25;
double price = 99.50;
String name = "Mayur";
boolean isStudent = false;
You can also declare first and give the value later:
int score; // declaration
score = 90; // initialization
One rule to remember: a local variable (one inside a method) must be given a value before you use it. Java will not guess a default for you.
int x;
System.out.println(x); // Error: variable x might not have been initialized
Naming rules
- Can contain letters, digits,
_and$ - Cannot start with a digit
- Cannot be a Java keyword (like
classorint) - Is case sensitive (
ageandAgeare different)
By convention, Java uses camelCase for variables, like studentAge or totalPrice.
Constants with final
If a value should never change, add final:
final double PI = 3.14159;
PI = 3.14; // Error: cannot assign a value to final variable
Data types in Java
Java has two groups of data types:
- Primitive types: simple values stored directly (numbers, characters, true/false)
-
Reference types: objects, like
String, arrays and classes
There are exactly 8 primitive types:
| Type | Size | What it stores | Range / example |
|---|---|---|---|
byte |
8 bits | Tiny whole numbers | -128 to 127 |
short |
16 bits | Small whole numbers | -32,768 to 32,767 |
int |
32 bits | Normal whole numbers | about -2.1 billion to 2.1 billion |
long |
64 bits | Very big whole numbers | about -9.2 × 10^18 to 9.2 × 10^18 |
float |
32 bits | Decimals (about 6-7 digits of precision) | 3.14f |
double |
64 bits | Decimals (about 15-16 digits of precision) | 3.14159265358979 |
char |
16 bits | A single character |
'A', '7', '$'
|
boolean |
not fixed | true or false |
true, false
|
Some quick tips:
- Use
intfor whole numbers anddoublefor decimals unless you have a reason not to. - Use
longwhen numbers can go beyond about 2 billion, like timestamps or phone-call counters. -
Stringis not a primitive. It's a class, which is why it starts with a capital S.
Literals: the values you type in code
A literal is a fixed value written directly in your code. In int age = 25;, the 25 is a literal.
int a = 100; // integer literal
long b = 3000000000L; // long literal (note the L)
float c = 3.14f; // float literal (note the f)
double d = 3.14; // double literal (decimals are double by default)
char e = 'A'; // char literal (single quotes)
boolean f = true; // boolean literal
String g = "Hello"; // String literal (double quotes)
Two mistakes beginners make all the time:
long big = 3000000000; // Error: integer number too large
float pi = 3.14; // Error: possible lossy conversion from double to float
The reason: Java treats whole-number literals as int and decimal literals as double by default. So 3000000000 is too big for an int, and 3.14 is a double. Fix them by adding L and f:
long big = 3000000000L;
float pi = 3.14f;
Underscores for readability
Big numbers are hard to read. Java lets you add underscores, and it ignores them:
int million = 1_000_000;
long phone = 98_7654_3210L;
Binary, octal and hex literals
Java lets you write whole numbers in other number systems. You just add a prefix.
| System | Prefix | Digits used | Example | Value in decimal |
|---|---|---|---|---|
| Decimal | none | 0-9 | 25 |
25 |
| Binary | 0b |
0, 1 | 0b1010 |
10 |
| Octal | 0 |
0-7 | 017 |
15 |
| Hex | 0x |
0-9, A-F | 0xFF |
255 |
int dec = 10;
int bin = 0b1010; // binary for 10
int oct = 017; // octal for 15 (careful: leading zero!)
int hex = 0xFF; // hex for 255
System.out.println(dec); // 10
System.out.println(bin); // 10
System.out.println(oct); // 15
System.out.println(hex); // 255
Watch out for the leading zero. 017 is not seventeen. It's octal, so it equals 15. This catches people out.
You can also use underscores in binary and hex to make them easier to read:
int mask = 0b1111_0000; // 240
int color = 0xFF_A5_00; // an orange color code
Why would you ever use binary or hex?
- Binary is great when you care about individual bits, like flags and permissions.
-
Hex is a short way to write binary. One hex digit equals exactly 4 bits, so
0xFFis1111 1111. You'll see hex in color codes, memory addresses and file formats.
Converting numbers to binary and hex strings
Java gives you ready-made methods to see a number in another system:
System.out.println(Integer.toBinaryString(10)); // 1010
System.out.println(Integer.toHexString(255)); // ff
System.out.println(Integer.toOctalString(15)); // 17
And to go the other way, from a string to a number:
int n = Integer.parseInt("1010", 2); // binary string to int -> 10
int m = Integer.parseInt("ff", 16); // hex string to int -> 255
A small surprise with negative numbers
Java stores negative whole numbers using a method called two's complement. You don't need to know the math. Just know this: -1 in an int is all 32 bits set to 1.
System.out.println(Integer.toHexString(-1)); // ffffffff
System.out.println(Integer.toBinaryString(-1)); // 32 ones
Type conversion (widening)
Sometimes you put a smaller type into a bigger one. Java does this for you automatically, with no extra code. This is called type conversion, or widening, or implicit conversion.
Think of pouring water from a small cup into a big jug. Nothing is lost, so Java says yes.
The widening order is:
byte -> short -> int -> long -> float -> double
char -> int
Examples:
int i = 100;
long l = i; // int to long: fine
double d = l; // long to double: fine
System.out.println(l); // 100
System.out.println(d); // 100.0
char also widens to int, which gives you its numeric code:
char c = 'A';
int code = c;
System.out.println(code); // 65
One catch: precision can be lost
Widening from int or long to float is allowed, but a float has limited precision, so big numbers can get slightly changed:
int big = 123456789;
float f = big;
System.out.println(f); // 1.23456792E8
The value is close, but not the same. If you need exact results, use double, or long for whole numbers.
Type casting (narrowing)
Now the other direction. Putting a bigger value into a smaller type is like pouring the jug into a small cup. Some water may spill. Java won't do it silently. You must say it clearly with a cast, by writing the target type in brackets.
double d = 9.99;
int i = (int) d;
System.out.println(i); // 9
Notice that 9.99 became 9, not 10. Casting a decimal to a whole number cuts off the decimal part. It does not round.
System.out.println((int) 9.99); // 9
System.out.println((int) -9.99); // -9
If you want rounding, use Math.round():
System.out.println(Math.round(9.99)); // 10
When the number doesn't fit
When a big whole number is cast into a smaller type, it wraps around. Only the lowest bits are kept.
int big = 130;
byte b = (byte) big;
System.out.println(b); // -126
Why? A byte can only hold -128 to 127. 130 is 3 past 127, so it wraps around to -126. Another example:
long l = 3_000_000_000L;
int x = (int) l;
System.out.println(x); // -1294967296
Java doesn't warn you here. It just gives you the wrong number. That's why you should only cast when you are sure the value fits.
Here's a handy hex example. 0xFF is 255, but a byte can't hold 255:
byte b = (byte) 0xFF;
System.out.println(b); // -1
The bits are 1111 1111, and in a signed byte that means -1.
Type promotion in expressions
This one surprises almost everyone. Look at this code:
byte a = 10;
byte b = 20;
byte c = a + b; // Error: possible lossy conversion from int to byte
Both a and b are bytes, so why does it fail? Because in math expressions, Java first promotes byte, short and char to int. So a + b is an int, and you can't put an int into a byte without a cast.
The fix:
byte c = (byte) (a + b); // 30
The general rules for promotion:
-
byte,shortandcharbecomeintfirst - If one side is
long, the result islong - If one side is
float, the result isfloat - If one side is
double, the result isdouble
int i = 5;
double d = 2.0;
System.out.println(i / d); // 2.5 (int is promoted to double)
System.out.println(5 / 2); // 2 (both are int, so decimals are dropped)
System.out.println(5 / 2.0); // 2.5
The += exception
Compound assignment operators like += quietly add the cast for you:
byte b = 10;
b += 5; // works fine, b is now 15
// b = b + 5; // Error, needs a cast
Common mistakes to avoid
1. Integer overflow. Numbers wrap around at their limit, with no error:
int max = Integer.MAX_VALUE; // 2147483647
System.out.println(max + 1); // -2147483648
2. Decimal surprises. Computers store decimals in binary, so some values are not exact:
System.out.println(0.1 + 0.2); // 0.30000000000000004
For money, use BigDecimal instead of double.
3. Integer division. Dividing two int values gives an int:
System.out.println(1 / 2); // 0, not 0.5
4. Casting char arithmetic. Adding to a char gives an int, so cast it back:
char c = 'A';
char next = (char) (c + 1);
System.out.println(next); // B
5. boolean is special. You can't convert it to or from numbers, with or without a cast. int x = (int) true; will not compile.
Quick recap
- A variable is a named box with a type:
int age = 25; - Java has 8 primitive types:
byte,short,int,long,float,double,char,boolean. - A literal is a value written in code. Use
Lfor long andffor float. - Use
0bfor binary,0xfor hex, and a leading0for octal. Underscores like1_000_000make numbers easier to read. -
Type conversion (widening) is automatic and safe:
inttolongtodouble. -
Type casting (narrowing) is manual and risky:
(int) 9.99gives9, and(byte) 130gives-126. - In expressions,
byte,shortandcharare promoted tointfirst.
Once you understand that every type is just a box of a certain size, the rules start to feel logical. Small box into big box is safe. Big box into small box is your responsibility.
If this helped, or if I missed something, let me know in the comments. I'm still learning too. 🙂
Top comments (0)