For my Task 1 program, it is designed to help anyone understand the basics of how Java handles names (identifiers) for different programming elements, how you set up variables, and how their accessibility is controlled (scoping).
First, in Java, you use identifiers to name variables, methods, and other elements. Java rules state that identifiers must start with a letter, an underscore (_), or a dollar sign ($), but they can't start with a number. In the program, you'll see valid examples like num_1 and num$2. It also includes a commented-out example (int 1num = 3;) to show an invalid identifier that starts with a number, helping differentiate between the two rules.
The program declares variables in different places, each with its own scope. Scope essentially represents where in the program that variable is valid or able to be referenced. This is important because scope determines where a variable can be accessed. We have class-level variables (like classLevelVariable), which can be used anywhere in the class. Next are method-level variables (like methodLevelVariable), which are only accessible within the method where they appear. Finally, there are block-level variables (such as blockLevelVariable in the if statement), which are basically confined to the block they’re declared in, meaning you can’t use them outside that block.
Understanding scope is very important while learning Java because it helps avoid name conflicts and keeps code organized. Later on in the semester we will touch on overriding and overwriting, which involves certain ideas of scope.
My program also includes an example of variable shadowing. Shadowing occurs when a variable declared in a smaller scope (like a block) has the same name as one declared in a larger scope (like a method), and within that smaller scope, the local variable actually takes precedence over the global variable.
Overall, my program shows a few examples of handling variable names and scopes in Java as well as touching on shadowing and identifiers.
Output:
This terminal output shows that the classLevelVariable, declared at the class level, has the value 5 and is accessible throughout the class. This makes sense as described above, as it has a wide class scope.
The methodLevelVariable, which is declared inside the main method, has a value of 10 and is only accessible within main. This is a smaller scope than a class level variable.
The displayVariable, declared within the displayVariables method, holds the value 30, demonstrating local variable scope when the method is called from the main function as well.
The output also shows the classLevelVariable accessed from displayVariables, retaining its value of 5 (again showing its scope). The line about entering the if block in main indicates that the condition methodLevelVariable > 5 is true. Inside the if block, blockLevelVariable is declared with a value of 15, showing an example of block-level scoping.
Finally, the reference to methodLevelVariable within the if block shows an example of variable shadowing. It stays at 10 since there is no variable with the same name within that scope.
My Task 2 program implements a binary search algorithm, a relatively efficient way to find a target value in a sorted array!
The program begins with a class definition, Task2, which is an important piece of a program in Java (in order to organize related methods and variables). The key/significant function of this program is the binarySearch method, which is defined using the syntax public static int binarySearch(int[] array, int target). This method takes an array of integers and a target integer as parameters specified by the two variables in the paranthesis, and returns the index of the target if found, or -1 if that value is not present in the array.
Inside the binarySearch method, the program uses control flow statements. The while loop continues executing as long as the left index is less than or equal to the right index, which represents the current search space. Within this loop, an if statement checks if the middle element of the array matches the target; if it does, the index is returned. Additional if and else statements determine whether to search the left or right half of the array based on comparisons of the middle element and the target value.
This structure illustrates how Java syntax allows for the creation of methods and the use of control flow statements to perform operations, which makes it easy to implement algorithms similar to binary search.
EXTENSION:
The commented out main method also shows how to call my binarySearch function with a sample sorted array, showing how a user would typically test this binarySearch method. After uncommenting this section and running the binary search algorithm we see this output:
This output shows that after running binary search on an array of [2, 4, 6, 8, 10, 12, 14, 16, 18, 20], and searching for the target value of 10 returns the index 4. This is correct, as the number 10 in the array is at index 4. The logic implemented in my main function essentially creates a test array with values 2 - 20 counting by 2s, and passes that to my binarySearch algorithm. I also included language to print out if the algorithm found the value or did not find the value!
My next Java program, task3.java, shows an example of the basic builtin types and also creates an aggregate type using a class to represent a point in the 2D space (basically on the xy plane). My program begins with a class definition of course, Task3, which organizes related methods and variables. In this class, the Point child class is also defined to show the characteristics of a point with two int fields (x and y) that basically represent points on a plane. This essentially acts as an example of an aggregate type creation.
The main method also shows various builtin types, including ints, doubles, chars, booleans, and strings. Each type is represented by its respective variable name: intValue for integers, doubleValue for floating-point numbers, charValue for a single character, boolValue for boolean values, and stringValue for text. These examples show Java's type system.
The program also performs mathematical operations using the variables. For example, the addition of intValue and a constant results in an integer, while multiplying doubleValue by an integer results in a double. The use of operators like +, -, *, /, and % show how basic mathematical operations work on various types of variables, and whether or not they return the appropriate result type based on the operands involved.
My next Java program, illustrates the control flow statements in Java and their usage, including conditional statements and loops. Within the main method, I use conditional statements like if, else if, and else to evaluate a variable's value, and printing statements to see the results of these statements.
Also, I used a switch statement to handle specific cases based on that variable (I like this control flow statement). The program also demonstrates loops through for, while, and do-while constructs to iterate over a set of values, showing how each loop type functions. My use of break and continue statements is also included to control the flow within the loops effectively, allowing conditional exits and iterations.
For the last Java Task, I attempted to show how functions can be treated as first class objects in Java. I show this by using the Function interface to assign a method, square, to a variable. This allows me to reference the method without invoking it immediately. Within the main method, I show how to pass this function variable to another method, processFunction, which takes a Function as a parameter and executes it using the apply method. This capability highlights how flexible Java is in handling functions as data types.