Programming
Java Basics
Contributors:
Hamid Hussain, Austin Benedicto
Hamid Hussain, Austin Benedicto
Programming in Java is a core part of both FRC and FTC. Although both programs support other languages such as Blocks, C++, Python, we exclusively use Java to make it easier to switch from an FTC codebase to an FRC one.
Before covering program-specific information (such as how to work with the FTC SDK and WPILib), new programmers should read this article to understand the basics of Java itself. This includes learning about Java's basic syntax and will give you the very bare bones skills necessary to get code working on your machine.
As a side note if you truly want to get better at Computer Science take the CS courses at Nichols at the time of writing Mr. DeGroat teaches them. We here can teach you a lot but he can teach you even more than we can.
When you create a Java project or file in a code editor, you will often see a structure like this.
Because Java is a very verbose* language, even a simple program can look daunting. This one takes 5 whole lines of code to print "Hello, World!" to the console.
Despite its intimidating nature, many of the fundamental elements of Java code are present in this small code snippet.
Here, we can see the different elements of this code. This still probably makes little to no sense to you, but we now have a great outline for what to learn next. As you go through the next sections, take a look back at this code and see if you can start to piece together not just what it does (I already told you that part) but why and how it does that.
In Java and other programming languages, variables are things that hold data for us. These variables can hold numbers, sentences, and yes/no values, among other things.
Since Java is a strongly-typed language, all variables that we create in our code have to be assigned a specific datatype.
Let's learn about some basic datatypes, and how to define variables of those datatypes in code.
First, let's look at numerical datatypes, or datatypes that store numbers. The three main numerical datatypes are int, double, and float.
int: An integer, or whole number. Usually used for counters or measuring discrete values.
double: A fractional number, or a number that can be defined with a fraction. Commonly has a few decimal places.
float: Another type of fractional number. Commonly used for very precise measurements, usually has a lot of decimal places.
int age;
double mass;
float distance;
age = 18;
mass = 140.25;
distance = 5.8733402128557872;
Here we have a code sample that uses all three of these datatypes. More specifically, this code declares three variables, one for each datatype.
The first one is an integer, and is named "age".
The second one is a double, and is named "mass".
The third one is a float, and is named "distance".
After declaring each variable, the code assigns a value to each. Here, it's easier to see the differences between the datatypes.
Java code will usually contain more than just numerical datatypes. Here are some more common (non-numerical) datatypes:
String: Represents a string of characters, like a word or sentence. For example, "Electric" is a string with 8 characters.
boolean: Represents a binary value, like yes/no or on/off. Even though it can represent any binary value, they are always referred to as true or false.
String message;
boolean showMessage;
message = "Hiya!";
showMessage = true;
Same deal as before, we can use these datatypes to declare variables. Here, the code declares a String "message" and a boolean "showMessage"
The code then assigns the message variable a value of "Hiya!" and the showMessage variable a value of true.
Now that we know about variables and datatypes in Java, we need to know how to put them into Java code. Fortunately, while you were learning about these datatypes, I secretly already showed you how. There are two steps to creating a value-holding variable in Java - Declaring and Assigning.
String foo;
foo = "bar";
System.out.println(foo);
The first line of this code declares a variable "foo" of type String. This initially creates the variable, but it doesn't yet have a value.
The second line assigns the "foo" variable a value of "bar". After this line, the variable now holds the value "bar". If we were to ask Java to print the "foo" variable (as shown on the third line), it would print "bar".
final boolean isFinal = true;
isFinal = false;
Here, the variable "isFinal" of type boolean is declared and assigned on the same line. This is possible within Java.
The variable is also a final variable, which you can see since it says "final boolean" instead of just "boolean". This means that the re-assignment done on the next line won't work.
When you have two variables/values of the same type, you can compare them to check whether or not they are equal. This is done my using the double-equals "==" and not-equals "!=" operators.
When you check the equality of two values, the result is a boolean value that is true if they are equal and false otherwise.
When you ckeck for inequality between two values, the result is a boolean value that is true if they are not equal and false otherwise.
String a = "foo"
String b = "bar"
System.out.println(a == b);
// prints false
System.out.println(a != "foobar")
// prints true
In this example, we define and assign two variables of type String.
Then, we print out the equality comparison between them (a == b). Since the two are not equal, "false" is printed to the console.
Next, we print out the inequality comparison between the "a" variable and a String value "foobar". Notice that we don't have to compare two variables, we can substitute one for a preset value. Since the two are not equal, "true" is printed to the console.
When you're dealing with numerical datatypes, it's possible to do all sorts of mathematical operations on them. Since this is just covering the basics, let's go over the four arithmetic operations: addition, subtraction, multiplication, and division.
double a = 2.0;
double b = 5.0;
System.out.println(b + a);
// prints 7.0
System.out.println(b - a);
// prints 3.0
System.out.println(b * a);
// prints 10.0
System.out.println(b / a);
// prints 2.5
System.out.println("foo" + "bar");
// prints "foobar"
To demonstrate these arithmetic operations, let's first define and assign two variables of type double.
On the next line, we print the result of the statement "b + a". This adds the value of b to the value of a.
Then, we do the same with the statement "b - a", which subtracts the value of a from the value of b.
The next line uses the statement "b * a", which multiplies the two values.
Finally, the fourth line uses the statement "b / a", which divides the value of b by the value of a.
Notice how the traditional symbols for multiplication (×) and division (÷) are replaced with the asterisk (*) and forward slash (/).
It's also possible to use the addition operator to concatenate (join) values of type String, as seen on the last line.
There are also specific operations that deal with comparing and modifying boolean values. There are many of these operations, but we'll just focus on the most common ones.
System.out.println(false || false);
// prints false
System.out.println(true || false);
// prints true
System.out.println(true || true);
// prints true
System.out.println(false && false);
// prints false
System.out.println(true && false);
// prints false
System.out.println(true && true);
//prints true
The first two print statements show the usage of the OR operator, indicated by two vertical separators (||). This operator gives a value of true only when at least one of the two boolean values is true.
The second pair demonstrates the usage of the AND operator, indicated by two ampersand symbols (&&). This operator gives a value of true only when both values are true.
boolean b = true;
System.out.println(!b);
// prints false
In this code sample, we define and assign a variable "b" of type boolean to the value true. Then, we print the output of the statement "!b". This prints false instead of true, because the NOT operator (defined with an exclamation point) negates a boolean value.
Now that we have a basic understanding of variables and datatypes, we can use these to do more complex operations using logic statements and loops.
If statements are statements that only run the code inside of them if a certain condition is met. In the case of anything else, it can also run a different piece of code.
int a = 1;
int b = 2;
if (a == b) {
System.out.println("My inputs are the same!");
} else if (a > b){
System.out.println("b is greater than a!");
} else {
System.out.println("a is greater than b!");
}
This if statement checks to see if a is equal to b, if they aren't equal, it moves to the "else if" to check if a is greater than b. If that is false, it prints out "a is greater than b".
Since a = 1 and b = 2, it will print "a is greater than b!"
While loops are statements that repeatedly run code until while a certain condition is met.
while (elapsedTime < 1000) {
System.out.println("It hasn't been a full second yet!");
}
This while loop will continue to print "It hasn't been a full second yet!" until the program has been running for 1000ms (1 second) or more.
while (true) {
if(elapsedTime > 1000){
break;
}
System.out.println("It hasn't been a full second yet!");
}
This while loop does the same thing as the previous one. However, instead it uses the "break" line, which causes the loop to end. In this case, while(true) means it will always run until told not to and the if statement in here will exit the loop if elapsed time is greater than 1000.
For loops are statements that repeatedly run code for a certain amount of iterations.
int a = 3
for (int i = 0; i < a; i++) {
System.out.println(i);
}
The for loop has a more complex syntax than a while loop, but they can accomplish the same thing. The for loop is often used to repeat something a certain number of times, compared to a while loop, which is often used to repeat something any number of times until something else changes.
int i = 0: This creates a int variable i and gives it a value of 0. This part of the for loop runs once before any other code in the loop is run.
i < a: This is the condition of the for loop and will be continuously checked like the while loop. In this code segment it will run until i = 2
i++: This is the segment that runs after every loop. In this case it increments the value of i after every loop.
Now that we have a basic understanding of variables and datatypes, which represent data in Java code, we can move on to methods, which can take in and output data, perform actions, and allow for organized, reusable code.
public double addDoubles(double a, double b) {
double sum = a + b;
return sum;
}
This is a very basic method that takes in two values of type double, adds the two, stores the sum in a new variable "sum", and then returns (outputs) the value of this new variable.
Even though we're back to being insanely verbose, each part of this method declaration actually means something.
public double: This part of the code makes the method public, meaning it can be accessed by other classes (we'll talk about these shortly). It also tells us that the method returns (outputs) a value of type double (the sum, in this case).
addDoubles: This is the name of the method, which is used to call it. We will learn about how to call functions shortly, but this name should be descriptive. For example, this method is named "addDoubles" because it does just that.
(double a, double b): The parenthesized statement directly after the method name indicates the method's inputs. These inputs are given to the method when it is called, but the method uses these variable names to refer to them. For example, if I were to input 12.0 and 4.0 to the method, the variable a would be 12.0 and the variable b would be 4.0.
{}: The curly braces contain the code that the method runs.
double sum = a + b: Using what we learned about Variable Arithmetic, we can deduct that this statement defines the sum as the value of a plus the value of b.
return sum: The return statement is used to output a value from the method. After the return statement, the method ends and no other code runs.
public int yearsToMonths(int years) {
int months = years * 12;
return months;
}
public static void main(String[] args) {
int a = yearsToMonths(2);
System.out.println(a);
// prints 24
}
Here's another method, yearsToMonths(). It's similar to the last one, so it should make sense.
We also have another method main(). The main method is seen in all Java projects, including the code snippet at the beginning of this article. The code inside it is run when the Java project is run.
In this main method, we call the yearsToMonths method and assign its output to a variable "a". To call the method, you just need to type its name and add some parentheses with the input values.
The main() method also highlights two new keywords - static and void.
static: The method exists only once, and cannot be instanced
void: The method does not return a value.
Now that we have a basic understanding of variables, datatypes, and methods in java code, now we can move on to classes. Classes are objects in java code which serve 2 main purposes: representing objects and serving as collections of methods (sometimes referred to as libraries). Functionally as Java Syntax they are the same thing but it is the way that we use them is different.
Object Classes are representations of objects in Java. They combine the usage of variables and methods.
public class Chicken {
private int age;
private double weight;
public Chicken(int age, double weight){
this.age = age;
this.weight = weight;
}
public int getAge() {
return age;
}
public double getWeight(){ return weight; }
}
This is a class that acts as an object (a chicken).
To represent a chicken, we use two variables ("age", an integer, and "weight", a double). These variables have the private keyword before their declarations. This means that methods outside this class cannot directly interact with them.
In addition to these variables, we also declare two methods, which just return the values of the two variables. These methods are public, meaning they can be called from other areas of our code.
Because the variables themselves are private, but the "get" methods are public, the "age" and "weight" values can be read, but not modified, outside of this class.
There's one exception to this, and that's the constructor of the class. The constructor is mainly used in object classes, and is similar to a method, but is only called when an instance of the class is made somewhere else in the code. We will learn about creating object instances later.
The constructor is the only place where the age and weight of the chicken is modified, as it's where these variables are first assigned. The constructor takes in these values as inputs and then assigns them to the object's variables.
These are different from object classes, since instead of representing objects, they simply act as collections of related methods.
public class AngleMath {
public static double addAnglesDegrees(double angle1, double angle2) {
double sum = angle1 + angle2;
while(sum >= 180.0)
sum -= 360.0;
while(sum < -180.0)
sum += 360.0;
return sum;
}
public static double addAnglesRadians(double angle1, double angle2) {
double sum = angle1 + angle2;
while(sum >= Math.PI)
sum -= 2 * Math.PI;
while(sum < -Math.PI)
sum += 2 * Math.PI;
return sum;
}
}
This would be an example of a library class. It has 2 methods inside of it in which are all dedicated to doing math with angles.
The first method "addAnglesDegrees" takes in 2 angles in degrees, and adds them together while making sure the sum doesn't exceed +180 or -180 degrees.
The second method "addAnglesRadians" takes in 2 angles in radians, and adds them together while making sure the sum doesn't exceed PI or -PI degrees.
These methods don't represent any object, but are in the same class because they both deal with Angle Math.
public class App {
public static void main(String[] args) {
Chicken ch1 = new Chicken(10, 45.6);
System.out.println( ch1.getAge() );
//prints 10
System.out.println(
AngleMath.addAnglesDegrees(360, 240)
)
//prints -120
}
}
Here, we have the main method of the program. The first line is instancing a Chicken object with the name ch1, and assigning it an age of 10 and a weight of 45.6.
The second line is using the getAge() method of the Chicken class to get the age of ch1, and then printing it.
The third line is calling the addAnglesDegrees() method from the AngeMath class and then printing that value.
Notice that "ch1" is a Chicken, and we represent this in code in a similar manner to how we specify a variable's datatype. This is because ch1 is still a variable, but instead of using a primitive datatype like "int" or "boolean", it uses the Object type of Chicken.
Because ch1 is a variable of type Chicken, we use "new Chicken" to call the constructor and assign its age and weight. We can then access the methods of the Chicken class through ch1.
When accessing the AngleMath methods, we don't need to instance it, because it is a library class and all of the methods are static (meaning they cannot be instanced).
Remember NO ONE gets good at programming by just reading code and looking at what other people have done. You will only be able to just get the surface level stuff. The way we are able to apply the skills that we learn is by doing little things called side projects. These side projects can be a range of things from very simple calculators all the way to full on video games. I suggest to start small. A program that can look very simple at the start can grow to be something massive really fast.
These are not necessarily put in order from easiest to hardest they are just a good starting point:
Tic Tac Toe game
Password manager
simple 4 function calculator
dice roller
text based video game
maze text based video game
Here to the left is a lot of small side projects that you can start with to begin to develop your skills. But if you want to create your own it's a very simple process. Think of something that you would find cool and fun to do and go ask an older programmer on the team, and see if they think you can do it. The older programmers have a better sense of your skill level and how hard the project you are thinking of could be.