CSA Blog

Ian Wu

Quiz Questions for APCSA Unit 1

Intro Primitive Types Reference Types Stack and Heap Code Example Quiz

Unit 1: Primitive Types

Question 1

Which of the following is a valid declaration of a variable of type int in Java?
a) int 123variable;
b) int variable123;
c) int variable#123;
d) int variable 123;

Answer: b) int variable123;

// Q1 Hack: Define variables according to Java naming conventions.
// For instance, is it snake_case, camelCase, or PascalCase?

int variable123 = 123;
System.out.println(variable123);

Question 2

What is the value of the following expression in Java: 5 / 2?
a) 2.5
b) 3
c) 2
d) 2.0

Answer: c) 2

// Q2.1 Hack: Show in code difference between integer and floating point division.
System.out.println(5 / 2);
// Q2.2 Hack: Show in code the differnt number types in Java and how they behave.
System.out.println(5.0 / 2.0);
// Behave means definition and assignment.
2
2.5

Question 3

Which primitive type is used to represent a single character in Java?
a) char
b) String
c) int
d) byte

Answer: a) char

// Q3.1 Hack: Show in code all the the non-number Java primitive data types and how they behave.
boolean b = true;
char c = 'c'
// Q3.2 Hack: Show in code the String data type and how it behaves.
String string = 'string'

Question 4

Answer the following questions based on the code cell:

  • a) What kind of types are person1 and person2?
  • Answer: Person
  • b) Do person1 and person3 point to the same value in memory?
  • Answer: no
  • c) Is the integer “number” stored in the heap or in the stack?
  • Answer: heap
  • d) Is the value that “person1” points to stored in the heap or in the stack?
  • Answer: stack
public class Person {
    String name;
    int age;
    int height;
    String job;

    public Person(String name, int age, int height, String job) {
        this.name = name;
        this.age = age;
        this.height = height;
        this.job = job;
    }
}

public static void main(String[] args) {
    Person person1 = new Person("Carl", 25, 165, "Construction Worker");
    Person person2 = new Person("Adam", 29, 160, "Truck Driver");
    Person person3 = person1;
    int number = 16;
    System.out.println(number);
}
main(null); // This is required in Jupiter Notebook to run the main method.

Question 5

(a) Define primitive types and reference types in Java. The application is for banking, where you need to represent customer information.

(b) Add comments for primitive types and reference types. In terms of memory allocation, discuss concepts like instance, stack, and heap where it adds value.

(c) To assist in requirements, here are some required elements:

  • Create multiple customers from the public class Account.
  • Consider key class variables that a Bank may require: name, balance, accountNumber.
  • Create a two argument constructor using name and balance.
  • Consider in constructor how you will create a unique account number using static int lastAccountNumber
  • Define a method calculateInterest that works with getting and setting double balance using private static double interestRate.
public class Account {
    String name;
    double balance;
    int accountNumber;
    static int lastAccountNumber = 0;

    Account(String n, double b) {
        this.name = n;
        this.balance = b;
        this.accountNumber = lastAccountNumber;
        lastAccountNumber += 1;
    }

    private double interestRate(int rate) {
        this.balance = this.balance * (1 + rate * 0.01);
        return this.balance;
    }
}

Unit 1 - Primitive & Reference Types Examples

Intro Primitive Types Reference Types Stack and Heap Code Example Quiz

Primitive Data Types

In your personal blog you should have a comprehensive example that help you recall Primitive Data Types.

All Primitives Demo

The class PrivitiveTypes shows an assignment and output of each of the Java primitive types.

public class PrimitiveTypes {
    public static void main(String[] args) {
        // Declare and initialize variables of different primitive types
        byte myByte = 10; // 8-bit integer
        short myShort = 32000; // 16-bit integer
        int myInt = 123456; // 32-bit integer
        long myLong = 123456789L; // 64-bit integer

        float myFloat = 3.14f; // 32-bit floating-point
        double myDouble = 3.14159; // 64-bit floating-point

        char myChar = 'A'; // 16-bit Unicode character
        boolean myBoolean = true; // true or false

        // Perform some operations
        int sum = myInt + 1000;
        float division = myFloat / 2;
        boolean isEqual = myByte == 10;

        // Print the results
        System.out.println("Byte value: " + myByte);
        System.out.println("Short value: " + myShort);
        System.out.println("Int value: " + myInt);
        System.out.println("Long value: " + myLong);
        System.out.println("Float value: " + myFloat);
        System.out.println("Double value: " + myDouble);
        System.out.println("Char value: " + myChar);
        System.out.println("Boolean value: " + myBoolean);

        System.out.println("Sum of myInt and 1000: " + sum);
        System.out.println("Division of myFloat by 2: " + division);
        System.out.println("Is myByte equal to 10? " + isEqual);
    }
}

PrimitiveTypes.main(null);

Overflow and Underflow

In Java, by nature of using strongly typed definitions, the developer needs to be aware of the limits of numeric data. The class OverFlow demonstrates the constraints of int and double addition, and introduces the terms overflow and underflow.

import java.text.DecimalFormat;

public class OverFlow {
    public static void main(String[] args) {
        DecimalFormat df = new DecimalFormat("#,###");
        DecimalFormat dfDouble = new DecimalFormat("#,###.################");

        System.out.println("Max Integer: " + Integer.MAX_VALUE);
        System.out.println("Min Integer: " + Integer.MIN_VALUE);
        System.out.println("Max Double: " + dfDouble.format(Double.MAX_VALUE));
        System.out.println("Min Double: " + Double.MIN_VALUE);

        // Integer Show Overflow
        int i = Integer.MAX_VALUE;
        i++;
        System.out.println("Overflow error (flips negative), Integer Max + 1: " + df.format(i));
        // Integer Show Underflow
        int j = Integer.MIN_VALUE;
        j--;
        System.out.println("Underflow error (flips positive), Integer Min - 1: " + df.format(j));

        // Double Show Double Handling Integer.MAX_Value + 1
        double d = Integer.MAX_VALUE + 1.0;
        System.out.println("Double Handling Integer Max + 1: " + dfDouble.format(d));
        // Double Show Double Handling Integer.MIN_Value - 1
        double e = Integer.MIN_VALUE - 1.0;
        System.out.println("Double Handling Integer Min - 1: " + dfDouble.format(e));

        // Integer Max + Min
        int k = Integer.MAX_VALUE + Integer.MIN_VALUE;
        System.out.println("Integer Max + Min, shows Min is greater: " + df.format(k));
    }
}

OverFlow.main(null);

Casting

In some numeric operations, it may be more logical to change the type.

  1. Widening: This is the process of converting a smaller data type to a larger data type. For example, in division, where two integers (int) produce a real number (double).
  2. Narrowing: This is the process of converting a larger data type to a smaller data type, such as truncating a double to an int.
public class Casting {
    public static void main(String[] args) {

        // Implicit casting (widening)
        int num1 = 5;
        int num2 = 2;
        System.out.println("Integer math: " + num1 / num2);
        // to widen one or the other must be a double
        System.out.println("Cast math to Double: " + (double) num1 / num2);

        // Explicit casting (narrowing)
        double rounding = 0.1;
        double test1 = 90.0;
        double test2 = 89.5;
        double test3 = 90.4;
        double average = (test1 + test2 + test3) / 3;
        // to narrow all must be casted to int
        double averageTruncated = (int) average;
        // to simplify narrow, cast after all of the math operations
        double averageRounded = (int) (average + rounding);
        System.out.println("Double average: " + average);
        System.out.println("Cast average to int, result is truncated: " + averageTruncated);
        System.out.println("Cast average to int, result is truncated after rounding adjust: " + averageRounded);
    }
}
Casting.main(null);

ArrayLists and Wrapper Classes

In the context of College Board, this Teacher believes that ArrayLists and Wrapper classes go together in learning and discussion.

A key use of Wrapper Classes is with ArrayList, which only accepts reference types. This allows primitives to be used within ArrayList through their Wrapper Classes, enabling dynamic resizing and access to built-in methods like streams for sum and average calculations.

Additionally, Wrapper Classes in Java allow primitive types to behave like reference types, providing useful methods and constants such as MIN_VALUE and MAX_VALUE. They enable transformations between primitives and strings, like converting an int to a String and vice versa.

In the following examples, the first example goes through the language elements of Wrapper Classes culminating with ArrayList. The second example puts these elements together in a more practical application, demonstrating the value of using Wrapper Classes and ArrayList to simplify code and perform calculations.

public class StudentWrapper {
    int age; // Primitive data type, int
    Integer ageWrapper; // Wrapper class for Integer
    int[] testScores; // Array of type int
    Integer[] testScoresWrapper; // Array of Wrapper class for Integer 
    ArrayList<Integer> testScoresList; // ArrayList of Wrapper class for Integer, int is not allowed
    double averageScore; // Primitive data type, double for calculated average

    // Method to calculate average score from an array of integers
    public static double calculateAverage(int[] scores) {
        int total = 0;
        // Enhanced for loop to calculate total
        for (int score : scores) {
            total += score;
        }
        // Cast to widden to double
        return (double) total / scores.length;
    }

    // Method to convert int array to Integer array
    public static Integer[] convertToIntegerArray(int[] scores) {
        // Allocate heap memory for Integer array based on length of int array, fixed size
        Integer[] integerArray = new Integer[scores.length];
        // Conventional loop to set elements from int array to Integer array
        for (int i = 0; i < scores.length; i++) {
            // Set values in an Array only work with an index
            integerArray[i] = scores[i];
        }
        return integerArray;
    }

    // Method to convert Integer array to ArrayList
    public static ArrayList<Integer> convertToArrayList(Integer[] scores) {
        // Allocate heap memory for ArrayList, dynamic size
        ArrayList<Integer> arrayList = new ArrayList<>();
        // Enhanced for loop to add elements from Integer array to ArrayList
        for (Integer score : scores) {
            // Add values dynamically to an ArrayList 
            arrayList.add(score);
        }
        return arrayList;
    }

    public static void main(String[] args) {
        // Simulate receiving input data as strings, e.g., from user input 
        String ageString = "17";
        String testScoresString = "85, 90, 78, 92";

        // Create an instance of Student class, in heap memory
        StudentWrapper student = new StudentWrapper();

        // Set and convert age using wrapper class method (static)
        student.ageWrapper = Integer.parseInt(ageString);
        student.age = student.ageWrapper;
        System.out.println("Student Age: " + student.age);
        System.out.println("Student Age (Wrapper): " + student.ageWrapper);

        // Set test scores from input string, notice String.split() method
        String[] testScoresArray = testScoresString.split(", ");
        // Allocate heap memory for test scores array based on length of input string
        student.testScores = new int[testScoresArray.length];
        // Conventional loop to set elements from input string to test scores array
        for (int i = 0; i < testScoresArray.length; i++) {
            // Set values in an Array only work with an index, requiring conventional loop
            // Integer.parseInt() method converts
            student.testScores[i] = Integer.parseInt(testScoresArray[i]);
        }
        // java.util.Arrays.toString() method converts array to string for printing in one line
        System.out.println("Student Test Scores: " + java.util.Arrays.toString(student.testScores));

        // Calculate average score, using class Student defined static method
        student.averageScore = calculateAverage(student.testScores);
        System.out.println("Student Average Score: " + student.averageScore);

        // Convert int array to Integer array, using class Student defined static method
        student.testScoresWrapper = convertToIntegerArray(student.testScores);
        System.out.println("Student Test Scores (Wrapper): " + java.util.Arrays.toString(student.testScoresWrapper));

        // Convert Integer array to ArrayList, using class Student defined static method
        student.testScoresList = convertToArrayList(student.testScoresWrapper);
        System.out.println("Student Test Scores (ArrayList): " + student.testScoresList);

        // Add a new test score ArrayList 
        student.testScoresList.add(88); // Notice dynmic sizing of an ArrayList
        System.out.println("Updated Student Test Scores (ArrayList): " + student.testScoresList);
        System.out.println("Updated Student Average Score (ArrayList): " + student.testScoresList.stream().mapToInt(Integer::intValue).average().orElse(0.0));

        // Convert ArrayList back to int array for recalculating average, using original claculateAverage method
        student.testScores = student.testScoresList.stream().mapToInt(Integer::intValue).toArray();
        student.averageScore = calculateAverage(student.testScores);
        System.out.println("Updated Student Average Score: " + student.averageScore);

    }
}
StudentWrapper.main(null);
import java.util.ArrayList;
import java.util.Arrays;

public class StudentGradeCalculator {
    int age; // Primitive data type, int
    ArrayList<Integer> testScoresList; // ArrayList of Wrapper class for Integer

    // Constructor to initialize age and test scores
    public StudentGradeCalculator(int age, String testScoresString) {
        this.age = age;
        this.testScoresList = new ArrayList<>();

        // Split input string and convert to integer values
        String[] testScoresArray = testScoresString.split(", ");

        // Add integer values to ArrayList
        for (String score : testScoresArray) {
            // Add integer values to ArrayList, if not an integer, set to minimum of 55 percent
            this.testScoresList.add(score.matches("\\d+") ? Integer.parseInt(score) : 55);
        }
    }

    // Method to calculate average score using College Board method 
    public double calculateAverage() {
        int total = 0;
        for (int score : testScoresList) {
            total += score;
        }
        return (double) total / testScoresList.size();
    }

    // Method to calculate average score using Java 8 Stream API
    public double calculateAverageStream() {
        return testScoresList.stream().mapToInt(Integer::intValue).average().orElse(0.0);
    }

    // Override toString method to display student details
    @Override
    public String toString() {
        return "Age: " + age + ", Test Scores: " + testScoresList + ", Average Score: " + calculateAverage() + ", Average Score (Stream): " + calculateAverageStream();
    }

    public static void main(String[] args) {
        // Initialize students with ages and test scores
        StudentGradeCalculator john = new StudentGradeCalculator(17, "85, A, 78, 92");
        StudentGradeCalculator anita = new StudentGradeCalculator(16, "88, 86, 90, 85");
        StudentGradeCalculator jamal = new StudentGradeCalculator(18, "92, 81, 79, 95");

        // Output student details
        System.out.println("John's Details: " + john);
        System.out.println("Anita's Details: " + anita);
        System.out.println("Jamal's Details: " + jamal);
    }
}
StudentGradeCalculator.main(null);

Refrence Types Examples

In your Personal Blog you should create a class that captures all the key reference type in Java that are required for College Board.

Class Reference Type

The class Person illustrates the basics of a Java class. When a Person person object is created, it is stored on the heap, and it contains data for the name and age. This object is a reference type, meaning that the variable person holds a reference (or address) to the memory location where the actual Person object is stored, rather than the object itself.

Key Points:

  1. Instance Variables: Attributes of the class that hold data.
  2. Constructor: Initializes the instance variables.
  3. Methods: Define behaviors for the class.
  4. Reference Type: The variable holds a reference to the memory location of the object on the heap.
public class Person {
    // Fields (attributes) of the Person class
    String name;
    int age;

    // Constructor to initialize the Person object
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Method to introduce the person
    void introduce() {
        System.out.println("Hello, my name is " + name + " and I am " + age + " years old.");
    }

    // Method to simulate having a birthday
    void haveBirthday() {
        age++;
        System.out.println("Happy Birthday! I am now " + age + " years old.");
    }

    public static void main(String[] args) {
        // Create an instance of the Person class (a custom reference type)
        Person person = new Person("John", 25);

        // Call methods on the Person object
        person.introduce();
        person.haveBirthday();
    }
}
Person.main(null);

Array Reference Types

The class ArrayReferenceTypes demonstrates the usage of arrays, which are reference types in Java. This class includes examples of a single-dimensional array of integers (int[]) and a two-dimensional array of strings (String[][]). Both arrays are initialized with hard-coded literals.

Key Points:

  1. Single-Dimensional Array: Demonstrates the use of int[] with hard-coded literals.
  2. Two-Dimensional Array: Demonstrates the use of String[][] with hard-coded literals.
  3. Enhanced For-Loop: Used for iterating over the single-dimensional array.
  4. Classic For-Loop: Used for iterating over the two-dimensional array with i and j indices.
  5. Reference Type: Arrays are reference types, meaning the variable holds a reference to the memory location of the array data.
public class ArrayReferenceTypes {
    public static void main(String[] args) {
        // Create and initialize an array of integers
        int[] numbers = {1, 2, 3, 4, 5};

        // Print the contents of the integer array
        System.out.println("Array contents:");
        for (int number : numbers) {
            System.out.println(number);
        }

        // Create and initialize a 2D array of strings
        String[][] matrix = {
            {"A1", "B1", "C1"},
            {"A2", "B2", "C2"},
            {"A3", "B3", "C3"}
        };

        // Print the contents of the 2D string array
        System.out.println("2D array contents:");
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                System.out.print(matrix[i][j] + " ");
            }
            System.out.println();
        }
    }
}
ArrayReferenceTypes.main(null);

Enums (Project-based Learning Topic)

Enums in Java, similar to those in the ‘C’ language, are a special reference data type that enables a variable to be a set of predefined constants. They are useful for representing fixed sets of related constants, such as days of the week, months of the year, etc.

Enums can be used in assignments, conditional checks (if, switch), and iterations (for, while), making them versatile for various programming scenarios.

Similarity to Classes:

  • Fields and Methods: Enums can have fields and methods just like classes.
  • Constructors: Enums can have constructor-like methods to initialize their fields, similar to class constructors.
  • Encapsulation: Enums encapsulate data (fields) and behavior (methods) just like classes.

In this example, we are setting constants and descriptions to represent educational units and questions for the APCSA curriculum.

public class APCSACurriculum { 
    // Enum to represent educational units
    enum Units {
        // Each enum constant is initialized with a description and is associated with a getter method
        UNIT_1("Primitive Types—You’ll learn the fundamentals of Java, a programming language, as well as other foundational concepts for coding."),
        UNIT_2("Using Objects—You’ll explore reference data as a way to represent real-world objects in a digital world and discover methods to perform more complex operations."),
        UNIT_3("Boolean Expressions and if Statements—You’ll delve into the building blocks of algorithms and focus on using conditional statements to solve problems and control results."),
        UNIT_4("Iteration—You’ll learn about iteration, another building block of algorithms that are for repetition."),
        UNIT_5("Writing Classes—You’ll explore how real-world interactions can be expressed digitally by organizing behaviors and attributes into classes, and you’ll examine the legal and ethical implications of computer programming."),
        UNIT_6("Array—You’ll learn techniques and standard algorithms to work with collections of related data, known as data structures."),
        UNIT_7("ArrayList—You’ll delve deeper into data sets, exploring ArrayList objects for larger amounts of data, as well as the privacy concerns related to personal data storage."),
        UNIT_8("2D Array—Now that you’ve explored 1D arrays, you’ll branch out into 2D arrays and experiment with data sets represented in a table."),
        UNIT_9("Inheritance—You’ll learn how to manipulate programming without altering existing code by using subclasses to create a hierarchy."),
        UNIT_10("Recursion—You’ll work on solving larger problems by solving smaller, simpler versions of the same problem using recursive methods.");

        // Private field to hold the description of each unit
        private final String description;

        // Constructor-like method to initialize the description field
        Units(String description) {
            this.description = description;
        }

        // Getter method to retrieve the description
        public String getDescription() {
            return description;
        }
    }

    // Enum to represent Free Response Questions (FRQs)
    enum FRQs {
        // Each enum constant is initialized with a description and is associated with a getter method
        QUESTION_1("Methods and Control Structures—You’ll be asked to write program code to create objects of a class and call methods, and satisfy method specifications using expressions, conditional statements, and iterative statements."),
        QUESTION_2("Classes—You’ll be asked to write program code to define a new type by creating a class and satisfy method specifications using expressions, conditional statements, and iterative statements."),
        QUESTION_3("Array/ArrayList—You’ll be asked to write program code to satisfy method specifications and create, traverse, and manipulate elements in 1D array or ArrayList objects."),
        QUESTION_4("2D Array—You’ll be asked to write program code to satisfy method specifications and create, traverse, and manipulate elements in 2D array objects.");

        // Private field to hold the description of each question
        private final String description;

        // Constructor-like method to initialize the description field
        FRQs(String description) {
            this.description = description;
        }

        // Getter method to retrieve the description
        public String getDescription() {
            return description;
        }
    }

    public static void main(String[] args) {
        System.out.println("AP Computer Science A Curriculum and FRQ Topics:");

        // Accessing enum values for Units
        System.out.println("Units:");
        for (Units unit : Units.values()) {
            System.out.println("\t" + unit + ": " + unit.getDescription());
        }

        System.out.println("FRQ types:");
        // Accessing enum values for FRQs
        for (FRQs frq : FRQs.values()) {
            System.out.println("\t" + frq + ": " + frq.getDescription());
        }
    }
}
APCSACurriculum.main(null);

Unit 1 - Stack & Heap Memory

Intro Primitive Types Reference Types Stack and Heap Code Example Quiz

Memory Allocation: Stack and Heap

In Java, memory allocation for variables occurs in two main areas: the stack and the heap.

Stack Memory

Stack memory is a region of memory that stores temporary variables created by each function (including the main function). It is managed by the execution stack and follows a last-in-first-out (LIFO) order.

  • Stores primitive data types and references to objects.
  • Memory is allocated in a last-in-first-out (LIFO) manner.
  • Each thread has its own stack, ensuring thread safety.

Example:

int number = 100; // Stored in the stack

Stack Variables Tips

College Board often asks questions about stack usage.

  • Since primitives are always on the stack, they point directly to the content. This is best observed in a debugger.
  • A reference type contains an address to the content on the stack.
  • Passing a stack variable to a method creates a copy of the content of that variable.
  • Changes to the content of a primitive type will not return back to the method caller; this is called pass-by-value.
  • Since a reference type contains an address to the heap, the reference is copied when calling a method. This is called pass-by-reference, as data type changes are then performed according to the reference.

Heap Memory

Heap memory is a region of memory used for dynamic memory allocation. It is managed by Java’s memory management system.

  • Used for storing objects and arrays.
  • Shared among all threads, requiring synchronization for thread safety.
  • Managed by the garbage collector, which reclaims memory when objects are no longer in use.

Example:

// Long form showing new
String message = new String("Hello");

// Short form Java performs new find the scenes
String message = "Hello";

Heap Variables Tips

  • Heap variables stay alive as long as a stack variable points to them.
  • By nature, all reference data types refer to an address on the stack but change content on the heap.
  • Objects created in the heap are globally accessible and can be shared among multiple methods, this creates concurrency issues when programming.
  • The garbage collector automatically reclaims memory from objects that are no longer referenced, helping to prevent memory leaks.

Popcorn Hack: literal vs input

A value that is directly in code is called a literal. Often developers will say this value is hard coded value.

  • Literal: In source code representation of a fixed value, e.g. 17. A hard coded number.
  • String Literal: In sourced code set of letters within quotes, e.g. “blue”, A hard coded string.

Q1: Define some literal data. Q2: Obtain that data from input versus hard coded.

// Hard code literal values

int literalAge = 17;
String literalFavoriteColor = "blue";
// Input your age
Scanner scanObj = new Scanner(System.in);  // Create a Scanner object
System.out.println("Enter age");
int inputAge = scanObj.nextInt();  // Read user input
System.out.println("My Age is: " + inputAge);  // Output user input

Popcorn Hack: pass-by-value, pass-by-reference

For College Articulation in Data Structures and College Board AP Exam you will need to understand pass-by-value and pass-br-reference.

  • If you pass primitives to a method they WILL NOT change the callers value.
  • If you wrap the primitive in a refrence type, in the example below using a class, then you can change the original.

Q1: Describe approache difference between IntByValue and IntByReference. IntByValue takes a primitive in as input, and therefore the original value is unchanged after operation. IntByReference uses a reference type and therefore the value is modified during the function call. Q2: Try to make a changeInt method that change would persist after it is called. Be careful, this will require a change in approach.

public class IntByValue {
    
    public static void changeInt(int n) {
        System.out.println("In changeInt method");
        System.out.println("\tBefore n += 10: n = " + n); // prints 5
        n = n += 10;
        System.out.println("\tAfter n += 10: n = " + n); // prints 10
    }

    public static void main(String[] args) {
        int n = 5;
        System.out.println("Main method before changeInt(n): n = " + n); // prints 5
        changeInt(n);
        System.out.println("Main method after changeInt(n): n = " + n); // still prints 5
    }
}
IntByValue.main(null);
Main method before changeInt(n): n = 5
In changeInt method
	Before n += 10: n = 5
	After n += 10: n = 15
Main method after changeInt(n): n = 5
public class IntByReference {
    private int value;

    public IntByReference(Integer value) {
        this.value = value;
    }

    public String toString() {
        return (String.format("%d", this.value));
    }

    public void swapToLowHighOrder(IntByReference i) {
        if (this.value > i.value) {
            int tmp = this.value;
            this.value = i.value;
            i.value = tmp;
        }
    }

    public static void swapper(int n0, int n1) {
        IntByReference a = new IntByReference(n0);
        IntByReference b = new IntByReference(n1);
        System.out.println("Before: " + a + " " + b);
        a.swapToLowHighOrder(b);  // conditionally build swap method to change values of a, b
        System.out.println("After: " + a + " " + b);
        System.out.println();
    }

    public static void main(String[] ags) {
        IntByReference.swapper(21, 16);
        IntByReference.swapper(16, 21);
        IntByReference.swapper(16, -1);
    }

}
IntByReference.main(null);
Before: 21 16
After: 16 21

Before: 16 21
After: 16 21

Before: 16 -1
After: -1 16
class IntWrapper {
    public int value;

    public IntWrapper(int value) {
        this.value = value;
    }
}

public static void changeInt(IntWrapper wrapper, int newValue) {
    wrapper.value = newValue;
}

IntWrapper myInt = new IntWrapper(10);
System.out.println("Before: " + myInt.value);

changeInt(myInt, 20);
System.out.println("After: " + myInt.value);
Before: 10
After: 20