Lesson Weekend

In previous lessons we learned how to create, compile, and run basic Java applications. We also explored declaring custom classes to act as a blueprint to a limitless number of objects! In this lesson we'll combine these two concepts by exploring how to add our own custom classes into Java applications.

Multiple .java Files

Before we begin, note that integrating custom classes into a Java applications means we'll have two .java files in our apps:

  • One will contain the user interface or command line interface logic, just as we saw in previous lessons. This file will be responsible for prompting the user, gathering user input, calling any methods, and returning information to the user. This is similar to the "frontend" or "user interface logic" we learned about in Intro to Programming. Moving forward, we will always name this file App.java.

  • The other will contain our custom class. This includes the class declaration itself, our constructor, and any additional methods. we'll refer to this as the class file or the business logic. This is like the "backend" or "business logic" we learned about in Intro to Programming.

Setup

As we discussed in Writing a Java Program, every basic Java application must contain a class and a main() method.

In our existing project, let's create our App.java file. Remember, it will be responsible for our command line interface or user interface. We'll add the following code:

src/main/java/App.java
public class App {
 public static void main(String[] args) { //type psvm + tab to autocreate
 }
}

Accessing Custom Classes in Java Applications

Previously, we included any logic we wanted to run when we launched our program in the main() method. Like asking the user questions through the console, and gathering their responses. But now we have an entire separate file for our Vehicle class! How do we include all that code in our application?

Packages

Because our Vehicle.java code resides in a different package, called models, we have to import it into App.java. Use the windows + enter( alt + enter on your personal machine) command to import it into App.java. Packages are simply a way to organize code. There are user-defined packages that developers create themselves, and there are built-in packages already included in Java.

We needed to manually import Java's built-in BufferedReader class in previous lessons because it did not exist in the same package as our application. It exists in the java.io package built-in to Java. So, in order to use its methods (like readLine()), we had to manually import the BufferedReader class with by declaring import java.io.BufferedReader at the top of the file. If you look at the top of this file now, you can see that we are importing models.Vehicle in the same way:

Instantiating Classes in Java Applications

Alright. We have a basic Java application in place, and a custom class with a constructor. And, because they both reside in the same package, we know our user interface file will have access to our Vehicle class automatically. Perfect. Next, let's create several different vehicles by including the following code in our main() method:

src/main/java/App.java
import models.Vehicle;

public class App {
 public static void main(String[] args) {

   Vehicle hatchback = new Vehicle();
    hatchback.year = 1994;
    hatchback.brand = "Subaru";
    hatchback.model = "Legacy";
    hatchback.miles = 170000;
    hatchback.price = 4000;

    Vehicle suv = new Vehicle();
    suv.year = 2002;
    suv.brand = "Ford";
    suv.model = "Explorer";
    suv.miles = 100000;
    suv.price = 7000;

    Vehicle sedan = new Vehicle();
    sedan.year = 2015;
    sedan.brand = "Toyota";
    sedan.model = "Camry";
    sedan.miles = 50000;
    sedan.price = 30000;

    Vehicle truck = new Vehicle();
    truck.year = 1999;
    truck.brand = "Ford";
    truck.model = "Ranger";
    truck.miles = 100000;
    truck.price = 4000;

  }
}
  • Here, the lines that look similar to Vehicle truck = new Vehicle(); are creating new instances of the Vehicle class.

  • Just like any other variable, we must declare a type. In our case, the type is Vehicle, because we're creating a new instance of our custom Vehicle class. This is no different than declaring a variable as a String, like this: String testVariable = "hey there";, we're simply using our own custom-made class instead of one built into Java.

  • Each Vehicle needs a variable name. We call the first one hatchback, for instance.

  • Since each Vehicle is a new instance of the Vehicle class, we must use the keyword new. This instantiates a new object. When you create an object it is called instantiation, because that object is called an instance of its class. Each individual vehicle we created above (truck, sedan, suv, hatchback) is an instance of the class Vehicle.

  • Finally, it’s a new Vehicle, so we end the line with Vehicle(). We’ll address what the parenthesis are for later. For now, just know they need to be there.

The Dot Operator

To store a value in a property of an object, we use this operator: ., called the dot operator. It means "look inside of the object to the left of this symbol for the property to the right of this symbol".

So when we state hatchback.year = 1994; We are essentially saying: "Find the object stored in the variable hatchback. Locate its year property." Then, we use the assignment operator, or = to set the value of that property to a specific number. Like 1994. This is the same as in JavaScript.

Exposing Class Fields

But how do we know everything has been successfully saved in our objects? Let's add some code to our program that prints out the details for each vehicle in the command line. This way, employees of the Car Dealership may quickly see a list of all cars on the lot, and details about them. We'll add all the instances of Vehicle that we've created to an Array, and loop through it to display details about each:

src/main/java/App.java
public class App {
 public static void main(String[] args) {

   Vehicle hatchback = new Vehicle();
    hatchback.year = 1994;
    hatchback.brand = "Subaru";
    hatchback.model = "Legacy";
    hatchback.miles = 170000;
    hatchback.price = 4000;

    Vehicle suv = new Vehicle();
    suv.year = 2002;
    suv.brand = "Ford";
    suv.model = "Explorer";
    suv.miles = 100000;
    suv.price = 7000;

    Vehicle sedan = new Vehicle();
    sedan.year = 2015;
    sedan.brand = "Toyota";
    sedan.model = "Camry";
    sedan.miles = 50000;
    sedan.price = 30000;

    Vehicle truck = new Vehicle();
    truck.year = 1999;
    truck.brand = "Ford";
    truck.model = "Ranger";
    truck.miles = 100000;
    truck.price = 4000;

    Vehicle[] allVehicles = {hatchback, suv, sedan, truck};

    System.out.println("All Vehicles:");

    for ( Vehicle individualVehicle : allVehicles ) {
      System.out.println( "----------------------" );
      System.out.println( individualVehicle.year );
      System.out.println( individualVehicle.brand );
      System.out.println( individualVehicle.model );
      System.out.println( individualVehicle.miles );
      System.out.println( individualVehicle.price );
    }

 }
}

First, the line Vehicle[] allVehicles = {hatchback, suv, sedan, truck}; stores our vehicles in a Array named allVehicles. We create this array just like we would create an Array of Strings or ints, but this is a list of Vehicles, so we state Vehicle[] when declaring the array's data type.

Then, in the following lines we reference each Vehicle object, accessing the fields, or member variables of each:

...
      System.out.println( individualVehicle.year );
      System.out.println( individualVehicle.brand );
      System.out.println( individualVehicle.model );
      System.out.println( individualVehicle.miles );
      System.out.println( individualVehicle.price );
...

We’re writing some text in a for each loop to the console like we’ve done in previous lessons, but we refer to each property by accessing that field of each Vehicle, which we refer to as individualVehicle in the loop.

We can compile and run by choosing Run > Run > App (after running an app the first time, you can see the small green play button in the menu bar or in the bottom left, next to your terminal output). You should see the following lines in the terminal:

All Vehicles:
----------------------
1994
Subaru
Legacy
170000
4000
----------------------
2002
Ford
Explorer
100000
7000
----------------------
2015
Toyota
Camry
50000
30000
----------------------
1999
Ford
Ranger
100000
4000

Let's add one more Vehicle to our dealership to see how useful this is. This time we don't need to modify our class, or our loop! All we need to do is instantiate some more objects and add them to our allVehicles array:

src/main/java/App.java
public class App {
 public static void main(String[] args) {

   Vehicle hatchback = new Vehicle();
    hatchback.year = 1994;
    hatchback.brand = "Subaru";
    hatchback.model = "Legacy";
    hatchback.miles = 170000;
    hatchback.price = 4000;

    Vehicle suv = new Vehicle();
    suv.year = 2002;
    suv.brand = "Ford";
    suv.model = "Explorer";
    suv.miles = 100000;
    suv.price = 7000;

    Vehicle sedan = new Vehicle();
    sedan.year = 2015;
    sedan.brand = "Toyota";
    sedan.model = "Camry";
    sedan.miles = 50000;
    sedan.price = 30000;

    Vehicle truck = new Vehicle();
    truck.year = 1999;
    truck.brand = "Ford";
    truck.model = "Ranger";
    truck.miles = 100000;
    truck.price = 4000;

    Vehicle crossover = new Vehicle();
    crossover.year = 1998;
    crossover.brand = "Toyota";
    crossover.model = "Rav-4";
    crossover.miles = 200000;
    crossover.price = 3500;

    Vehicle[] allVehicles = {hatchback, suv, sedan, truck, crossover};

    System.out.println("All Vehicles:");

    for ( Vehicle individualVehicle : allVehicles ) {
      System.out.println( "----------------------" );
      System.out.println( individualVehicle.year );
      System.out.println( individualVehicle.brand );
      System.out.println( individualVehicle.model );
      System.out.println( individualVehicle.miles );
      System.out.println( individualVehicle.price );
    }

 }
}

And, if we run again, we see the additional vehicle appears at the bottom of our list of all vehicles in the terminal!

All Vehicles:
----------------------
1994
Subaru
Legacy
170000
4000
----------------------
2002
Ford
Explorer
100000
7000
----------------------
2015
Toyota
Camry
50000
30000
----------------------
1999
Ford
Ranger
100000
4000
----------------------
1998
Toyota
Rav-4
200000
3500

Since all our Vehicle objects use the same "blueprint" defined by our Vehicle class, we know the code within our loop will work for any Vehicle!


Example GitHub Repo for Car Dealership