// hw hack 1

public class ObjectCreation {
    public static void main(String[] args) {
        // 1. Create two Car objects using 'new'
        Car car1 = new Car("Tesla", 2024);
        Car car2 = new Car("Honda", 2023);

        // 2. Print each car's info
        System.out.println(car1);
        System.out.println(car2);
    }
}

class Car {
    // 1. Declare variables: brand, year
    String brand;
    int year;

    // 2. Create a constructor to set those variables
    public Car(String brand, int year) {
        this.brand = brand;
        this.year = year;
    }

    // 3. Add a method or toString() to display car info
    @Override
    public String toString() {
        return "Car: " + brand + ", Year: " + year;
    }
}

Output:

Car: Tesla, Year: 2024
Car: Honda, Year: 2023

---

### Hw hack 2

---


```python


public class HeapVsStack {
    public static void main(String[] args) {
        // 1. Create a primitive variable (int pages)
        int pages = 300;
        
        // 2. Create another primitive variable that copies it
        int pagesCopy = pages;
        
        // 3. Create a Book object (Book b1 = new Book("Java Basics");)
        Book b1 = new Book("Java Basics");
        
        // 4. Create another Book reference (Book b2 = b1;)
        Book b2 = b1;
        
        // 5. Change the original primitive and the Book title
        pages = 400;
        b1.title = "Advanced Java";
        
        // 6. Print both sets of values to compare behavior
        System.out.println("=== Primitive Variables (Stack) ===");
        System.out.println("Original pages: " + pages);
        System.out.println("Copied pagesCopy: " + pagesCopy);
        System.out.println("Note: pagesCopy is INDEPENDENT\n");
        
        System.out.println("=== Object References (Heap) ===");
        System.out.println("Book b1: " + b1);
        System.out.println("Book b2: " + b2);
        System.out.println("Note: b2 points to SAME object as b1");
    }
}

class Book {
    // 1. Declare variable: String title
    String title;
    
    // 2. Create a constructor to set the title
    public Book(String title) {
        this.title = title;
    }
    
    // 3. Create a toString() to show the title
    @Override
    public String toString() {
        return "Book Title: " + title;
    }
}

Expected Output: === Primitive Variables (Stack) === Original pages: 400 Copied pagesCopy: 300 Note: pagesCopy is INDEPENDENT

=== Object References (Heap) === Book b1: Book Title: Advanced Java Book b2: Book Title: Advanced Java Note: b2 points to SAME object as b1

Ph1

public class MemoryDemo {
    public static void main(String[] args) {
        // Stack variables
        int a = 10;
        int b = a;  // Copy of value
        b = 20;     // Changing b doesn't affect a
        
        System.out.println("Primitives (Stack):");
        System.out.println("a = " + a);  // Still 10
        System.out.println("b = " + b);  // Now it's 20
        
        // Heap variables
        int[] array1 = {1, 2, 3};
        int[] array2 = array1;  // Copy of reference (address)
        array2[0] = 99;         // Changing array2 DOES affect array1
        
        System.out.println("\nArrays (Heap):");
        System.out.println("array1[0] = " + array1[0]);  // Now it's 99!
        System.out.println("array2[0] = " + array2[0]);  // Also 99
    }
}

output

Primitives (Stack): a = 10 b = 20

Arrays (Heap): array1[0] = 99 array2[0] = 99

Question 1: Why does changing b not affect a, but changing array2 affects array1? Changing b does not affect a because primitives like int are stored on the stack and use pass-by-value. When we assign b = a, Java creates a complete copy of the value 10. So a and b are two separate variables with their own memory locations containing independent values. Changing one does not affect the other. However, changing array2 does affect array1 because arrays are objects stored on the heap. When we assign array2 = array1, we’re not copying the actual array - we’re copying the reference (memory address) that points to the array on the heap. Both array1 and array2 now point to the same array object in memory. So when we modify the array through array2[0] = 99, we’re modifying the same underlying object that array1 also points to. Question 2: Describe what’s on the stack vs. the heap for this code. On the Stack:

a - primitive int with value 10 b - primitive int with value 20 array1 - reference variable containing the memory address of the array object array2 - reference variable containing the same memory address as array1

On the Heap:

The actual array object {99, 2, 3} (originally {1, 2, 3}) This single array object is pointed to by both array1 and array2 references

Popcorn Hack #2: Understanding Pass-by-Reference

Ph2

public class PersonDemo {
    static class Person {
        String name;
        int age;
        
        Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    }
    
    public static void haveBirthday(Person p) {
        p.age = p.age + 1;  // Modifying object content
        System.out.println("Inside method: " + p.name + " is now " + p.age);
    }
    
    public static void reassignPerson(Person p) {
        p = new Person("New Person", 99);  // Reassigning reference
        System.out.println("Inside reassign: " + p.name + " is " + p.age);
    }
    
    public static void main(String[] args) {
        Person john = new Person("John", 20);
        
        System.out.println("Before birthday: " + john.name + " is " + john.age);
        haveBirthday(john);
        System.out.println("After birthday: " + john.name + " is " + john.age);
        
        System.out.println("\nBefore reassign: " + john.name + " is " + john.age);
        reassignPerson(john);
        System.out.println("After reassign: " + john.name + " is " + john.age);
    }
}

output

Before birthday: John is 20 Inside method: John is now 21 After birthday: John is 21

Before reassign: John is 21 Inside reassign: New Person is 99 After reassign: John is 21

questions:

Question 1: After haveBirthday(john) is called, what is John’s age? Why? After haveBirthday(john) is called, John’s age is 21. This happens because when we pass john to the method, Java copies the reference (the memory address pointing to the Person object on the heap). The parameter p in the method now points to the same Person object as john. When we execute p.age = p.age + 1, we’re modifying the actual object’s content on the heap that both john and p point to. Therefore, the change is reflected in the original john object after the method returns. Question 2: After reassignPerson(john) is called, what is John’s name and age? Why? After reassignPerson(john) is called, John’s name is still “John” and age is still 21 (unchanged from the previous method call). This happens because inside reassignPerson, when we write p = new Person(“New Person”, 99), we’re creating a completely new Person object on the heap and making the local parameter p point to this new object. However, this only changes where the local parameter p points - it does NOT change where the original john reference points. The original john reference in the main method still points to the original Person object on the heap. When the method ends, the local parameter p is removed from the stack, and the original john reference remains unchanged. Question 3: Explain the difference between modifying an object’s contents vs. reassigning a reference. Modifying an object’s contents:

Changes the data inside the object on the heap Affects all references that point to that object Example: p.age = p.age + 1 changes the age field of the object The original reference still points to the same object, but the object’s state has changed

Reassigning a reference:

Changes which object a reference variable points to Only affects the local reference variable, not the original Creates or points to a different object in memory Example: p = new Person(“New Person”, 99) makes p point to a brand new object The original reference (like john in main) is unaffected and still points to the original object When the method ends, the reassigned reference is discarded and the original remains unchanged