Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Java Data Types and Core Mechanisms

Tech May 8 3

Java categorizes data types into two distinct groups: primitive types and reference types. Primitive types store their values directly on the stack, offering high performance for basic calculations. Reference types, such as classes, interfaces, and arrays, store a memory address on the stack that points to the actual object data residing in the heap.

Primitive Data Types

Java defines eight primitive data types to handle fundamental data values.

Integer Types

Integer types represent whole numbers without fractional parts. They vary in size to optimize memory usage for different scenarios.

TypeSize (Bytes)RangeDefault Value
byte1-128 to 1270
short2-32,768 to 32,7670
int4-2^31 to 2^31-10
long8-2^63 to 2^63-10L

Floating-Point Types

These types handle numbers with fractional components, adhering to the IEEE 754 standard.

TypeSize (Bytes)Default Value
float40.0f
double80.0d

Character and Boolean Types

  • char: Occupies 2 bytes using UTF-16 encoding. Default value is '\u0000'.
  • boolean: Represents logical values (true or false). The JVM typically compiles boolean variables to int type (4 bytes), though in boolean arrays, they occupy 1 byte.

Wrapper Classes and Autoboxing

Each primitive type has a corresponding wrapper class in the java.lang package (e.g., Integer for int, Double for double). These classes allow primitives to be treated as objects, which is necessary for usage in Collections.

Autoboxing is the automatic conversion from a primitive to its corresponding wrapper class, while Unboxing is the reverse process.

Integer wrappedVal = 100; // Autoboxing: calls Integer.valueOf(100)
int rawVal = wrappedVal; // Unboxing: calls wrappedVal.intValue()

Excessive autoboxing/unboxing can degrade performance, so direct primitive usage is preferred for intensive calculations.

The Integer Cache

To optimize memory, Java maintains a cache of Integer instances for values between -128 and 127. When assigning a value within this range, the JVM returns a cached instance rather than creating a new object.

Integer a = 127;
Integer b = 127;
System.out.println(a == b); // true, same cached instance

Integer c = 200;
Integer d = 200;
System.out.println(c == d); // false, new instances created

String Handling

Strings in Java are immutable objects. Once created, their value cannot be modified. Operations that appear to modify a String actually create a new object. This immutability ensures thread safety and allows for String pooling.

String Creation and Memory

Creating a String via a literal (e.g., String s = "text") checks the String Constant Pool first. If the string exists, the reference is reused. If not, a new object is added to the pool.

Using the constructor (e.g., String s = new String("text")) creates a new object in the heap memory distinct from the pool, potentially resulting in two objects if the literal is not already in the pool.

String, StringBuilder, and StringBuffer

  • String: Best for constants. Immutable and thread-safe.
  • StringBuilder: Suitable for single-threaded environments where strings are modified frequently. Not thread-safe but faster.
  • StringBuffer: Thread-safe version of StringBuilder, using synchronized methods. Use in multi-threaded contexts.

Object Class Methods

The java.lang.Object class is the root of the class hierarchy. Every class inherits methods like getClass(), hashCode(), equals(Object obj), clone(), toString(), and finalize(). The wait(), notify(), and notifyAll() methods are essential for thread synchronization and are located in Object because locks in Java are object-based.

Equality and Hashing

== vs equals()

The == operator compares memory addresses for reference types and values for primitives. The equals() method, by default, compares addresses but should be overridden to compare logical content.

Contract between equals() and hashCode()

When overriding equals(), one must also override hashCode(). The contract dictates that if two objects are equal via equals(), they must return the same hash code. This ensures objects behave correctly in hash-based collections like HashMap and HashSet.

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Product product = (Product) o;
    return id == product.id;
}

@Override
public int hashCode() {
    return Objects.hash(id);
}

Common Type Behaviors and Pitfalls

Floating Point Precision

Java treats floating-point literals as double by default. Assigning a double to a float variable without a cast causes a compilation error.

float val = 3.4; // Compilation error
float val = 3.4f; // Correct syntax

Short Arithmetic

Numeric operations involving types smaller than int automatically promote the operands to int. Consequently, the result must be cast back explicitly if assigning to a smaller type.

short num = 10;
num = num + 1; // Error: result is int
num += 1; // OK: implicit cast performed by compound operator

Large Numbers

For numbers exceeding the 64-bit long limit, the java.math.BigInteger class provides arbitrary-precision integers. It handles overflow correctly but with lower performance than primitive types.

Operators and Utilities

Logical AND Operators

The && operator is a short-circuit logical AND; if the left operand is false, the right is not evaluated. The & operator evaluates both operands and can also function as a bitwise AND.

Deep vs. Shallow Copy

A shallow copy duplicates the object's fields, but for reference fields, only the address is copied. A deep copy creates new instances for referenced objects, resulting in a completely independent object graph.

Math.round() Behavior

The Math.round() method implements rounding by adding 0.5 to the value and then flooring it. For example, Math.round(11.5) returns 12, while Math.round(-11.5) returns -11.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.