The most obvious reason to learn Java is that it’s in high demand. It’s the number 1 language (in 2021) for developing enterprise application and can run on any platform. Known for “write once, run anywhere”. It’s also general purpose which means it can be used for web, mobile, machine learning, automation and more.
Why you should learn other languages first
How much does a Java Developer make in USA? The average java developer salary in the USA is $113,248 per year or $58.08 per hour. Entry level positions start at $95,166 per year while most experienced workers make up to $146,250 per year.
talent.com
I know the following statement it’s going to sell you on it but in the name of full disclosure:
The average python developer salary in the USA is $119,995 per year or $61.54 per hour. Entry level positions start at $97,500 per year while most experienced workers make up to $150,959 per year.
talent.com
Java isn’t easier than other languages and I’d actually argue it’s harder due to some of it’s extra steps you just don’t have to consider in languages like python or bash.
My take
I have to say - if you know Typescript or Dart or even Javascript, then Java is going to be super easy to transition into. The hardest part is Objects and Classes with OOP (but isn't that the hardest of any language). If you are just a functional programmer, it's a breeze. It's not my favorite but it does have some advantages. The main disadvantage I see is boilerplate fluff that makes simple things really long (java generator extension on vscode really kinda kills this argument though). Java makes up for the fluff with excellent debugger tooling, lack of es6 baggage like javascript, and it can run anywhere. Since you can make more as a Python Developer, and because python is a bit easier to learn - I'd start with bash and move to python if I was starting out from scratch but this wouldn't be a bad 3rd. I'm learning it so I can start learning groovy which is built on java. Jenkins CI/CD tooling is written in java and most of it's scripts are written in groovy making it a must have tool in your tool belt if you want to become a senior DevOps engineer in 2022.
Installing Java
You need to install a JDK (Java Development Kit) and download a text editor - I recommend visual studio code but you can use any that you are comfortable with.
How to install JDK (Mac)
It’s something we need to develop java applications - you need 2 things. A java compiler and a runtime. The JDK includes these and more.
You can use brew but for this instruction we are going to use AWS Coretto. Download it here: https://docs.aws.amazon.com/corretto/latest/corretto-11-ug/downloads-list.html download the package for Mac.
Open the package installer and then run it.
How to install VS code
Head over to https://code.visualstudio.com/download and install it.
I recommend the following extentions
- https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-pack
- https://marketplace.visualstudio.com/items?itemName=ullissescastro.theme-bracketsdarkhttps://marketplace.visualstudio.com/items?itemName=2gua.rainbow-brackets
- https://marketplace.visualstudio.com/items?itemName=oderwat.indent-rainbow
Set up code
command in your path.
- Press
command
+shift
+p
and then type:install 'code' command in PATH
and then click it on the drop down. Now if you are in terminal, you can open a file with thecode <file or directory>
command.
Create a project workspace at ~/development
then open that directory using that code ~/development
command.
Hello Java World
Create your first java application
in your ~/development directory go ahead and create a new file and call it HelloJavaWorld.java
Notice the Camel Case for the file name is a general construct that Java developers adhere to.
In every Java application there is 2 parts:
- The
class
keyword - The class name - the class name needs to be the same as the file name.
It’ll look something like this
public class HelloJavaWorld{
}
For now, don’t get tripped up on the public
keyword, what you need to know is it exposes this class to other classes. It’s not really doing anything since we only have one.
Next up we have a main()
method which is the entry point of our application.
Java starts by looking for the main() method.
Use the java extension we installed earlier by typing main
and then selecting the expansion
What that just spit out was a bunch of boilerplate java that is similar to other languages like dart. It’s necessary for the Java runtime/compiler to have this line as an entrypoint.
Inside of that function that is created (inside of it’s {}
) you will want to add the following: System.out.println("Hello World!");
It should look like this:
public class HelloJavaWorld{
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
Save your file.
Let’s discuss a little of the line we just created.
println()
- prints a message inside it’s parenthesis to the console
;
- in java, every single line of code needs to be closed with a semi-colon. If you come from python, this will drive you crazy. If you come from Javascript, this isn’t entirely new but it’s no longer optional. Insert disdain here...
So, now if we wanted to run this application - we first must compile it.
javac <file_name>.java
- this compiles the code
💡 You will see the new compiled code as HelloJavaWorld.class which is bite code.
java <file_name>
- this runs the code which you have compiled
You did it!
💡 Now if you make changes to the file, you have to compile it again before running otherwise you will just run the most recently compiled code.
Primitives - Variables in Java
What are variables in Java?
Variables like every other language are used to store values. We are going to learn how to do it with Java.
Basically a variable is a “box” with a name on it that you can put things inside. Those things inside will be of 1 type of things (numbers, strings, arrays, etc...). That box can be used to represent the things inside it or can be used to pull things out of when you need it.
Create a file called Variables.java and in it add the class and main method from our hello world example.
public class Variables {
public static void main(String[] args) {
}
}
How do you create and update a variable in Java?
In javascript you just say let name = drew
and in python you say name = 'drew'
in Bash you say name=drew
so how do you do it in java?
String name = drew;
it’s very “typescript-y” with strong typing. I don’t love it but it’s simple enough. Like in typescript/javascript if you were to try to store an integer in a variable that is required to be a string, you would get a type mismatch error on compilation.
The naming convention for Java variables is lower-camel case - just like typescript/javascript. It is very case sensitive like most languages meaning drewlearns
is not the same variable as drewLearns
.
To update a variable, just make a new statement that sets the variable to a new value like this:
public class Variables {
public static void main(String[] args) {
// int (integer) type variable example
int students = 0 ;
students = students + 10; // long form
students += 9; // shorthand example using += operator
students -= 1; // shorthand example using -= operator
// More on math operators later in this section
System.out.println(students);
//prints 18
// string type variable example
String greeting = "Hello, ";
String name = "Drew";
System.out.println(greeting += name);
// prints "Hello, Drew"
}
}
It’s not at all different than how javascript/typescript handle variable declaration and concatenation of strings.
So how do you do f’strings or string interpolation?
The +
method is one way but if you are at all familiar with this way, spacing is a nightmare and it’s a lot more code for the same exact results. There is something called the format()
method which is similar to how Python2 did string interpolation before the f’string’ came about. Here is an example of how it works: String.format("%s and %s", variableA, variableB);
which I also dislike very much but it’s probably as good as it gets from what I can tell.
What are the different supported ‘types’ of supported variables in java?
Type | What does it do? | Example |
---|---|---|
char | Used to to store 1 character, no more. It’s wrapped in single quotes, do not use double quotes. | char gender = ‘F’; |
String | Used for storing double quotes of any combination of characters. | String name = “Drew”; |
int | Used for storing whole numbers from -2,147,483,647 to +2,147,483,647 | int ten = 10; |
long | Used for storing whole numbers larger than int can handle. It can handle -/+9,223,372,036,854,775,808. It requires the number to end with an L. This isn’t likely to be used often. | long population = 780000000000L; |
double | Used to store decimal numbers. Always use double for math calculations. It can store whole numbers but will always return a double. Avoid using int or long for math calculations. | double price = 9.99; |
What are the math operators supported in Java?
Operator | What it does |
---|---|
+ | simple addition |
- | simple subtraction |
* | simple multiplication |
/ | simple division |
% | returns the remainder of a division - useful for determining odd/even |
++ | add 1 - useful for counts |
-- | subtract 1 - useful for counts |
+= | add by the value of the number on the right |
-= | subtract by the number on the right |
Dynamic Type (Type casting)
What if your double type needs to be an int? How do you change it?
You may be tempted to do the following:
double decimal = 1.03;
int integer = decimal; // ERROR
In java, you have to do this a little differently than other languages I’ve used. Here is how you’d do it:
double decimal = 1.03;
int integer = (int)decimal;
In the code snippet above the (int)
is the type we are converting (casting) to. I’m not personally a fan of this but cool.
Does it round though?
public class Variables {
public static void main(String[] args) {
double decimal = 1.6;
int integer = (int)decimal;
System.out.println(integer);
}
}
// drewk@Drews-MacBook-Air Dev % javac Variables.java
// drewk@Drews-MacBook-Air Dev % java Variables
Nope, it just lops off the decimal. The above example would return 1
.
So is there a floor or float method?
Yes but it doesn’t work like we would expect in Javascript/Typescript/Python. Let’s take a look:
public class Variables {
public static void main(String[] args) {
// get two double numbers
double x = 60984.1;
double y = -497.99;
// call floor and print the result
System.out.println("Math.floor(" + x + ")=" + Math.floor(x));
System.out.println("Math.floor(" + y + ")=" + Math.floor(y));
System.out.println("Math.floor(0)=" + Math.floor(0));
}
}
// drewk@Drews-MacBook-Air Dev % java Variables
// Math.floor(60984.1)=60984.0
// Math.floor(-497.99)=-498.0
// Math.floor(0)=0.0
💡 Note that it rounds accordingly but still adds a .0
to the result, this is because it’s doing math with doubles. To fix this you’d need to use the type casting method from the previous section.
In the previous section we learned how to store variables - but what if we want to prompt the user for a variable value? Let’s learn about libraries and then how to prompt users using the scanner library
Importing libraries and prompting users
Importing Modular libraries
Like many first class languages, Java has libraries and you can leverage them to perform more complex tasks. In java, it is very similar to javascript we use an import statement to pull in a library into our application. The import
keyword is used specifically to import a package, class or interface.
Java has a bunch of built-in packages in the Java API, you can find the complete list here: https://docs.oracle.com/javase/8/docs/api/
You can use it to import an entire package that contains all the classes or you can import a specified package.
How do you create your own packages in java?
To create a package, use the package
keyword in a file called “MyPackageClass” like this:
package drewlearns; // package names are in lowercase
class MyPackageClass {
public static void main(String[] args){
System.out.println("This is our first package"
}
}
After you have that code created, you will need to compile it -but- you have to do things slightly differently.
First compile your code:
javac MyPackageClass.java
💡 Remember javac command always requires a file extension (typically .java)
Then compile your package:
javac -d . MyPackageClass.java
💡 The -d flag specifies the destination of where to save the class file - typically just use the .
like the example above to keep it in the same directory.
Importing is done like so:
import package.name.Class; // Import a single class
import package.name.*; // Import the whole package
public class HelloJavaWorld {
...
}
What is Scanner and how do we use it?
Scanner is just like Prompt method from javascript and python. Why it’s called scanner is beyond me.
Scanner waits for the user to input a value by using scan.nextInt();
method.
In a new file called Prompt.java, let’s set up our import.
import java.util.Scanner;
class Prompt {
public static void main(String[] args) {
...
}
}
To create the Scanner - we have to use some boilerplate:
Scanner scan = new Scanner(System.in);
This instantiates a new scanner looking for input (System.in)
.
Now we can create a prompt followed by a scanner that will pause the code until the user provides input:
System.out.println("Welcome. What is your name?");
scan.nextLine();
Let’s put it all together:
import java.util.Scanner;
class Prompt {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("What is your name?");
scan.nextLine();
}
}
To capture the value provided, we will want to create a variable and set it equal to the value of scan.nextLine()
like this:
String name = scan.nextLine();
Let’s tie together how to use an import, variables, Scanner, and string interpolation here:
import java.util.Scanner;
class Prompt {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("What is your name?");
String name = scan.nextLine();
System.out.println(String.format("Welcome to java, %s", name));
}
}
Compared to bash, this is a lot of code for something so simple. Let’s compare it to bash:
#!/bin/bash
read -p "What is your name? " name
echo "Welcome to bash, $name"
2 (technically 3 lines) to do what java does in 9. There is so much boilerplate in there. Luckily, the linter we installed from visual studio code is very good at helping you fill it in.
I personally like bash more but it’s got it’s own limitations like needing a linux OS. Knowing the right tool for the job is half the battle and the often times, the right tool is the one you know best. Having more languages you have learned to compare and contrast provides you with a tool box instead of node.js for everything. Seriously though, node.js isn’t a solution for everything.
If you want to use Scanner with types other than strings like nextInt()
or nextDoublt()
, then check out the documentation here: https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html
💡 When passing multiple values into a scanner, you’ll need to know about Delimiters.
Delimiters
Delimiters separates inputs. By default, blank space is considered a delimiter. In the following methods, blank space will require multiple scans for each input separated by a space:
scan.nextInt()
scan.nextLong()
scan.nextDouble()
scan.next()
Escape Characters in Java
If you would like to escape characters in java you’ll want to check out the table below. Nothing really new here compared to other languages I’ve used.
Escape sequence | What it does |
---|---|
\t | inserts a tab |
\n | inserts a new line |
\r | Inserts a carriage return (new line with the cursor at the beginning of the line |
\’ | inserts a single quote |
\” | inserts a double quote |
\\ | inserts a backslash |
Adding logic with conditionals and booleans
If you are familiar with any other language, booleans are pretty consistent. We have learned a number of variable types, boolean is the last one.
Boolean can only store true
or false
and java can use them to make decisions.
boolean alive = true;
boolean dumb = false;
Boolean values really aren’t useful unless they are written as a comparison.
How do you write comparisons in java?
Here is a list of comparator operators that you would use for logical statements.
Operator | What it does |
---|---|
> | Greater than |
< | Less than |
>= | Greater than or equal to |
<= | Less than or equal to |
== | Equal to (for ints/doubles/long/boolean) |
!= | Not equal to (for ints/doubles/long/boolean) |
equals | Equal to (for string values) |
!equals | Not equal to (for string values) |
You can compare any type of value
int homework = 100;
int test = 95;
System.out.println(homework > test);
// prints "true"
In the example above, we compare two values, the result is going to return a boolean. In this case true.
Control flow - if statements and how to use them
If statements control the flow of your application by performing actions if a statement is true and skipping it if it returns false.
In the previous section we discussed the difference between comparisons and how to use them. When comparisons are used in an if statement though, they are called conditions.
This is how they work:
if ( a > 1 ) {
// execute this code if a > 1 is true
} else if ( a < 0 ) {
// code runs if a < 0 is false
} else {
// runs if all conditions above are false (a = 1)
💡 You can use as many else if
statements but only one else
statement which is used as a “catch all”
How to chain comparisons into one condition
Logical operators allow you to compare many things at once. The two main ones are OR
& AND
.
Operator | What it does |
---|---|
&& | Allows you to compare if more than one comparator evaluates to true. Both comparators must evaluate to true to return a true condition. |
if ( comparison1 || comparison2 || comparison3 ) {
// if 1 of these are true, the whole condition is true
}
Cases or “Switches”
When would you want to use cases over if-statements?
A case (sometimes called a switch) compares one value (the argument) against a list of values (cases).
An example is months of the year - you know there are only 12 and writing if statements would be pretty painful. Case statements also run a tiny bit faster.
You wouldn’t want to use cases for something with an infinite range of potential values to compare, which would be when you’d want to use an if statement.
Here is what a case statement would look like:
switch(value1){
case value2: System.out.println(value2); break;
case value3: System.out.println(value3); break;
case value4: System.out.println(value4); break;
default: System.out.println("Invalid response"); break;
This “case-break” syntax is pretty common.
Functions
Functions perform a sole task and is reusable.
If you aren’t familiar with the concept of “DRY” ( Don’t Repeat Yourself) - you should be. Programing can easily get very challenging to read when you have repetitive code. Functions allow you to store code snippets and reuse them. It’s a foundational building block in any language. Functional programing is functional programing across the board.
There is a little boilerplate code involved with function declaration in java compared to other languages. Let’s take a look:
public class Functions {
public static void main(String[] args) {
doThing();
}
public static void doThing() {
System.out.println("Doing thing");
System.out.println("Doing thing");
System.out.println("Doing thing");
System.out.println("Did thing");
}
}
💡 What is the static part? For now all we need to know is that all functions we create need to be “static”. Void keyword means it’s going to return nothing - we will also get into that later.
How to use parameters with Java
Some functions require a value passed to it in order for it to perform its task. These values that are required to be passed to it are called parameters.
Parameters are passed inside the function’s ()
.
public class Functions {
public static void main(String[] args) {
rectangle();
}
public static void rectangle(double length, double width) {
double area = length * width;
System.out.println("The area of the rectangle is " + area + "\\n");
}
}
If you ran the code as it is, you’d get an error.
The method rectangle(double, double) in the type Functions is not applicable for the arguments ()"
What does that mean?
How to use Arguments in java
This means that the function rectangle
requires 2 arguments to be passed because it has 2 parameters that are not being met. It also enforces the value type so you cannot pass a string when the function is looking for a double for example.
Arguments and Parameters are a word salad that a lot of senior developers even confuse verbally. The difference between an argument and a parameter. Parameters are met, arguments are passed - this only matters if you are having an intellectual debate or trying to sound smarter than someone. Don’t be that guy.
So how do we fix the error?
public class Functions {
public static void main(String[] args) {
rectangle( 1.2, 2.6 );
}
public static void rectangle(double length, double width) {
double area = length * width;
System.out.println("The area of the rectangle is " + area + "\\n");
}
}
//The area of the rectangle is 3.12
You pass arguments in the function instantiator (the place where the function is being called). You separate each positional argument with a comma. Now in this specific case, the arguments being passed are positionally important because the 1st argument would be the length and the 2nd argument would be the width. Unlike other languages, you can’t just put recangle(width=2.6, length=1.2)
and expect it to run.
Capturing functional values outside of the function
In every language I’ve learned, they have something similar to return
keyword.
return
allows us to use functions as first class citizens - meaning a variable can be equal to a function and it’s value would be the final result of the function.
Return is the last thing that runs in a function and breaks the function when it’s called.
Now this gets weird and is more complex than other languages I’ve learned by a good measure. Hang in there.
function reserved keywords and errors
Remember earlier, how I spoke of the void
bit before? Well now it is coming into play.
void
means we aren’t returning anything that is calculated.
Let’s take a look at some code based on what we already know and adding in a return statement to try to capture square
. We can no longer use void
or we get an error because we are returning a value of area which is a double. So we have to change that type from public static void rectangle
to public static double rectangle
public class Functions {
public static void main(String[] args) {
double square = rectangle( 1.2, 2.6 );
System.out.println( square );
}
public static double rectangle(double length, double width) {
double area = length * width;
return area;
}
}
Does Java have any built in functions?
A built in function is one that java already made for you. System.out.println("argument")
is an example of a built in function.
void
is another synonym for println- it only performs the task of outputting your code to the console. How do I know?
Sorry, this is hard to capture but I’m pointing to the void when getting the doc reference for println
Here is a great article/resource on many of the built-in functions of Java: https://www.gcreddy.com/2021/07/built-in-methods-in-java.html
Comments
Let’s learn how to make comments 😃
Comments are the defining difference between good code and bad code in many cases. I want to start you off with good habits. Comments make your code more human readable. If you have ever read my code - I stick to fundamentals and anywhere that things get complicated, I comment, a lot. I’d rather over comment than under comment.
Commenting in Java is the same as it is with javascript and typescript with //
for a single line or /**.../
for a multiline.
A quick trick in VS code is to mash the command key and the /
key on a highlighted line.
What are doc comments?
There is something called documentation comments in java which allows you to generate documentation pages for reference.
...
/**
* Function name: rectangle
*
* Inside the function:
* 1. returns double value for area of a rectangle
*
* @param length
* @param width
* @return area
*/
public static double rectangle(double length, double width) {
double area = length * width;
return area;
}
This doc commenting allows you to get linter assistance when writing code. Vs code will auto fill out most of it just by typing /**
then mashing the return button.
The gif below is what it looks like and you can see the details when you hover over rectangle. This is something I really do like about java.
Scope
Class or function level scope is similar to global and functional scope in javascript.
Basically what you need to know is that in function scope, a variable inside a function’s curly brackets doesn’t exist outside of it.
In class scope, a function will have access to it’s variables and so will anything inside the class. Akin to global function but more narrowly inside the class.
This means that main doesn’t have access to any other functions and visa versa. If you did want that, just move the variable up inside of the class above the functions.
Loops
Loops enable us to repeat blocks of code while conditions are met - it unlocks the real power of development. Let’s learn how it works in java. There are two types of loops which control how many times a block of code is ran:
- for loop
- while loop
For loops
For loops are used when you know in advanced how many times a piece of code needs to run. This isn’t a new concept if you know any other languages.
While loops
Unlike a for loop, while loops don’t have any concept of a counter - they will just keep running as long as a condition remains true. These are best used when you don’t know how many times a piece of code will need to run.
For loops
These are built just like you are used to in Javascript.
for ( int i = 1; i <=3; i++) {
System.out.println(i)
}
// 1
// 2
// 3
While loops
These are built just like you are used to in javascript as well
number = 25;
while (number <= 50 ) {
System.out.println(i)
number++;
}
// prints all numbers 25-50
This example would have been best used in a for loop but it’s hard to make an example.
Break and Continue
continue
keyword is primarily used in if statements to say “if this condition is met, skip the rest of the run but don’t stop”.
break
keyword is similar to continue except it will stop the loop from running further.
Arrays in Java
Arrays can be used to store many values at once. The concept isn’t new in the programing languages I’ve learned. In fact it’s most similar to javascript.
int[] integers = { 1, 2, 3 };
The square brackets next to the type let java know it’s going to be an array of integers (in this specific example). All of the values that are stored, must be of the same type.
Similarly:
String[] words = { "one", "two", "three" };
double[] decimals = { 1.1, 2.2, 3.3 };
char[] letters = { 'a', 'b', 'c', 'd'};
Accessing Arrays
How to access an element in an array - elements are just the value. Each value/element has an index of the arrary. To access the second value, you’d want to use words[1]
which would result in “two”.
Every index starts with 0.
Looping through Arrays
Looping through data in an array is super easy and also very much like Javascript
String[] Kingdoms = { "Mercia", "Wessex", "Northumbria", "East Anglia" };
for ( int i = 0; i < 4; i++ ) {
System.out.println("Kingdom " + Kingdoms[i])
}
This isn’t ideal, length
would be a better way to do this. Length is a built in method which can be used to find the length (max index number) of an array. It would look like this:
String[] Kingdoms = { "Mercia", "Wessex", "Northumbria", "East Anglia" };
for ( int i = 0; i < kingdoms.length; i++ ) {
System.out.println("Kingdom " + Kingdoms[i])
}
💡 Java has a Arrays.toString(array_name)
method that can be used to print the array as a string.
Updating Arrays
We know how to loop through arrays and access their data but how do we update them?
Updating an array is done the same as accessing it and setting it equal to a new value. It’s that simple.
Kingdoms[1] = “Norfolk”;
2D arrays
This is probably my least favorite java concept so far.
A 2D array is an array that contains data like that of a table where you have rows of data. You bundle the arrays up into a single one. Sounds terrible doesn’t it? Well, I guess people use it.
x = 3;
y = 5;
int[][] integers = new int[x][y];
In the example above, you can see the double brackets to declare this is a 2D array. The x
would be replaced with a number to specify how many rows you would have and the y
would specify how many elements are in each row.
So you would have a 3x5 table of values.
It would return something that looks like this:
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
Objects and Classes
The idea behind “object oriented programming” is to find closely related variables and combine them into an object.
What if you had the below code:
String make = “Nissan”;
double price = 5000.0;
int year = 2020;
String color = "red";
drive( make, price, year, color );
While you could do it this way, it’s not going to look pretty when you have more than 1 kind of car.
You can only create objects from a class. So let’s learn how to make a class.
Create a class
In a file called Car.java created a class called Car like this:
public class Car {
String make;
double price;
int year;
String color;
}
This code above defines a car blueprint. It can be used over and over to create new Car
objects to define four car variables.
In a new file called Main.java review the following code
public class Main {
public static void main(String[] args) {
Car nissan = new Car();
nissan.make = "Nissan";
nissan.price = 5000.0;
nissan.year = 2020;
nissan.color = "red";
System.out.println(nissan.make);
System.out.println(nissan.price);
System.out.println(nissan.year);
System.out.println(nissan.color);
}
}
// Nissan
// 5000.0
// 2020
// red
The properties we created (make, price, year and color) become accessible to the object by using dot notation as you can see demonstrated above after we instantiate the nissan object with car nissan = new Car();
.
When you write a class that has variables ini t, it needs to have three things.
- Constructor
- Getters
- Setters
Constructor
A constructor runs as soon as you create an object. By default, each “field” or parameters in that class are set to 0 or null. So you have to update those values.
Constructors help to update fields quickly instead of 1 at a time.
Declare the level of access (usually public), the class name, then the parameters values using “this”.
<aside> 💡 Note the private - I’ll explain these in a moment.
</aside>
public class Car {
private String make;
private double price;
private int year;
private String color;
}
public Car (String make, double price, int year, String color ){
// this
this.make = make;
this.price = price;
this.year = year;
this.color = color;
}
The constructor always share the name of the Class that it’s in.
this
keyword - this will be used to distinguish between fields and parameters.
If we update our main file to look like this:
public class main {
public static void main(String[] args) {
Car nissan = new Car( "Nissan", 5000.0, 2020, "red");
System.out.println(nissan.make);
System.out.println(nissan.price);
System.out.println(nissan.year);
System.out.println(nissan.color);
}
}
We get the same output but this is much easier to write and use when there is more than 1 car.
Private vs Public
When do you label a function private or public?
Methods and Constructors should always be public so they are accessible anywhere.
Fields should be private - they should not be accessible outside of their class. This prevents updating fields values directly and ensuring the field’s values follow the application’s logic/requirements.
Getters
If a class has fields, you have to add getters. Since every field is private - you cannot access them from outside of the class meaning the state of the object is preserved.
We use “getter” is a method (function) to copy and return the a field’s value.
A getter is public and typically lowerCamelCase.
Since we have four fields (make, price, year, color) we need 4 getters.
public class Car {
private String make;
private double price;
private int year;
private String color;
}
//Constructor
public Car (String make, double price, int year, String color ){
// this refers to the private fields
this.make = make;
this.price = price;
this.year = year;
this.color = color;
}
// Getter
public String getMake() {
return this.make;
}
public double getPrice() {
return this.price;
}
public int getYear() {
return this.year;
}
public String getColor() {
return this.color;
}
Now the function call “get___()” returns the private value when you call “nissan.field”.
Setter
If a class has fields, you need to create setters. You create a field setter to update a field’s value.
public class Car {
private String make;
private double price;
private int year;
private String color;
}
// constructor
public Car (String make, double price, int year, String color ){
this.make = make;
this.price = price;
this.year = year;
this.color = color;
}
//Getters
public String getMake() {
return this.make;
}
public double getPrice() {
return this.price;
}
public int getYear() {
return this.year;
}
public String getColor() {
return this.color;
}
public String setMake() {
this.make = make;
}
public double setPrice() {
this.price. =price;
}
public int setYear() {
this.year = year;
}
public String setColor() {
this.color = color;
}
Object Inheritance
classObject
is the parent class of every object in Java. Everything besides primative types (variables that store data such as boolean, string, double, etc.) share classObject as their parent. This means every class inherits methods from the class object.
This is how we have built-in methods.
Override
A class can customize or “overide” methods that it inherits.
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
}
When you override, you change the logic of an inherited method. If you override equal
you have to also override a matching hashCode()
method. Objects that are equal must always have a matching hashCode.
Object Polymorphism
Objects are polymorphic meaning they will take many forms.
Ultimately, every object is of the Object class, meaning if you created a new object called Person, due to inheritance, it’s still of the Object class.
Child classes and Parent classes
A class that extends another class inherits from it.
Let’s say you have a class called Product and you want to create a child class of it called “Shirt”. Shirt would extend the Product class to have more fields but still inherit all the pieces of a Product class.
The syntax looks like this:
public class Shirt extends Product{
private String size;
public Shirt(String size, double price, String color);
When two classes share common fields, it’s important to never define the same fields in each class. Instead, each class should inherit common fields from a parent class.
Super
super
keyword refers to the “superclass” or “Parent” class.
super()
refers to the constructor of the superclass (parent class).
To call the constructor of the parent class you simply pass arguments into super like this: super(arguments)
.
public class Pants extends Product{
private int waist;
public Pants(int waist, double price, String color, String brand){
super(price, color, brand)
this.waist = waist;
}
}
Not that we create Pants as a child of Product and since all products share price, color, and brand, we inherit those since we extend Product but in order to update them, we have to pass them as arguments to super and then update Pants with waist.
This all goes back to Polymorphism.
The child class uses it’s constructor to update it’s unique fields and uses the parent constructor to update inherited fields.
Abstract
If a class has the sole purpose of being a parent class for inheritance purposes, it should be made abstract
. In the pants-product example, it wouldn’t make sense to allow a user to create a product with out being a child of Product. Abstract prevents creating objects of its class.
public abstract class Product {
...
}
If the parent class defines an abstract method, the child class is forced to override (extend) it. We typically want this behavior.
Enums
Enums are a collection of static final constants. Constants, by definition, do not change and can only be a limited set of values.
Enums are basically a list of allowed values for a given variable. This is a new concept for me.
public class Shirt extends Product{
public enum Size {
SMALL, MEDIUM, LARGE, XL, XXL
}
private Size size;
public Shirt(Size size, double price, String color, String brand){
super(price, color, brand);
this.size = size;
}
Enum constants are always capitalized. We would then want to change the type of “size” to the enum “Size”.
Conclusion
You now have all the necessary building blocks to go out and code in Java. The good news is, there is tons more to learn.
While Java may not be my favorite language - it certainly has its advantages and disadvantages. As the old saying goes, the best tool for the job is the one you know. I am happy it's another tool in my tool bag that I can apply given the right job.
If you found this article helpful or you have questions, you can drop a comment below.
Drew is a seasoned DevOps Engineer with a rich background that spans multiple industries and technologies. With foundational training as a Nuclear Engineer in the US Navy, Drew brings a meticulous approach to operational efficiency and reliability. His expertise lies in cloud migration strategies, CI/CD automation, and Kubernetes orchestration. Known for a keen focus on facts and correctness, Drew is proficient in a range of programming languages including Bash and JavaScript. His diverse experiences, from serving in the military to working in the corporate world, have equipped him with a comprehensive worldview and a knack for creative problem-solving. Drew advocates for streamlined, fact-based approaches in both code and business, making him a reliable authority in the tech industry.