Data Types in Java

Before discussing Data Structures it is important to review Data Types and the AP Methods and Control Structures topic. To begin this discussion I asked ChatGPT, "what are Java data types" and was really happy with the answer ...

  • In Java, data types are used to define the type of data that a variable can hold. There are two main categories of data types in Java: primitive data types and reference data types.

    • Primitive data types:

      • byte: 8-bit signed integer (-128 to 127)
      • short: 16-bit signed integer (-32,768 to 32,767)
      • int: 32-bit signed integer (-2,147,483,648 to 2,147,483,647)
      • long: 64-bit signed integer (-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807)
      • float: 32-bit floating-point number (1.4e-45 to 3.4e+38)
      • double: 64-bit floating-point number (4.9e-324 to 1.8e+308)
      • boolean: true or false
      • char: 16-bit Unicode character (0 to 65,535)
    • Reference data types:

      • Objects: instances of classes
      • Arrays: a collection of data of the same type.
  • Primitive data types are stored directly in memory, whereas reference data types are stored as a reference to a memory location where the actual data is stored.

This led to follow up question, "what about Java Wrapper data types" and this answer even corrected my language to say wrapper classes ...

  • Java Wrapper classes are classes that provide a way to use primitive data types as objects. They are called wrapper classes because they "wrap" the primitive data types into an object.

    • There are eight wrapper classes in Java, each corresponding to one of the primitive data types:
    • Byte: represents a byte value
    • Short: represents a short value
    • Integer: represents an int value
    • Long: represents a long value
    • Float: represents a float value
    • Double: represents a double value
    • Boolean: represents a boolean value
    • Character: represents a char value
  • Wrapper classes are often used when working with collections or other APIs that require objects rather than primitive data types. They also provide methods for converting between primitive data types and their corresponding object types, as well as methods for performing operations on the wrapped values.

As an addendum to ChatGPT definition of a Wrapper Class, it is critical to understand assignments. When you assign a value to a wrapper class object, Java automatically creates a new instance of the wrapper class and assigns the value to it. Thus, every assignment is a new object!!! This process is called Auto-boxing. For example, to assign an integer value to an Integer object ...

// Both of these create new objects
Integer n = 5; // Auto-boxing, Integer n = new Integer(5);
n += 5;  // Auto-boxing, Integer n = new Integer(n + 5);

For clarification, for my students I asked, "define reference data types". This added a purpose to the name reference ...

  • In Java, reference data types are data types that hold references or memory addresses that point to objects. These data types do not actually contain the data they refer to, but instead, store a reference to the memory location where the data is stored.

  • Reference data types are used to store complex data structures such as objects and arrays. Objects are instances of classes that encapsulate data and behavior, while arrays are collections of data of the same type.

  • When a reference data type variable is declared, memory is allocated for the reference variable itself, but not for the object or array it refers to. Memory for the object or array is allocated separately using the "new" keyword, and the reference variable is assigned the memory address of the object or array.

  • *Reference data types are passed by reference, which means that when a reference variable is passed as a method argument, the method receives a copy of the reference, but both the original reference and the copy point to the same object in memory. This allows methods to modify the object or array that the reference points to***.

For completeness on this discussion I asked, "define primitive data types" ...

  • In Java, primitive data types are the basic building blocks of data that can hold a single value of a specific type. They are called "primitive" because they are not objects and do not have any methods or properties like objects do.

  • There are eight primitive data types in Java:

    • byte: 8-bit signed integer (-128 to 127)
    • short: 16-bit signed integer (-32,768 to 32,767)
    • int: 32-bit signed integer (-2,147,483,648 to 2,147,483,647)
    • long: 64-bit signed integer (-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807)
    • float: 32-bit floating-point number
    • double: 64-bit floating-point number
    • boolean: true or false
    • char: 16-bit Unicode character (0 to 65,535)
  • Primitive data types are stored directly in memory and are passed by value, which means that when a primitive data type variable is passed as a method argument, the method receives a copy of the value, not a reference to the original variable. This also means that modifying the value of a primitive data type variable inside a method does not affect the original value of the variable outside the method.

Data Types behaviors

The AP exam will have questions about "primitives", "wrapper classes", and "reference" and how they work in relation to "pass by value", and "pass by reference".

A primitive Data Type "int" showing pass by value

The primitive int data type. This code shows behavior as it is passed to method and the value is changed.

public class PassByValue {
    
    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
    }
}
PassByValue.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

The wrapper Integer class (by value or reference?)

An object wrapper class Integer for the primitive int data type. TWhen an Integer object is passed as a parameter to a method, the object is passed as a class. How does assignment behave in this example? By value or by reference? Observe the hashCode(), we will compare it to the next example.

public class PassByValueOrReference {
    
    public static void changeInteger(Integer n) {
        System.out.println("In changeInteger method");
        System.out.println("\tBefore change: n = " + 
                            n + // prints 5
                            " hash code = " + 
                            n.hashCode()); 

        n += 10;  // behind the scenes, this is:  n = new Integer(n+10)
        
        System.out.println("\tAfter change: n = " + 
                            n + // prints 15
                            " hash code = " + 
                            n.hashCode()); 
    }

    public static void main(String[] args) {
        Integer n = 5;
        System.out.println("Main method before changeInteger(n): n = " + 
                            n + // prints 5
                            " hash code = " + 
                            n.hashCode()); 

        changeInteger(n);
        
        System.out.println("Main method after changeInteger(n): n = " + 
                            n +  // now prints 15
                            " hash code = " + 
                            n.hashCode());     
}
PassByValueOrReference.main(null);
Main method before changeInteger(n): n = 5
In changeInteger method
	Before change: n = 5 hash code = 5
	After change: n = 15 hash code = 15
Main method after changeInteger(n): n = 5

The class AtomicInteger

A class AtomicInteger for the primitive int data type. When an AtomicInteger object is passed as a parameter to a method, the object is passed as a Java class. The only way to change the data with a class is to use the setters and getters of the Object. The hashCode() show a unique object number and it maintains consistency through as the referenced data being changed by the setter.

import java.util.concurrent.atomic.AtomicInteger;

public class PassByReference {
    
    public static void changeAtomicInteger(AtomicInteger n) {
        System.out.println("In changeAtomicInteger method");
        System.out.println("\tBefore change: n = " + 
                            n + // prints 5
                            " hash code = " + 
                            n.hashCode()); 
        n.set(n.get() + 10);  // at this point, we are clearly working with reference data type
        System.out.println("\tAfter change: n = " + 
                            n + // prints 15
                            " hash code = " + 
                            n.hashCode()); 
}

    public static void main(String[] args) {
        AtomicInteger n = new AtomicInteger(5); // unlike conventional wrapper class, this requires new
        System.out.println("Main method before changeAtomicInteger(n): n = " + 
                            n + // prints 5
                            " hash code = " + 
                            n.hashCode()); 
        changeAtomicInteger(n);
        System.out.println("Main method after changeAtomicInteger(n): n = " + 
                            n +  // now prints 15
                            " hash code = " + 
                            n.hashCode()); 
    }
}
PassByReference.main(null);
Main method before changeAtomicInteger(n): n = 5 hash code = 747820531
In changeAtomicInteger method
	Before change: n = 5 hash code = 747820531
	After change: n = 15 hash code = 747820531
Main method after changeAtomicInteger(n): n = 15 hash code = 747820531

Methods and Control Structures in Java 2022 AP Video on Method and Control

Authority on testing should be considered AP Classroom. There are a lot of sources out there, some drift according to their bias, just like me drifting toward PBL. The video link above goes over test and format, there could be minor changes with electronic vs paper format. Though, this video is call Methods and Control Structures it covers a lot of fundamentals on testing.

  • AP Test Format

  • AP FRQ Types

Hacks

Much of this trimester, the Teacher will be introducing topics and then asking the student to do details explorations on these topic according to their need or interest. This week first the Teacher will expect a pull request related to assignment options between Team and Teacher. The request will require an ipynb file that is formed like a lesson and exploration into the topic. Below are some hack options. They are expected to be done as individuals and reviewed by team for errors and quality. Do not provide deliverables where Teacher is first reviewer. I will not announce on this item if it will be silent or live review; likely some combination.

  • Early seed award

    • Write a sample binary addition 1 + 1 = 10
    • Have Java Code cell on screen at start of lecture
    • Don't tell anyone
  • Start with some small code excercises

    • Write a Jupyter notebook code example on the following primitive types with a code example (4 to 5 lines), preference would be using array and methods like substring and random as applicable: int, double, boolean, char.
    • Now convert each of the examples to corresponding Wrapper classes, using arrays.
    • Expression of these in Class or PBL forms is an option. But the review must be easy for me to see work.
  • Explore Teacher Code: [methodDataTypes]https://github.com/nighthawkcoders/spring_portfolio/tree/master/src/main/java/com/nighthawk/hacks/methodsDataTypes. I would like a Jupyter Notebook that goes over key concepts in Teacher code and uses background from ChatGPT and from AP Classroom.
    • Answer what are Methods and Control Structures
    • Explore AP FRQ that teaches us about Methods and Control Structures FRQ
    • Look at Diverse Arrays, Matrix in Teacher code and see if you think this is Methods and Control structures.
    • Look at Diverse Arrays,Matrix in Teacher code an see if you thing this fits Data Types.
    • Math.random is covered in Number, this Teacher code associated with random is critical knowledge when taking the AP Exam. Random numbers in range like 7 to 9 is very important.
    • Review DoNothingByValue, what is key knowledge here?
    • Review IntByReference, what is key knowledge here?
    • Review Menu code. Try, Catch, Runnable are used to control program execution. See if there is a way to get this to work in Jupyter Notebooks.
    • Define "Method and Control Structures". To the Teacher, the Menu Code has the most work of methodDataTypes files that is related to the "Methods and Control Structures" topic. Such exploration would begin by asking "describe Java Methods and Control structures". Are instances of MenuRow and Runnable data types, control structures? Does Driver have control structures, enumerate them.
  • Explore AP Classroom. Look at 1 unique FRQ per team member on AP Classroom that goes over Methods and Control Structures. Provide me a Jupyter Notebook, Video, and/or Code that cover key concepts. Make this better than AP Classroom, specifically trying to get these reviews to cover key parts in under Ten minutes. This option could use your PBL project and concepts if they were tailored to Teaching.
    • Explore Testing requirements in AP Classroom Video
    • Explore AP FRQ that teaches us about Methods and Control Structures FRQ, 18:10
    • Make sure that code runs completely, complete any portion of FRQ that is undone. Complete FRQs in a Jupyter notebook with markdown description and comments is a requirement.
    • Integrate Data Types into the discussion as this is import concept when studying early materials.
    • Integrate Definition of Methods and Control Structures in comments and definitions.

Personal Hacks

Early Seed

Example Binary Addition:

1 + 1 = 10

01101010 + 01010111 = 11000001

public class BinaryAddition {

    public static String add(String byte1, String byte2) {

        // Turn each byte into an integer, add integers together, then reconvert integers into a byte
        return Integer.toBinaryString(Integer.parseInt(byte1, 2) + Integer.parseInt(byte2, 2));
    }

    public static void main(String[] args) {
        System.out.println(add("1", "1"));
        System.out.println(add("01101010", "01010111"));
    }
}

BinaryAddition.main(null);
10
11000001

Small Code Exercises

public class PrimitiveExample {

    public <E> E sort(E element) {
        return null;
    }
    public static void main(String[] args) {
        int[] intArray = new int[]{3, 4, 2, 6, 1, 8, 4, 5, 9, 1, 2};
        
        ArrayList<Integer> integerArray = new ArrayList<Integer>();

        for (int i = 0; i < intArray.length; i++) {
            integerArray.add(new Integer(intArray[i]));
        }

        System.out.println(integerArray);
    }
}

PrimitiveExample.main(null);
[3, 4, 2, 6, 1, 8, 4, 5, 9, 1, 2]

Exploring AP Classroom

public class FrogSimulation
{
    /** Distance, in inches, from the starting position to the goal. */
    private int goalDistance;

    /** Maximum number of hops allowed to reach the goal. */
    private int maxHops;

    /** Constructs a FrogSimulation where dist is the distance, in inches, from the starting
    * position to the goal, and numHops is the maximum number of hops allowed to reach the goal.
    * Precondition: dist > 0; numHops > 0
    */
    public FrogSimulation(int dist, int numHops)
    {
    goalDistance = dist;
    maxHops = numHops;
    }

    /** Returns an integer representing the distance, in inches, to be moved when the frog hops.
     */
    private int hopDistance()
    { /* implementation not shown */ 

        // Int datatype used because steps should be whole numbers
        return (int) (Math.random() * 20) - 10;
    }

    /** Simulates a frog attempting to reach the goal as described in part (a).
    * Returns true if the frog successfully reached or passed the goal during the simulation;
    * false otherwise.
    */
    public boolean simulate()
    { /* to be implemented in part (a) */ 
        int distance = 0;

        // if control structures catch any return conditions being met
        for (int i = 0; i < maxHops; i++) {
            distance += hopDistance();
            if (distance < 0) {
                return false;
            }
            if (distance >= goalDistance) {
                return true;
            }
        }
        return false;
    }

    /** Runs num simulations and returns the proportion of simulations in which the frog
    * successfully reached or passed the goal.
    * Precondition: num > 0
    */
    public double runSimulations(int num)
    { /* to be implemented in part (b) */ 

        // Note the usage of the double datatype here
        // When doubles are operated on with ints, the result is an integer
        double trueResults = 0;


        for (int i = 0; i < num; i++) {

            // if control structure differentiates between successful and unsuccessful simulations
            if (this.simulate()) {
                trueResults++;
            }
        }

        // Here a double and int are operated on together, resulting in another double
        return trueResults / num;
    }

    public static void main(String[] args) {
        FrogSimulation test = new FrogSimulation(24, 5);
        System.out.println(test.simulate());

        System.out.println(test.runSimulations(100));
    }
} 

FrogSimulation.main(null);
false
0.01

Datatypes

There are 2 main datatypes present in the above code, which are:

  • ints
  • doubles

Certain datatypes are better suited than others to model a situation; since the situation includes the distance per hop, the maximum distance, and the max number of hops are all whole numbers, ints are preferrable to use here.

However, considering the output of runSimulations() being a ratio, a different datatype would be better suited: a double.

Methods and Control Structures

Control structures form the building blocks of most methods, allowing them to handle simple tasks such as filtering or calculating. In this case, the main methods are simulate() and runSimulations().

simulate() utilizes both for loops, in order to iterate through the hops and their effect on distance, and if loops, in order to check if any one of the return conditions are met (negative distance, max hops, or reached distance).

runSimulations() also takes advantage of for loops in order to run simulate() numerous times, using an if statement to distinguish between successful and unsuccessful simulations.

Quiz Corrections

Overall, I got 38/39.

Question 3

public class A {
    public show() {
        System.out.println("A");
    }
}

public class B extends A {
    public show() {
        System.out.println("B");
    }
}

A obj = new B();
B.show();

I thought that, since obj was specifically given the type A, that it would print out "A" when show() is called. But since the type used to fill up the A datatype requirement is B, then the method from B is used, so when show() is called "B" is printed.