1.3 Variables & Data Types Flashcards
(8 cards)
Q: What are the four types of variables in Java and where are they stored in memory?
A: 1) Instance Variables (Non-static fields): Stored in heap memory with the object. Each object has its own copy. Default values assigned if not initialized.
2) Class Variables (Static fields): Stored in Method Area/Metaspace, shared among all instances. Initialized when class is first loaded.
3) Local Variables: Stored in stack memory within method frames. Must be explicitly initialized before use - no default values.
4) Parameters: Stored in stack memory, passed by value (for primitives) or by reference value (for objects). Scope limited to the method/constructor.
```java
public class VariableExample {
private int instanceVar; // Instance variable (heap)
private static int classVar; // Class variable (metaspace)
public void method(int param) { // Parameter (stack) int localVar = 10; // Local variable (stack) } } ~~~
Explain the 8 primitive data types in Java with their sizes, ranges, and default values
A: Integer Types:
byte: 8 bits, range -128 to 127, default 0
short: 16 bits, range -32,768 to 32,767, default 0
int: 32 bits, range -2³¹ to 2³¹-1 (~-2.1B to 2.1B), default 0
long: 64 bits, range -2⁶³ to 2⁶³-1, default 0L
Floating Point:
float: 32 bits, IEEE 754 single precision, default 0.0f
double: 64 bits, IEEE 754 double precision, default 0.0d
Other:
boolean: JVM dependent size (typically 1 bit in arrays, 32 bits standalone), values true/false, default false
char: 16 bits, Unicode characters 0 to 65,535, default ‘\u0000’
Memory Layout: Primitives stored directly in stack (local) or heap (instance fields), no object overhead.
What’s the fundamental difference between primitive and reference types in Java, including memory allocation and performance implications?
A: Primitive Types:
Store actual values directly in memory
Passed by value (copy of value)
Faster access, no indirection
No methods, stored in stack (local) or heap (fields)
Cannot be null
Reference Types:
Store memory addresses pointing to objects in heap
Passed by reference value (copy of address)
Slower access due to indirection
Have methods, object header overhead (8-16 bytes)
Can be null, subject to garbage collection
```java
// Primitive - value stored directly
int x = 10;
int y = x; // y gets copy of value 10
x = 20; // y still 10
// Reference - address stored
String s1 = new String(“Hello”);
String s2 = s1; // s2 gets copy of address
s1 = “World”; // s2 still points to “Hello” object
~~~
Performance Impact: Primitives are faster for arithmetic, references ena
Explain variable scope rules and lifetime in Java, including shadowing and initialization requirements
A: Scope Rules:
1) Class Level: Accessible throughout class
```java
public class ScopeExample {
private int classVar = 10; // Class scope
public void method() { int localVar = 20; // Method scope { int blockVar = 30; // Block scope // classVar, localVar, blockVar all accessible } // blockVar not accessible here } } ~~~
2) Shadowing: Local variables can shadow instance variables
```java
public class Shadowing {
private int value = 10;
public void method() { int value = 20; // Shadows instance variable System.out.println(value); // Prints 20 System.out.println(this.value); // Prints 10 } } ~~~
3) Initialization Requirements:
Instance/Static variables: Get default values automatically
Local variables: Must be explicitly initialized before use
Final variables: Must be initialized exactly once
Lifetime:
Instance variables: Live with the object (GC eligible when object unreachable)
Static variables: Live for entire JVM lifetime
Local variables: Live within method execution (stack frame)
How do wrapper classes work in Java, and what are the performance implications of autoboxing/unboxing?
A: Wrapper Classes: Object representations of primitives
Boolean, Byte, Short, Integer, Long, Float, Double, Character
Immutable objects with utility methods
Enable primitives in collections, generics
Autoboxing/Unboxing:
```java
// Autoboxing (primitive → wrapper)
Integer obj = 100; // Compiler: Integer.valueOf(100)
// Unboxing (wrapper → primitive)
int val = obj; // Compiler: obj.intValue()
~~~
Integer Caching: JVM caches Integer objects from -128 to 127
Integer a = 100, b = 100; System.out.println(a == b); // true (same cached object) Integer c = 200, d = 200; System.out.println(c == d); // false (different objects) System.out.println(c.equals(d)); // true (value comparison)
Performance Cost: Boxing creates objects (heap allocation), unboxing req
Explain implicit vs explicit type conversion in Java, including promotion rules and potential data loss
A: Implicit Conversion (Widening): Safe, no data loss
javabyte b = 10; int i = b; // byte → int (implicit) long l = i; // int → long (implicit) float f = l; // long → float (implicit, but may lose precision) double d = f; // float → double (implicit)
Promotion Hierarchy: byte → short → int → long → float → double
Explicit Conversion (Narrowing): May lose data, requires cast
javadouble d = 123.456;
int i = (int) d; // 123 (fractional part lost)
byte b = (byte) 300; // 44 (300 % 256, overflow)
Arithmetic Promotion Rules:
byte, short, char promoted to int in arithmetic
If any operand is double → result is double
If any operand is float → result is float
If any operand is long → result is long
Otherwise → result is int
javabyte a = 10, b = 20;
int result = a + b; // Must assign to int, not byte
byte c = (byte)(a + b); // Explicit cast required
Overflow Behavior: Silent wraparound for integer types
javaint max = Integer.MAX_VALUE;
int overflow = max + 1; // -2147483648 (wraps to MIN_VALUE)
Explain the different uses of ‘final’ with variables, including blank finals and effectively final
A: Final Variables: Cannot be reassigned after initialization
1) Final Local Variables:
javapublic void method() {
final int x = 10;
// x = 20; // Compilation error
final List<String> list = new ArrayList<>(); list.add("item"); // OK - modifying object, not reference // list = new ArrayList<>(); // Error - reassigning reference } 2) Final Instance Variables: Must be initialized in constructor or declaration javapublic class FinalExample { private final int value1 = 10; // Initialize at declaration private final int value2; // Blank final public FinalExample(int val) { this.value2 = val; // Must initialize in constructor } } 3) Final Static Variables (Constants): javapublic class Constants { public static final int MAX_SIZE = 100; // Compile-time constant public static final String NAME = "App"; // String literal constant // Runtime constant (not compile-time) public static final long CURRENT_TIME = System.currentTimeMillis(); } 4) Effectively Final (Java 8+): Variables that are not declared final but never reassigned javapublic void method() { int count = 0; // Effectively final Runnable r = () -> { System.out.println(count); // Can access in lambda }; // count++; // Would break effectively final }
Performance Benefits: Final variables can be optimized by compiler/JIT,
How are variables laid out in memory, and what’s the overhead of object creation vs primitives?
**A: Primitive Memory Layout:
**
Stack Frame:
[int local1: 4 bytes][long local2: 8 bytes][reference obj: 4/8 bytes]
Object Memory Layout (64-bit JVM):
Object Header (12-16 bytes):
- Mark Word (8 bytes): hashcode, GC age, lock state
- Class Pointer (4 bytes compressed, 8 uncompressed)
- Array Length (4 bytes for arrays)
+ Instance Data
+ Padding (8-byte alignment)
Example Comparison:
java// Primitive: 4 bytes total
int primitive = 42;
// Wrapper: 16+ bytes total
Integer wrapper = 42;
/*
Object header: 12 bytes
int value: 4 bytes
Total: 16 bytes (minimum)
*/
Array vs Individual Objects:
java// Array of primitives: efficient
int[] intArray = new int[1000]; // 12 bytes header + 4000 bytes data
// Array of wrappers: much larger
Integer[] integerArray = new Integer[1000];
// 12 bytes header + 4000/8000 bytes references + 1000 objects (16 bytes each)