Java Refresh
What is Java?
Java is a High Level, Class Based, Object Oriented Programming language first released in 1996. Click here for a Java syntax and functionality review.
Java has many useful features which can help us learn programming strategies. It is also a good jumping-off point to learn other programming languages while keeping the same fundamentals.
High Level – means that Java itself handles much of the System level work needed to make the language function. One of the key features is managing memory for variables/objects, using the Java Garbage Collector. The written code in Higher Level languages is often closer to human language (how we would describe a programs steps).
- The lowest level programming language is Machine Language, consisting of pure Binary (Zeros and Ones). All code is converted to ML before the computer runs it.
Class Based – means that Code is organized into distinct Classes, which each contain information and executable methods for a specific type of object.
- In this guide, we won’t worry about classes. View the Object Oriented Program guide for more information about class structure and uses.
Java Code Rundown
Java contains many popular features of programming languages which can be used and combined to do almost anything you could imagine.
These include Variables, Objects, Operators (+,-,*,/), Conditionals, Loops, and much more.
All Java code must be written in the bodies of methods. Often, this is the main() method. The main method is the code that runs when you compile and run a java file. See the OOP Programming Guide for more info on main methods.
Each line of java code is ended by a semicolon ; and if a semicolon is not there, the program will not compile.
Let’s review some of the features of Java, and how we can use them in our programs.
Variables
Variables in Java are how we store data, values, and access any object. You declare variables with a given type, which defines what that variable will hold/reference. You can then assign a value/object of that type to the variable, to access/use that value/object. You can reassign the variable as much as you’d like.
int num = 5; // Creates a variable named "num" which is of the "int" type, and assigned the value 5
String name = "Mark"; // Creates a variable named "name" of the type "String", which holds "Mark"
Variables are the building blocks of programming languages, including java. They are necessary to solve problems, and their uses/requirements are largely dependent on their type.
About Java Types:
- There are two kinds of types in java, Primitive Types and Reference Types
- Primitive Types represent basic values. They are int, long, short, float, double, boolean, char, and byte.
- int is a basic integer, and can hold values from -2,147,483,647 to 2,147,483,647
- long and short are also integer representations. A short can represent -32,768 to 32,767, and a long can represent -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807.
- float and double are both representations of numbers with a decimal point. A double has 16 digits of precision, while a float has 7.
- boolean is either true or false
- char represents a single Unicode character, such as ‘A’, ‘?’, ‘/’, etc..
- byte is a one-byte integer ranging from -128 to 127
- Reference Types represent any other object.
- These objects are instantiated with the “new” keyword and assigned to a variable of that Class type
- Objects are defined by a Java Class. You can learn more about java classes and oop here.
- These objects are often much more complex than primitives. They can represent entire data structures, and contain methods to solve complex problems.
- Each primitive type listed above has a corresponding Wrapper-Class which represents the same primitive type, but includes methods you can use.
- Integer – int
- Double – double
- Boolean – boolean
- etc
- These objects are instantiated with the “new” keyword and assigned to a variable of that Class type
The memory used to store Variables and objects they reference are managed by the Java Garbage Collector.
Java Garbage Collector
The Java garbage collector is a vital part of the Java Virtual Machine (JVM) that automates memory management by identifying and clearing memory which was allocated to objects which are no longer in use. It works by tracking object references (variables) and ensuring that wasted memory is reclaimed without requiring anything of the developer.
When an object is created, it is allocated memory on the heap. The garbage collector periodically scans the heap to identify which objects are still reachable, meaning they are referenced directly or indirectly by active variables or static fields.
If an object is found to be unreachable, meaning no active references point to it, it is considered eligible for garbage collection.
Basic Operations
Java has many basic operators which can be used in programs. Many of these include basic mathematical operators.
+ adds two values, or concatenates two strings
– subtracts two values
/ divides two values
* multiplies two values
= assignment operator (NOT equals comparison)
- This assigns the value on the right side to the variable on the left side, and accesses each in that order.
- intName = 4;
- strName = “34”;
== object comparison
- == checks if the two given objects are the same. This works well with primitive values like ints and booleans, but does not work as well with object reference-type variables.
- This is because two different objects can hold the same value, but not be the same under ==. In this case, we usually use the .equals( ) method if the type has one.
- A good example of this is Strings. We have to compare them with .equals(), since two String objects are unique, even if they hold the same message.
Java also has mathematical comparsion operators such as <, >, <=, and >=
Conditionals
Java Conditional statements allow the program to execute code only if a certain condition is met. The most basic conditional statement is an if-statement.
if ( BooleanCondition ) {
//Execute code;
}
If statements have a Boolean Condition which determine whether or not to run the code inside.
Boolean Conditions
- A combination of boolean variables/values which evaluates to either true or false. Can also be viewed as an equation.
- Boolean Conditions can use || (OR), && (AND), ! (NOT), == (EQUALS), and ^ (XOR)
- You can use these to combines boolean values down into a single T/F value
- true && true == true, false && true == false, true && false == false
- true || true == true, true || false == true, false || true == true
- !true == false, !false == true
- true ^ false == true, false ^ true == true, true ^ true == false
In addition to if-statements, there are also else-if and else statements, which are connected to an if-statement.
If the initial if statement is not true, it will then check any else-if statements directly below and evaluate the first one that is true. If none of the checked conditionals are true, it evaluates the else statement at the bottom.
These always have to be declared in if-else if-else order, and only the first one to evaluate to true will be ran. You can never write an else-if statement or an else statement without an if statement above them.
if ( false ) {
// Execute code if true
} else if ( false ) {
// Execute code if true
} else if ( false ) {
// Execute code if true
} else {
// This actually executes
}
if ( false ) {
// Execute code if true
} else if ( true ) {
// Execute code if true
} else if ( true ) {
// This does not execute
} else {
// This does not execute
}
Loops
Java loops allow a block of code to be repeated multiple times, either to repeat the same exact task many times or to repeat a single task on many different objects/pieces of data. Loops are very useful, and can accomplish powerful tasks with a small amount of code.
There are three types of loops in Java: for loops, while loops, and do-while loops. All three types of loops have loop-conditions which determine how many times the loop iterates (repeats).
A for loop: has three parts to the condition (initialization; condition; advancement)
- Initialization allows you to create and assign variables, of any type, in the loop condition
- Condition is a boolean condition which determines when the loop should keep going and when it should stop
- Advancement allows the loop to run a piece of code after each iteration, which ‘advances’ to the next loop-iteration
A for loop can alternatively be expressed as a for-each loop, which changes how the loop condition is structures. Instead of the above, you can declare a variable of a type followed by a colon “:”, followed by a object which is a Collection/array that holds the given object type.
Examples:
for (int i = 0; i < 10; i++) {
// Write your code here
}
for (Node ptr = front; ptr != null; ptr = ptr.next) {
// Write your code here
}
int[] ints = new int[25];
for (int j = 0; j < ints.length; j++) {
int curr = ints[j];
// Write your code here
}
Integer[] intArr = new Integer[15];
for (Integer curr : intArr) {
// Write your code here
}
A while loop: has a loop condition which is a boolean condition that is checked each time before running the code block.
The while loop will check its condition before running its code, and will continue to check the condition each time before repeating the code. If the condition is not true, the code does not run and the while-loop exits.
// These are both equivalent
int i = 0;
while (i < 10) {
// Write your code here
i++;
}
for (int i = 0; i < 10; i++) {
// Write your code here
}
// These are also equivalent
while (booleanCheck) {
// Write your code here
booleanCheck = false;
}
if ( booleanCheck ) {
// Write your code here
}
while (StdIn.hasNextLine()) {
String line = StdIn.readLine();
// Write your code here
}
String line = (StdIn.hasNextLine())?(StdIn.readLine()):(null);
for (; line != null && StdIn.hasNextLine(); line = StdIn.readLine()) {
// Write your code here
}
A do-while loop: has a loop condition which is a boolean condition that is checked each time after running the code block.
The do-while loop will check its condition after running its code, and will continue to check the condition each time after repeating the code. This allows you to always execute a code block once, and then decide at the end whether or not to repeat it.
do {
// Write your code here
} while ( booleanCondition );
int i = 0;
do {
// Write your code here
if ( booleanCheck ) {
i++;
}
} while ( i < 11 );
Node ptr = front; // Linked List with guaranteed 1 item
do {
// Write your code here
ptr = ptr.next;
} while (ptr != null);
Objects and Methods
When we use Reference-Type variables in java, we hold a reference to an object. This object can be of many types, and is defined by a class. This class can have methods, which you can use, either on a specific object instance of the class, or via the class file itself (static). View the OOP guide for more info on classes.
Integer int = new Integer(3); // Creates a new Integer object (wrapper class) with the value of 3
ArrayList<String> arr = new ArrayList<>(); // Creates a new ArrayList of strings
You can then use any methods on the object instances you made.
int.equals(otherInt);
str.equals(otherStr);
arr.contains("Hello");
arr.add("Hi!");
arr.remove("Bye.");
Classes also contain static methods, which are accessed via the class itself, NOT a specific object instance of the class.
Integer int2 = Integer.valueOf(3);
int2 = Integer.parseInt("4");
StdIn.setFile("input.in");
int i = StdIn.readInt();
StdOut.setFile("output.out");
StdOut.print(i);
StdIn and StdOut are classes that heavily utilize static methods and variables. You don’t instantiate either class before you use them, you simply call the static methods StdIn.setFile(inputFile) or StdOut.setFile(outputFile). This sets the singular static filestream for either to the given input/output, and which can be accessed statically with the StdIn.readX() methods or StdOut.print() methods.
Coding Strategy
You can combine all of the above tools to do powerful things in java.
Generally, to solve problems with java code, we want to:
1. Understand the Problem: Make sure you understand what is being asked. Identify the inputs, outputs, and any constraints.
- Always try to rephrase the problem in your own words.
2. Break Down the Problem: Divide the main problem into smaller, manageable sub-problems or tasks.
- Then, Outline the steps needed to solve each sub-problem. This could involve algorithms or logical steps (i.e. for each of these i have to do this only if x is true).
3. Design the Solution
- Write Pseudocode: Draft the logic in pseudocode to organize your thoughts before coding.
- Consider Edge Cases: Think about special cases and how your solution will handle them.
- Write your code, and test it AS your write it.
- See the debugging guide for more info on testing your code.
- Test your final solution with a variety on inputs, and fix any bugs.