Java Class Walkthrough¶
This is a full implementation of a Java class, annotated so you know what's what. (Feedback is welcome: ted@SpiralLearningLLC.com)
Package¶
package com.welltestedlearning.kiosk;
-
package
is a Java keyword that tells Java the name of the package (namespace) this class is in.Default Package
If you don't have
package
in your class, it is put in a "default" package that has no name. In general, this is not recommended and you should always put all classes (and interfaces, and enums) into a named package.
Import¶
import java.util.ArrayList;
import java.util.List;
import
tells the compiler which package to look at for classes you're using that are not in the current package. In this case, we don't need to import anything from thecom.welltestedlearning.kiosk
package, but we do need to import theList
andArrayList
classes.
Class Declaration¶
Finally we get to declaring the MealOrder class itself.
public class MealOrder extends Order {
-
public
indicates that this class is visible from any other class in the system. -
class
means we're defining a class named MealOrder. This class' name has two words, meal and order, so when we combine them into a single word, we use camel-case with the first letter capitalized. -
extends
is used for inheriting, or subclassing from another class, in this case a class called Order. (Remember that class names start with an upper-case letter.)Reading
extends
We would read this as: MealOrder subclasses Order or MealOrder inherits from Order.
Member Variable¶
Here we're declaring a member (or instance, or non-static) variable, named items
that's of type List<MenuItem>
and points to (references) an instance of an ArrayList
.
private List<MenuItem> items = new ArrayList<>();
-
private
here indicates that only (non-static) code within this class (e.g., inside non-static methods) can access this variable. Other classes cannot even see that it exists.- Because it's a variable, it starts with an initial lowercase letter and follows the camel-case form.
-
List<MenuItem>
is aList
(a Java Collection class) that is holding objects of typeMenuItem
.Note
This list can hold instances of
MenuItem
, or subclasses ofMenuItem
, or any class that implementsMenuItem
(though only ifMenuitem
is an interface). -
new
is how instances of a class are created (or instantiated) by calling the target class' constructor (in this caseArrayList()
, the no-argument constructor).- Since we already defined the types of objects this list can hold (
MenuItem
), we don't need to repeat that, so we can use the shorthand:<>
.
- Since we already defined the types of objects this list can hold (
Static Variable¶
Here we declare a static variable of type int
to keep track of the number of orders:
private static int orderCount = 0;
-
private
means it's only accessible by code inside of this class. -
static
here means that there's only oneorderCount
for any and all instances of this class. We say that this variable belongs to the class and not to an instance (or object). It's accessible from inside of any constructor and any method -- static or non-static.
Constant¶
private static final int ORDER_LIMIT = 10;
ORDER_LIMIT
here is a constant, that is, it cannot be changed during runtime, and there's only one copy of it due to the static
keyword.
In addition, because it's marked as private
, it can only be accessed from code within this class.
Static Method¶
public static MealOrder createBurgerOnlyOrder(BurgerOption burgerOption) {
return new MealOrder(burgerOption);
}
This static
method is a creation method (not to be confused with the factory method pattern -- see this article to learn about the difference and purpose).
We also have a constructor that looks similar, but creation methods are useful when you end up creating lots of constructors that vary slightly. See this article that discusses the reasoning.
Entry Point: main method¶
public static void main(String[] args) {
This is an entry point into the application that would be executed if you did
java MealOrder
at a terminal command line.
Entry points must always have the signature of public static void main(String[] args)
so that the Java runtime knows what to look for.
MealOrder drinkOrder = new MealOrder();
drinkOrder.addDrink(Drink.DRINK_LARGE);
drinkOrder.display();
-
12
Here we're declaring a variable nameddrinkOrder
(initial lowercase letter), which points to (references) a newly created instance ofMealOrder
by calling the default (no-arg) constructor. -
13
Next we call (invoke) theaddDrink
method (a non-static method) and pass in a constantDRINK_LARGE
(all uppercase) that would be found in theDrink
class. -
14
Finally we invoke thedisplay()
method.
MealOrder burgerOrder = createBurgerOnlyOrder(BurgerOption.REGULAR);
burgerOrder.display();
}
In this part of the main method, 15
we invoke the creation method that was defined above, passing in the constant REGULAR
found in the BurgerOption
class (which is probably an enum given the suffix Option
.
Calling Static Method
Note that we didn't need to specify the class name MealOrder
when invoking the createBurgerOnlyOrder
method, since it's in the current class, so the current class is assumed.
We end the main method 16
by invoking display()
on this second instance of MealOrder.
Constructors¶
The first constructor is the "no argument" constructor:
public MealOrder() {
Unlike other methods, constructors don't have a name, though they look like they have the same name as the class. Another way of looking at the constructor is like this:
public MealOrder <init>() {
This makes it more clear that the return value of the constructor is an instance of the class.
In fact, <init>
is the true name of a constructor, but only used internally by the compiler, so when we write the constructor, we say that the name of the constructor is the same as (and must match) the name of the class.
if (orderCount > ORDER_LIMIT) {
throw new IllegalStateException("Too many orders!");
}
orderCount = orderCount + 1;
}
We first check to see if the static variable, orderCount
, exceeded the order limit (a constant, being all uppercase), and if so, we throw
an instance (created by the new
) of the IllegalStateException
to abort the creation of the MealOrder.
If we're fine, we increment the order count and the constructor completes successfully.
Static Variable Naming
Some coding styles use a prefix of s_
for static variables and m_
for member variables.
There are also coding styles that use _
and __
(single- and double-underscore) as prefixes to differentiate static and member variables.
These styles have become less common as IDEs, such as IntelliJ IDEA and Eclipse, color such variables differently, so you no longer need the name to tell you what's what.
If your code has so many variables that you can't easily tell them apart, it might be time for some refactoring. :)
This constructor takes a single argument (a reference to a BurgerOption
):
public MealOrder(BurgerOption burger) {
this();
addBurger(burger.name().toLowerCase());
}
-
The
this();
statement (25) is how we call the first constructor. We want to invoke the no-arg constructor so that the order limit code is executed, but without having to duplicate that code here.The Meaning of
this
Since constructors don't have a name that we can use, Java uses
this
as a way of saying "hey, call the constructor for this class". You will also seethis
used to refer to the current instance of the object in order to access member variables, e.g.,this.items = null
is the same asitems = null;
. Most of the time you don't need to prefix member variables withthis
, unless there's naming collision, e.g., in this methodprivate int limit = 0; public void setLimit(int limit) { limit = limit; }
it's unclear which
limit
is which, since there's the member variablelimit
, and the parameterlimit
. In this case you can tell the Java compiler which one you mean by doing:this.limit = limit;
This way the compiler knows that you're assigning the value of the parameter
limit
to the member variablethis.limit
.Also note that constructors can only be called from other constructors.
-
We then add a new burger (26) by extracting the name, converting it to lowercase, and invoking the Burger's constructor.
Method Chaining
This sequence of calling a method right after another method is called chained invocations. It's exactly the same as if we did:
but since we don't need these intermediate variables, we can chain them together:String name = burger.name(); String nameLower = name.toLowerCase(); add(new Burger(nameLower));
burger.name().toLowerCase()
.
Non-Static Methods¶
The meat of most of your application will be in non-static methods, called instance or member methods -- or sometimes just methods.
Public Methods¶
Here's a public
method, which means any other code that has an instance of the class can call it:
public void addBurger(String burgerType) {
items.add(new Burger(burgerType));
}
So, if you have MealOrder meal = new MealOrder()
, you can do meal.addBurger("cheeseburger")
.
Private Methods¶
These methods are private
, meaning only other methods in the same class can call them.
Private methods are a great way to give meaningful names to fragments of code: instead of having 30 lines of code in a public
method, it might be more readable to have that method call several private
methods.
public void addDrink(String drinkType) {
addDrink(new Drink(drinkType));
}
private addDrink(Drink drink) {
addItem(drink);
}
private addItem(MenuItem item) {
items.add(item);
}
Here (31), the public addDrink()
method calls (or delegates to) the internal addDrink()
method(35) that takes a Drink
object instead of just a String
, which itself delegates the work to the private addItem
method(39) that takes a more general MenuItem
object.
That's a Wrap¶
That wraps up the dive into all the parts that make up a fairly typical Java class. Feedback or questions are always welcome at: ted@SpiralLearningLLC.com.