Prelude

First of all, thank you for your time and for your patience.

I know that when I was in school I never wanted to read a book and, except for The Cay and Great Expectations, I got away without having to.

So while it is hypocritical for me to ask this of you, please read this book like a book and go from the start to the end, one section at a time.

At the end of each section there will also be challenges. I want you to at least attempt all of them before moving on to the next section.

This book is written specifically for those folks that feel like giving up, like they are too stupid to get it, or like they didn't understand a damn thing their professor has said for the last three months.

I see you. You are not stupid. This is not your fault.1

1

probably.

Asking for Help

If anything in this confuses you or feels intimidating please, please reach out to someone.

If you are in a position to, make use of your teacher. That is what they are there for.

If you are not, on every page there is a button in the top right corner which you can click to ask a question.

When you do, keep in mind these basic rules.

1. You get what you pay for

Often the people willing to help you will be volunteers.

Do not expect them to do your assignments for you, do not expect them to be available at a moments notice, and accept that they are under no obligation to help anyone or you in particular.

2. Ask early

If you are struggling with something and you have a deadline in 5 hours, that might not be enough time to do anything.

Asking questions well before a deadline is best for all those involved.

3. Don't Ask to Ask

Don't ask to ask, nor only say hello, just ask your actual question right away.

Consult https://dontasktoask.com/ for what that means exactly.

Toy Problems

As you go through this book there will be a lot of what can be considered "toy problems."

That is, you will be shown or asked to write programs that have no obvious real world use. They will be similar in spirit to math problems like "if you have 8 apples and I take 3, how many apples do you have left?"

The intent is not for these to be annoying, although I am sure they will be. The intent is for these problems to help you build an understanding of mechanics and structure.

Lies

At various points in this book I am also going to lie to you. Specifically I will make lies of omission.

If there are five ways to do something, I might pretend that there is only one way to do it until I give you enough context so that I can talk about the other four.

This can be particularly annoying if you are in a course that is teaching things in a different order or if you feel rushed to just get some project done.

I get that. I just ask that you trust me and go in the sequence I am laying out. I am honestly trying to make it so that you end with a stronger understanding than you would have otherwise.

There is the question mark in the top right of every page.

Getting Started

There are a lot of ways to "get set up" to run Java code.

For the purposes of this book, I am going to recommend that you start with replit.com.

It requires an internet connection and you will have to make an account, but of the available options it is the easiest to set up.

If you are in school and your teacher has helped you get set up in some other way it is okay to skip this section and just do it the way you were shown.

All that matters is that in the end you have the ability to run and edit the following code.

FerrisMeaning
Ferris with a question markThis code does not compile!
Ferris throwing up their handsThis code panics!
Ferris with one claw up, shruggingThis code does not produce the desired behavior.

In most situations, we’ll lead you to the correct version of any code that doesn’t compile.

void main() {
    System.out.println("Hello, World");
}

Step 1. Make an account

Go to replit.com and find the "Sign Up" button. Websites change every now and then so these screenshots might be out of date.

Picture of the sign up button on replit's website

Click it and sign up for an account.

Picture of the sign up form on replit's website

Step 2. Create a Java REPL

Find the "Create REPL" button and click it.

Picture of the create repl button on replit's website

Then you should be presented with a menu that lets you search for the type of REPL to create. Find the Java template and click "Create".

Unfilled in create from template menu on replit

Filled in create from template menu on replit

Step 3. Run code

You should land on a screen with a big green run button, an open file called "Main.java", and a blank window labeled "console".

Picture of an unran hello world program

Click it and you should see the text Hello, world! appear under the console window.

Picture of a hello world program after running

First Steps

If you made it through the Getting Started section you've successfully run this program.

void main() {
    System.out.println("Hello, World!");
}

This "prints" - not in the sense of a physical printer, but like "displays on the screen" - the text "Hello, World!".

Its a tradition for this to be your first program in any language.

We aren't quite at the point where I can explain what void main() means, but all you need to know for now is that it is what Java looks for to know where to start the program.

void main() {
    < WRITE YOUR CODE HERE >
}

So for all intents and purposes, this is the whole program.

System.out.println("Hello, World!");

This bit of magic here - System.out.println - is a "statement" that "prints" the text inside the ( and ) as well as a "new line" to the screen.

print with new line.

If you were to replace it with System.out.print, then the output would lack that new line. This makes the following program be functionally identical to the first.

System.out.print("Hello, ");
System.out.print("World");
System.out.println("!");

Which, when we add back void main(), looks like this.

void main() {
    System.out.print("Hello, ");
    System.out.print("World");
    System.out.println("!");
}

You should get in the habit of, whenever you see some bit of code, trying to physically type it out, run it, tweak it, and play with it.

So try playing around with this program. If you are not actively engaging then the whole thing is a bit of a wash.

Comments

At various points, I am going to leave "comments" in the code. Comments are parts of the code that are solely there for a human to be able to read as an explanation and can be written in regular words.

In-line commenting

void main() {
    // This prints hello world!
    System.out.println("Hello, World!");
}

The rules for this are that if you see a //, everything after that in the same line is ignored.

If you put // in front of something that is "code" and not an English explanation we colloquially call that "commenting out" the line.

void main() {
    System.out.println("Hello, World!");
    // The line that prints out goodbye is "commented out"
    // System.out.println("Goodbye!");
}

You might want to do that at various points where you want to see what happens if you "turn off" parts of the code.

Multi-line commenting

If you put /* in the code then everything up until the next */ will be treated as a comment. The distinction here is that this style of comment can span multiple lines.

void main() {
    /*
        I have eaten
        the plums
        that were in
        the icebox
        and which
        you were probably
        saving
        for breakfast
        Forgive me
        they were delicious
        so sweet
        and so cold
    */
    System.out.println("Hello, World!");
}

So that's a mechanism you will see me use and you can use yourself however you see fit.

Semicolons

The ; at the end of each of those lines is a "semicolon".

System.out.print("Hello, "); // <-- this thing
                       //  ^

It indicates that the statement has finished. A "statement" is a line of code that "does something." The reason we call it a statement and not just a "line of code" is that it can technically span multiple lines and be more complicated than these examples.

System.out.print(
    "Hello, "
);

The ; at the end is needed so that Java knows that the statement is over. You need to put a ; at the end of every statement. If you do not, Java will get confused and your code will not work.

If you happen to have an extra semi-colon or two that is technically okay. It just reads it as an "empty statement." It's pointless, but it is allowed.

System.out.print(
    "Hello, "
);;

Or even

System.out.print(
    "Hello, "
);

  // Technically legal, but kinda sus

  ;;;;;;;;;;;;;
  ;;;        ;;
  ;;;        ;;
  ;;;;;;;;;;;;;
  ;;   ;;;   ;;
  ;;;;;;;;;;;;;
  ; ;       ; ;
  ; ;       ; ;
  ;;;       ;;;

Formatting

You may have noticed that after each { all the code that comes after it is "indented" in one "level."

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

I will kindly ask that you try to stick to this rule when writing your own code as well. If you try to find help online and you haven't, it will be hard for people to read your code.

This is easier to show than to explain in detail. Just try to make your code look like this.

void main() {
    System.out.println("Hello, World!");
}

And not like this.

void main()
{
System.out.println("Hello, World!");}

And keep in mind that this rule of thumb applies to every language constrict that requires a { and } many of which I will introduce later.

Challenges

At the end of each larger section, I am going to write down some things you can do to make sure you get what was just gone over.

The rules for this are

  • Try to use only the information given up to this point in this book.
  • Try not to give up until you've given it a solid attempt

Challenge 1

Write a program that prints your name twice. So if your name is "Jasmine", the output of the program should be this.

Jasmine
Jasmine

Challenge 2

What will this program output when run? Write down your guess and then try actually running it.

void main() {
    System.out.println("A");
    //System.out.println("B");
    System.out.println("C");//
    System.out.println("D");
    /*
    System.out.println("E");
    System.out.println("F");*/
    System.out.println("G");
}

Challenge 3

There are four semicolons in this perfectly functional program. Delete one of them at random and see what the errors you get look like.

How could you use that error to figure out where you might have forgotten to put a semicolon?

void main() {
    System.out.println("Apple");
    System.out.println("Banana");
    System.out.println("Clementine");
    System.out.println("Durian");
}

Local Variables

Mechanically, the next thing to cover is "variables".

void main() {
    String boss = "Jaqueline";
    System.out.println(boss);
}

A variable declaration has three components - the "type", the "name", and the "initial value".

     String boss = "Jaqueline";
//   type   name   initial value

In this case, we are declaring a variable called "boss" and assigning it the initial value of "Jaqueline". Its "type" is "String", which I'll explain in more detail a bit ahead.

After you declare a variable and assign it a value, the "name" refers to the value on the right hand side and you can use that name instead of the value.

// Does the same thing as System.out.println("Jaqueline");
String boss = "Jaqueline";
System.out.println(boss);

Naming

It is a social convention1 that local variables be named likeThis.

That is if their name is one word, that word should be in lowercase.

String apple = "Red Delicious";

If it is multiple words, the first word should be lowercase and the others should start with a capital letter.

This convention is called camelCase because the capitals looks like the humps on a Camels back2.

Just like proper formatting, sticking to this style will increase your chances of someone online being able to help you with your code.

1

Trapped! By societal convention! 2: And because doing this will increase your body's ability to retain water by ~34%

Reassignment

After a variable is declared and assigned an initial value, that value can be later reassigned.

void main() {
    String boss = "Jaqueline";
    System.out.println(boss);
    boss = "Chelsea"
    System.out.println(boss);
}

Reassignments just involve the name and the new value. The type should not be redeclared.

    boss = "Chelsea";
//  name   new value

After a variable is reassigned, the value associated with the name will reflect the new value from that point in the program onwards.

void main() {
    String boss = "Jaqueline";
    // This will output "Jaqueline"
    System.out.println(boss);
    boss = "Chelsea"
    // But this will output "Chelsea"
    System.out.println(boss);
}

Delayed Assignment

The declaration of a variable and the assignment of its initial value can be done separately.

void main() {
    String contestWinner;
    contestWinner = "Boaty McBoatface";

    System.out.println(contestWinner);
}

In which case the "variable declaration" will only have the "type" and "name" components.

   String contestWinner;
//  type  name

And the "initial assignment" will look identical to a "re-assignment".

   contestWinner = "Boaty McBoatface";
//   name            initial value

Before an initial value is assigned to a variable, it is not allowed to be used.1

void main() {
    String contestWinner;
    // This will not run, since Java knows that
    // you never gave contestWinner an initial value.
    System.out.println(contestWinner);
}
1
There is no direct use for separating declaration and initial assignment at this point,
but [it's a surprise tool that will help us later](https://knowyourmeme.com/memes/its-a-surprise-tool-that-will-help-us-later).

Types

When a variable is declared, it is given a type.

String color = "green";

In this case, the variable color is declared to have the type String. After this declaration, color cannot be assigned to a value that is not a String.

// A number is not a String!
String color = 8;

This applies to all situations where a variable might be given a value, including delayed assignment and reassignment.

One mental model is that types are like shapes. If the type of something is a circle, you can only put circles into it.

◯ thing = ◯;

You cannot put square pegs in that round hole.

// If Java actually functioned in terms of shapes, this
// would not work since a Square is not the same "type"
// of thing as a Circle.
◯ thing = ▢;

Final Variables

There is an optional extra part to a variable declaration where you can mark a variable as "final", meaning its value can never be reassigned.

void main() {
    final String coolestChef = "Anthony Bourdain";
    System.out.println(coolestChef);
}

If you try to reassign a final variable, Java will not accept your program.

void main() {
    final String coolestChef = "Anthony Bourdain";
    System.out.println(coolestChef);

    // I'm sorry, but no. Cool guy, but no.
    coolestChef = "Gordan Ramsey";
    System.out.println(coolestChef);
}

This is useful if you have a lot of lines of code and want the mental comfort of knowing you couldn't have reassigned that variable at any point between its declaration and its use.

final String genie = "Robin Williams";
// imagine
// 100s of lines
// of code
// and it is
// hard to
// read all of it
// at a glance
// ......
// ......
// You can still be sure "genie"
// has the value of "Robin Williams"
System.out.println(genie);

Variables whose assignment is delayed can also be marked final.

final String mario;
mario = "Charles Martinet";

The restriction is the same - after the initial assignment, the variable cannot be reassigned.

final String mario;
// An initial assignment is fine
mario = "Charles Martinet";
// But you cannot reassign it afterwards
mario = "Chris Pratt";

The downside to this, of course, is more visual noise. If a variable is only "alive" for a small part of the code, then adding final might make it harder to read the code, not easier.

Inferred Types

In many cases, Java is smart enough to know what the type of a variable should be based on what it is initially assigned to. In these cases, you can write var in place of the type and let java "infer" what it should be.

// Since what is to the right hand side
// of the = is in quotes, Java knows that
// it is a String.
var theDude = "Lebowski";
System.out.println(theDude);

You cannot use var with variables whose assignment is delayed.

// With just the line "var theDude;",
// Java doesn't know enough to infer the type
var theDude;
theDude = "Lebowski";
System.out.println(theDude);

You can use var with final to make a variable whose type is inferred and cannot be reassigned.

final var theDude = "Lebowski";
System.out.println(theDude);

Important to note that even if Java is smart enough to automatically know the type, you might not be yet. There is no shame in writing out the type explicitly.

String theDude = "lebowski";

Challenges

Remember the rules for this are

  • Try to use only the information given up to this point in this book.
  • Try not to give up until you've given it a solid attempt

Challenge 1

What will this program output when run? Write down your guess and then try running it.

void main() {
    String mascot = "The Noid";
    System.out.println(mascot);
    mascot = "Pizza the Hut";
    System.out.println(mascot);
    mascot = "Little Caesar";
    System.out.println(mascot);
}

Challenge 2

Why won't this code run? Make it run by only changing one line.

void main() {
    String fruit;
    fruit = "apple"

    System.out.println(fruit);

    final String vegtable = "carrot";

    System.out.println(fruit);
    System.out.println(vegtable);

    fruit = "orange";
    vegetable = "celery";

    System.out.println(fruit);
    System.out.println(vegtable);
}

Challenge 3

What is the output of this code?

void main() {
    String a = "A";
    String b = "B";

    b = a;
    a = b;
    b = a;
    a = b;

    System.out.println(a);
    System.out.println(b);
}

Challenge 4

Only adding lines in the middle and without writing "A" or "B" again, make it so that the output of the program is

B
A
void main() {
    String a = "A";
    String b = "B";
    // Don't touch above this

    // You can add code here

    // Don't touch below this
    System.out.println(a);
    System.out.println(b);
}

Challenge 5

Some of the variables in this program are named "wrong." Fix them.

void main() {
    String apple = "red";
    String clown_car = "polka dot";
    String SeriousCar = "black";
    String FASTRunner = "bolt";
    String slowRunner = "tortoise";
}

Booleans

A boolean is either true or false.

boolean onFleek = true;
boolean badVibes = false;

This is used to represent situations where there are exactly two possible states.

And

One way multiple booleans can be combined is by using the "and" operator - &&.

boolean funToBeAround = true;
boolean believesInFundamentalHumanRights = true;
boolean willAskOnDate = funToBeAround && believesInFundamentalHumanRights;

So in this case, I will ask someone on a date if they are fun to be around and they wholeheartedly believe in the assertions made in the Universal Declaration of Human Rights.

funToBeAroundbelievesInFundamentalHumanRightswillAskOnDate
truetruetrue
truefalsefalse
falsetruefalse
falsefalsefalse

Or

Another way booleans can be combined is by using the "or" operator - ||.

boolean dogLooksNice = true;
boolean personLooksNice = false;
boolean willAskToPetDog = dogLooksNice || personLooksNice;

So in this case, I will ask to pet someone's dog if either the the dog looks nice or the person walking the dog looks nice.

dogLooksNicepersonLooksNicewillAskToPetDog
truetruetrue
truefalsetrue
falsetruetrue
falsefalsefalse

Exclusive vs. Inclusive

It is important too note that this is not an "exclusive" OR.

An exclusive OR would be something like a child being allowed to have ice cream or a cookie, but not both.

The || operator is an "inclusive" OR, meaning the child is allowed ice cream, a cookie, or both ice cream and the cookie.

Not

Booleans can also be "negated" using the "not" operator - !.

boolean haveOreosInHouse = true;
boolean stuckToCalorieLimit = !haveOreos;

So in this case, I have stuck to my calorie limit if there are not Oreos in the house.

haveOreosInHousestuckToCalorieLimit
falsetrue
truefalse

Operator Precedence

The operators that work on booleans have a "precedence order."

This is defines an order of operations similar to mathematics, where multiplication and division happen before addition and subtraction.

For booleans ! always happens first. This is followed by && and then by ||.

boolean a = true;
boolean b = false
boolean c = false;

// just as 2 + 5 * 3 "evaluates" 5 * 3 before adding 2
// first, !b is true
// second, a && true is true
// third true || c is true.
boolean result = a && !b || c;

Also like mathematics, parentheses can be used to control this order.

// Even though || has a lower precedence than &&, we evaluate
// !b || c first because of the parentheses.
boolean result = a && (!b || c);

Challenges

Remember the rules for this are

  • Try to use only the information given up to this point in this book.
  • Try not to give up until you've given it a solid attempt

Challenge 1

What will this program output when run? Write down your guess and then try running it.

void main() {
    boolean a = true;
    boolean b = false;
    boolean c = true;
    boolean d = false;

    boolean result = a || b && c || !d;

    System.out.println(result);
}

Challenge 2

What will this program output when run? Write down your guess and then try running it.

void main() {
    boolean a = true;
    boolean b = false;
    boolean c = true;
    boolean d = false;

    boolean result = !(a || b && c || !d) || (a && b || c);

    System.out.println(result);
}

Challenge 3

Say you have two boolean variables, how could you use the operators we've covered to get the "exclusive or" of the two.

void main() {
    // Change these two variables to test your solution
    boolean hasIceCream = true;
    boolean hasCookie = false;

    boolean validChoice = < YOUR CODE HERE >;

    System.out.println(validChoice);
}

Make sure to test all the possibilities.

hasIceCreamhasCookievalidChoice
truetruefalse
truefalsetrue
falsetruetrue
falsefalsefalse

Integers

An integer is any number in the set { ..., -2, -1, 0, 1, 2, ... }.

int x = 1;
int y = 8;
int z = -4;

Integer Literals

In order to write an integer in a program, you write an "integer literal."

789

We call them this because the integer is literally written down in the program.

int trueCrime = 789;

Addition

You can add any two ints using the + operator.

int x = 5;
// y will be 6
int y = x + 1;
// z will be 11
int z = x + y;

System.out.println(x);
System.out.println(y);
System.out.println(z);

Adding a negative number does the same thing as subtraction.

int x = 5;
// y will be 1
int y = x + -4;

System.out.println(x);
System.out.println(y);

Subtraction

You can subtract any two ints using the - operator.

int x = 5;
// y will be 4
int y = x - 1;
// z will be 1
int z = x - y;

System.out.println(x);
System.out.println(y);
System.out.println(z);

Subtracting a negative number does the same thing as addition.

int x = 5;
// y will be 9
int y = x - -4;

System.out.println(x);
System.out.println(y);

Multiplication

You can multiply any two ints using the * operator.

// x will be 15
int x = 3 * 5;
// y will be 75
int y = x * 5;
// z will be 1125
int z = x * y;

System.out.println(x);
System.out.println(y);
System.out.println(z);

Division

You can divide any two ints using the / operator.

int x = 8;
// y will be 4
int y = x / 2;

System.out.println(x);
System.out.println(y);

Division with integers gives results in only the quotient of the result, not the remainder.

So 5 / 2 does not result in 2.5, but instead just 2.

// 5 / 2 is not 2.5, but instead 2.
int x = 5 / 2;
// 13 / 3 is not 4.3333, but instead 4.
int y = 13 / 3;

System.out.println(x);
System.out.println(y);

Remainder

To get the remainder of the division between two integers you can use the % operator. This is called the "modulo operator."

int x = 5;
// The remainder of 5 / 2 is 1
// y will be 1
int y = x % 2;
// The remainder of 5 / 3 is 2
// z will be 2
int z = x % 3;

System.out.println(x);
System.out.println(y);
System.out.println(z);

A common use for this is to make numbers "go in a circle."

For instance, say you wanted to count from 0 up to 3 and then go back to 0.

int value = 0;
System.out.println(value);

// the remainder of (0 + 1) divided by 3 is 1
// value will be 1
value = (value + 1) % 3;
System.out.println(value);


// the remainder of (1 + 1) divided by 3 is 2
// value will be 2
value = (value + 1) % 3;
System.out.println(value);


// the remainder of (2 + 1) divided by 3 is 0
// value will again be 0!
value = (value + 1) % 3;
System.out.println(value);

// the remainder of (0 + 1) divided by 3 is 1
// value will be 1
value = (value + 1) % 3;
System.out.println(value);

// and so on.

The fact that all the reassignments of value look identical is something that will be useful in tandem with loops.

Equality

Any two ints can be inspected to see if their value is equal by using the == operator.

Unlike the previous operators, which all take ints and produce ints as their result, == takes two ints and produces a boolean as its result.

// 1 is never equal to 2
// this will be false
boolean universeBroken = 1 == 2;
System.out.println(universeBroken);

boolean loneliestNumber = 1;
boolean otherLonelyNumber = 2;

// this will be true
boolean bothLonely = loneliestNumber == (otherLonelyNumber - 1);
System.out.println(bothLonely);

It is very important to remember that a single = does an assignment. Two equals signs == checks for equality.

The opposite check, whether things are not equal, can be done with !=.

// 1 is never equal to 2
// this will be true
boolean universeOkay = 1 != 2;
System.out.println(universeOkay);

Comparison

In addition to comparing for equality with == and !=, ints can be compared to see if one is bigger than another using >, <, >=, and <=.

> will evaluate to true if the number on the left is greater than the one on the right.

boolean willBeTrue = 5 > 2;
boolean willBeFalse = 2 > 5;

< will evaluate to true if the number on the right is greater than the one on the left.

boolean willBeFalse = 5 < 2;
boolean willBeTrue = 2 < 5;

If you went to public school like I did, you should be used to imagining that the > was the jaw of a shark. Whatever direction the Jaws are facing, thats the one that would need to be bigger for the statement to be true.1

// true if the shark is facing the bigger number
// false otherwise.
boolean result = 9 🦈 5;

>= behaves the same as > except >= will evaluate to true if the numbers are identical, > will not.

boolean willBeTrue = 5 >= 5;
boolean willBeFalse = 5 > 5;

<= has the same relationship to < as >= does to >.

boolean willBeTrue = 5 <= 5;
boolean willBeFalse = 5 < 5;
1

Shark attacks are far more rare than people think they are. You are not a seal.

Chained Comparisons

When writing an expression in math to say something along the lines of "x is greater than zero and less than 5," it is natural to put that x in the middle of both operators like so.

0 < x < 5

This does not work in Java. In order to "chain" comparisons like this, you should combine the results of comparisons using the && operator.

boolean xInRange = 0 < x && x < 5;

Operator Precedance

Just like boolean operators, +, -, *, /, and % have a defined precedence order.

The order of operations is the same as mathematics. Multiplication and division happen before addition and subtraction, with the modulo operator being a sort of "funky division." Parentheses can be used to control this order.

None of this should be a surprise if you learned PEMDAS in school.

// Following the order of operations:
// 2 * 3 + 3 * 9 / 2 - 2

// 2 * 3 happens first
// 6 + 3 * 9 / 2 - 2

// 3 * 9 happens next
// 6 + 27 / 2 - 2

// 27 / 2 happens next
// because of integer division, that gives 13
// 6 + 13 - 2

// 6 + 13 comes next
// 19 - 2

// and the final result is 17;
int result = 2 * 3 + 3 * 9 / 2 - 2;
System.out.println(result);

The ==, !=, >, <, >=, and <= operators play a part here too1. They all have a lower precedence order than all the math operators, so you can put them in the middle of any two math expressions.

// The == check happens last.
boolean areThingsSame = 3 * (4 - 1 + 3) * 4 == 5 * 3 + 1 * 3 * 9;
1

Every operator in the language has a defined order of operations with respect to all of the others. I am just showing them to you as they become relevant.

Reassignment

When the value of a variable is reassigned, the value stored in the variable before the reassignment can be used to compute the new value.

This is true for all data types, but it is easiest to demonstrate with numbers.

int x = 1;
System.out.println(x);

// x starts as 1, 1 + 1 is 2.
// 2 is the new value of x.
x = x + 1;
System.out.println(x);

// x is now 2, 2 * 2 * 3 is 12
// 12 is the new value of x.
x = x * x * 3;
System.out.println(x);

This property was used in the previous example for the % operator, but I think it worth calling attention to even if it is "intuitive".

Shorthands for Reassignment

A very common thing to do is to take the current value of a variable, perform some simple operation like addition on it, and reassign the newly computed value back into the variable.

int x = 2;
System.out.println(x);

x = x * 5 // 10
System.out.println(x);

As such, there is a dedicated way to do just that.

int x = 1;

// This is the same as
// x = x + 2;
x += 2;

// This is the same as
// x = x * 4
x *= 4;

// This is the same as
// x = x - (x * 5)
x -= (x * 5)

// This is the same as
// x = x / 6
x /= 6;

// This is the same as
// x = x % 3
x %= 3;

// Pop quiz!
System.out.println(x);

Of note is that adding or subtracting exactly 1 is common enough that it has its own special shorthand.

int x = 0;
System.out.println(x);

// Same as
// x = x + 1;
// x += 1;
x++;
System.out.println(x);

// Same as
// x = x - 1;
// x -= 1;
x--;
System.out.println(x);

Limits

Unlike in math, where numbers can be arbitrarily big or small, a Java int is "fixed width."

Say you had a piece of paper that was only big enough to write two numbers on.

The only numbers you could write in a base ten system would be those from 0 to 99. You could not write 100 or anything larger.

A Java int is similar except instead of only being able to write 0 to 99 on a piece of paper, a variable that has the type int can represent numbers from -231 to 231 - 1.

If you try to directly write out a number that is outside of that range, Java will not let you.

// This will not run
int tooBig = 999999999999;

If you do math that should produce a larger number than is representable, the value will "loop around."

// This is the value of 2^31 - 1
int atLimit = 2147483647;
// The value will "loop around" to -2^31
int beyondLimit = atLimit + 1;
// This will output -2147483648
System.out.println(beyondLimit);

There are other types which can represent a larger range of integers, as well as types which do not have any limits, but for now int is the only one you will need.

Challenges

Remember the rules for this are

  • Try to use only the information given up to this point in this book.
  • Try not to give up until you've given it a solid attempt

Challenge 1

What will this program output when run? Write down your guess and then try running it.

void main() {
    int x = 5;
    int y = 8;
    System.out.println(x + y);
}

Challenge 2

What will this program output when run? Write down your guess and then try running it.

void main() {
    int x = 5;
    x--;
    x--;
    x = x + x;
    System.out.println(x);
}

Challenge 3

Make it so that this program correctly determines if the numbers are even or not.

Assume that the values of x, y, and z could be changed. Don't just write out literally true and false for their current values.

void main() {
    int x = 5;
    int y = 4;
    int z = 98;

    boolean xIsEven = < CODE HERE >;
    System.out.println(xIsEven);

    boolean yIsEven = < CODE HERE >;
    System.out.println(yIsEven);

    boolean zIsEven = < CODE HERE >;
    System.out.println(zIsEven);
}

Challenge 4

Try dividing a number by zero. What happens?

Write down your guess and then try running the program below to see.

void main() {
    System.out.println(5 / 0);
}

Challenge 5

What can you write in the spot marked that will make the program output 2?

void main() {
    int x = 5;
    int y = <CODE HERE>;
    System.out.println(x + y);
}

Challenge 6

What is the output of this code.1

void main() {
    System.out.println(
        6 / 2 * (1 + 2)
    );
}

Floating Point Numbers

Floating point numbers are used to represent numbers which cannot be stored as Integers like 2.5 or 3.14.

double x = 1.5;
double y = 8.0;
double z = -3.14;

The type you will use to store a floating point number is double. double stands for "double precision floating point."

Floating Point Literals

In order to write a floating point number in a program, you use a "floating-point literal."

1.5

Any number written with a decimal point is a floating point literal.

double pi = 3.14;

This includes numbers where a decimal point is written, but there is no fractional part to the number.

5.0

You cannot directly give a value to an integer variable using a floating point literal, even if there is no fractional part to the number.

// this will not work
int x = 5.0;

The reverse is possible though. You can give a value to a variable that stores a floating point number using an integer literal.

double x = 5;

Accuracy

Floating Point numbers are not an exact representation of numbers.

The reasons for this are twofold.

  1. It is much more efficient for a computer to work with data that is a "fixed size". You can't cram all the infinite possible numbers into 32, 64, or any fixed number of bits.
  2. For most systems, the inaccuracy is okay. When it is not, there are ways to do "real math" that we will cover much later.

For an explanation of the mechanics, I'll defer to this old Computerphile video.

Addition

You can add any two doubles using the + operator.

double x = 5.1;
// y will be 14.2
double y = x + 9.1;

Because of the previously mentioned inaccuracy, the results of additions might not always be what you expect.

// z will be 19.299999999999997
double z = x + y;

You can add any int to a double and the result of any such addition will also be a double.

int x = 5;
double y = 4.4;
// z will be 9.4
double z = x + y;

System.out.println(x);
System.out.println(y);
System.out.println(z);

Even if the result of such an expression will not have any fractional parts, you cannot directly assign it to an int.

int x = 5;
double y = 4;
// even though z would be 9, which can be stored in an int
// this will not work. The result of the expression is a double.
int z = x + y;

System.out.println(x);
System.out.println(y);
System.out.println(z);

Subtraction

You can subtract any two doubles using the - operator.

double x = 5.1;
// y will be 4.1
double y = x - 9.2;

System.out.println(x);
System.out.println(y);

Because of the previously mentioned inaccuracy, the results of subtractions might not always be what you expect.

// z will be -4.199999999999999
double z = y - 0.1;

System.out.println(z);

You can subtract any int to or from a double and the result of any such subtraction will also be a double.

int x = 5;
double y = 4.5;
// z will be 0.5
double z = x - y;

System.out.println(x);
System.out.println(y);
System.out.println(z);

Even if the result of such an expression will not have any fractional parts, you cannot directly assign it to an int.

int x = 5;
double y = 4;
// even though z would be 1, which can be stored in an int
// this will not work. The result of the expression is a double.
int z = x - y;

Multiplication

You can multiply any two doubles using the * operator.

double x = 3;
// y will be 27
double y = x * 9;
// z will be 13.5
double z = y * 0.5;

System.out.println(x);
System.out.println(y);
System.out.println(z);

Just like with addition and subtraction, it is fine to use both integers and integer literals when doing multiplication on doubles. So long as any number being used is a double the overall result will be a double.

// a will be 3
double a = 1.5 * 2;

Division

You can divide any two doubles using the / operator.

double x = 8;
// y will be 4.0
double y = x / 2;
// z will be 1.3333333333333333
double z = y / 3;

System.out.println(x);
System.out.println(y);
System.out.println(z);

Unlike with integer division, floating point division will include the remainder in the result.1

1

With the caveat that the result is now potentially inaccurate.

Equality

Just like ints, doubles can be inspected to see if they are equal to one another using ==.

double numberOfToes = 10.0;
double numberOfFingers = 10.0;

boolean humanGenerated = numberOfToes == numberOfFingers;

Because of floating point inaccuracy, this might not always give you the result you expect though.

double x = 0.1;
double y = 0.2;
// z will be 0.30000000000000004
double z = x + y;

// this will be false.
boolean doesWhatYouExpect = z == 0.3;

A double can also be compared to an int and, if they represent the same value, they will be reported as equal.

int x = 5;
double y = 5.0;

// will be true
boolean fiveIsFive = x == y;

Comparison

In addition to comparing for equality with == and !=, doubless can be compared to see if one is bigger than another using >, <, >=, and <=.

This works the same as it does with ints.

double x = 1.5;
double y = 0.2;

// true
System.out.println(x > y);
// false
System.out.println(x < y);

Shorthands for Reassignment

All the same shorthands for reassignment work with doubles the same as they do with ints.

double x = 0.5;
// 0.5
System.out.println(x);

x += 3;
// 3.5
System.out.println(x);

x -= 1;
// 2.5
System.out.println(x);

x++;
// 3.5
System.out.println(x);

x--;
// 2.5
System.out.println(x);

x *= 5;
// 12.5
System.out.println(x);

x /= 2;
// 6.25
System.out.println(x);

NaN

There is a special floating point number called NaN, which stands for "Not a Number."

You generally only encounter NaN as the result of doing something silly like dividing zero by zero.

double nan = 0.0 / 0.0;

NaN is not equal to itself.

// will be false
boolean equalToItself = nan == nan;

System.out.println(equalToItself);

NaN is not greater than itself.

// will be false
boolean greaterThanItself = nan > nan;

System.out.println(greaterThanItself);

NaN is not less than itself.

// will be false
boolean lessThanItself = nan < nan;

System.out.println(lessThanItself);

NaN is not greater than, less than, or equal to any number.

// will all be false
System.out.println(nan < 5);
System.out.println(nan > 5);
System.out.println(nan == 5);

None of this is usually useful, but it is fun to know about.

Positive and Negative Infinity

In addition to the wackyness of NaN, floating point numbers can also represent both positive and negative infinity.

You can get positive infinity by dividing any positive number by zero.

double positiveInfinity = 1.0 / 0.0;

You can get negative infinity by dividing any negative number by zero.

double negativeInfinity = -1.0 / 0.0;

As you might expect, positive infinity is greater than any number and negative infinity is less than any number.

// true
System.out.println(positiveInfinity > 99999999);

// true
System.out.println(negativeInfinity < -99999999);

Except for NaN, of course.

double nan = 0.0 / 0.0;

// false
System.out.println(positiveInfinity > nan);

// false
System.out.println(negativeInfinity < nan);

Square Root

A relatively common operation to want to perform on floating point numbers is to find their square root.

You can do this with Math.sqrt.

double x = 4;
double y = Math.sqrt(x);

// This will output 2
System.out.println(y);

You need to write Math.sqrt and then inside of parentheses the expression whose value you want to take the square root of..

double x = 5;
double y = 13;
double z = Math.sqrt(9 * x + y);

// This will output 7.615773105863909
System.out.println(z);

If you try to take the square root of a negative number, the result will be NaN.

// will output NaN
System.out.println(Math.sqrt(-5.2));

Conversion to Integers

Normally, a double value cannot be assigned to an int.

double x = 5.0;
// will not work
int y = x;

The reason for this is that there are numbers like 2.5, the infinities, and NaN which do not have an obvious way to be represented as an integer.

There are also numbers which a double can represent like 4207483647.0 and -9999999999.0 which happen to be too big or too small to fit into the limits of an int even though they do have an obvious "integer representation."

As such, to make an int out of a double you need to accept that it is a "narrowing conversion." The number you put in won't neccesarily be the number you get out.

To perform such a narrowing conversion, you need to put (int) before a literal or expression that evaluates to a double.

double x = 5.0;
// will be 5
int y = (int) x;

System.out.println(y);

Any decimal part of the number will be dropped. So numbers like 2.1, 2.5, and 2.9 will all be converted into simply 2.

int x = (int) 2.1;
int y = (int) 2.5;
int z = (int) 2.9;

System.out.println(x);
System.out.println(y);
System.out.println(z);

Any number that is too big to store in an int will be converted to the biggest possible int, 231 - 1.

// 2147483647
System.out.println((int) 4207483647.0);

double positiveInfinity = 5.0 / 0.0;
// 2147483647
System.out.println((int) positiveInfinity);

Any number that is too small to store in an int will be converted to the smallest possible int, -231.

// -2147483648
System.out.println((int) -9999999999.0);

double negativeInfinity = -5.0 / 0.0;
// -2147483648
System.out.println((int) negativeInfinity);

And NaN will be converted to zero.

double nan = 0.0 / 0.0;
System.out.println((int) nan);

When you use (int) to convert, we call that a "cast1 expression". The (int) is a "cast operator." It even has a place in the operator precedence order just like +, -, ==, etc.

The main difference is that instead of appearing between two expressions like the + in 2 + 5, it appears to the left of a single expression.

1

https://english.stackexchange.com/questions/220001/etymology-of-type-cast

Conversion from Integers

To convert from an int to a double, you don't need to do any special work. All ints are representable as doubles so it is a "widening conversion" and will be handled automatically by Java when performing an assignment.

int x = 5;
double y = x;

System.out.println(x);
System.out.println(y);

This is not true in an expression. Even if the result of a computation between ints is being assigned to a double, the computation will still be performed using the same rules ints usually follow.

int x = 7;
int y = 2;
// integer division of 7 and 2 gives 3.
double z = x / y;

System.out.println(z);

To perform math on an int and have that int behave as if it were a double, you need to convert said int into a double using a cast expression and the (double) cast operator.

int x = 7;
int y = 2;
// This converts x into a double before performing the division
// so the result will be 3.5.
double z = (double) x / y;

System.out.println(z);

Challenges

Remember the rules for this are

  • Try to use only the information given up to this point in this book.
  • Try not to give up until you've given it a solid attempt

Challenge 1

What will this program output when run? Write down your guess and then try running it.

void main() {
    double x = 5.1;
    double y = 2.4;
    System.out.println(x + y);
}

Challenge 2

What will this program output when run? Write down your guess and then try running it.

void main() {
    double x = 5.1;
    double y = 2.1;
    System.out.println(x + y);
}

Challenge 3

What will this program output when run? Write down your guess and then try running it.

How can you make it give the "right" answer?

void main() {
    double x = 5 / 2;
    System.out.println(x);
}

Challenge 4

These two expressions give different results. Why is that, and what results do they give?

double resultOne = (int) 5.0 / 2 + 5.0 / 2;
double resultTwo = (int) (5.0 / 2 + 5.0 / 2);

System.out.println(resultOne);
System.out.println(resultTwo);

Challenge 5

The following is a quadratic equation.

\[ 2x^2 + 8x + 3 = 0 \]

To find the solutions of any quadratic equation you can use the following formula.

\[ x = \frac{-b \pm \sqrt{b^2 - 4ac} }{2a} \]

Where \(a\), \(b\), and \(c\) are the prefixes of each term in the following equation.

\[ ax^2 + bx + c = 0 \]

Write some code that finds both solutions to any quadratic equation defined by some variables a, b, and c. If the equation has imaginary solutions, you are allowed to just output NaN.

void main() {
    // For this one in particular, you should output
    // -3.5811388300842 and -0.41886116991581
    // but your code should work with these three numbers changed to
    // represent any given quadratic equation.
    double a = 2;
    double b = 8;
    double c = 3;

    double resultOne = ???;
    double resultTwo = ???;

    System.out.println(resultOne);
    System.out.println(resultTwo);
}

Characters

A character, represented by the data type char, is a single letter or symbol.

char letter = 'a';

I choose to pronounce it like the "char" in "Charmander."

Character Literals

In order to write a character in a program, you write that one character surrounded by single quotes.

'a'

This is called a "character literal." It has the same relationship to char that an integer literal like 123 has to int.

// Same as this "integer literal" is used to write a number
int sesameStreet = 123;
// A "character literal" is used to write text
char thisEpisodeIsBroughtToYouBy = 'c';

Common Escape Sequences

While most characters can be written directly into a program, as is the case for a, b, or t, there are some which cannot.

For these, you need to use what is called an "escape sequence."

The most common escape sequence you will use will be the one for a "new line." Which is a backslash followed by an n.

char newline = '\n';

Because a backslash is used for this special syntax, to put a backslash into a character literal you need to escape it with a backslash of its own.

char backslash = '\\';

And because single quotes are used to mark the start and end of a character literal, they need to be escaped as well.

char singleQuote = '\'';

Conversion to Integers

All chars have a matching numeric value. 'a' is 97, 'b' is 98, '&' is 38, and so on.

Same as assigning an int to a double, you can perform a widening conversion by attempting to assign a char to an int.

int valueOfA = 'a';

System.out.println(valueOfA);

chars will be automatically converted to ints when used with mathmatical operators like +, -, >, <, etc.

char gee = 'g';

// all the letters from a to z have consecutive numeric values.
boolean isLetter = gee >= 'a' && gee <= 'z';

System.out.println(isLetter);

This can be useful if you are stranded on Mars1 or if you want to see if a character is in some range.

1

https://www.youtube.com/watch?v=k-GH3mbvUro

Conversion from Integers

An int can represent more values than a char, so conversion from int to char requires the use of the cast operator (char).

int x = 120;

char xAsChar = (char) x;

System.out.println(xAsChar);

This conversion is narrowing, so information might be lost if the int value is too big or too small to fit into a char.

The initial value of a char can also be given by an integer literal if the integer literal represents a small enough letter.

char z = 122;

System.out.println(z);

Unicode

Most letters and symbols that are common in the English speaking world fit into a single char, so pretending that a char is always "a single letter or symbol" is generally a good enough mental model.

Where this falls apart is with things like emoji (👨‍🍳) which are generally considered to be one symbol, but cannot be represented in a single char.

char chef = '👨‍🍳';

chars are actually "utf-16 code units". Many symbols require multiple "code units" to represent.

For a full explanation, refer to this old Computerphile video.

It describes "utf-8", which is 8 bits per "code unit." Java's char uses 16 bits, but that is the only difference.

Challenges

Remember the rules for this are

  • Try to use only the information given up to this point in this book.
  • Try not to give up until you've given it a solid attempt

Challenge 1

A lot of math problems ask you to find \( x^2 \). What is the value of the character x squared?

Try to work it out on paper before running the program below.

void main() {
    char x = 'x';

    System.out.println(x * x);
}

Challenge 2

Alter the program below so that it will output true if the character declared at the top is a letter.

Make use of the fact that the numeric values for a - z and A - Z are contiguous.

void main() {
    char c = 'a';

    boolean isLetter = ???;

    System.out.println(isLetter);
}

Challenge 3

How many UTF-16 code units does it take to represent this emoji? 👨‍🍳.

Strings

The String data type is used to represent text.

String shortStory = "Everyone lived happily ever after, the end."

The word "string" comes from the fact that text is just individual characters "strung together".

As a concrete example j, o, and e can be "strung together" into the "string" joe.

String Literals

In order to write text in a program, you surround it with double quotes.

"Hello, World"

This is called a "string literal." It has the same relationship to String that an integer literal like 123 has to int.

// Same as this "integer literal" is used to write a number
int abc = 123;
// A "string literal" is used to write text
String name = "penelope";

Common Escape Sequences

Inside of a string literal, there are some characters that cannot be written normally.

An easy example is double quotes. You can't write double quotes in the middle of a string literal because Java will think the extra quote is the end of the String.

String title = "The "Honorable" Judge Judy";

In order to make it work, the "s need to be "escaped" with a backslash.

String title = "The \"Honorable\" Judge Judy";

Since the backslash is used to escape characters, it too needs to escaped in order to have it be in a String. So to encode ¯\_(ツ)_/¯ into a String you need to escape the first backslash.

// The first backslash needs to be escaped. ¯\_(ツ)_/¯
String shruggie = "¯\\_(ツ)_/¯";

And much the same as with char, you need to use \n to write in a newline.

String letter = "To Whom It May Concern,\n\nI am writing this letter to complain.";

The Empty String

There is a special String which contains no characters at all.

// There is nothing to say.
String conversationWithDog = "";

You write it just like any other string, just with nothing between the double quotes.

""

It is different from a String that just contains spaces because to Java those "space characters" are just as much real characters as a, b, or c.

// There is noteworthy silence.
String conversationWithInlaws = " ";

This is one of those things that feels totally useless, but comes in handy pretty often.

  • Say you are writing a message to send to your friend. The messenger app can represent the state of the input box before you type anything with an empty String.
  • If you want to digitally record responses to legal paperwork, you might choose to represent skipped fields as empty Strings.
  • Video Games where characters have assigned names can assign an empty String as the name of otherwise "unnamed" characters.
  • etc.

Multiline Strings

If the text you want to store in a String has multiple lines, you can use three quotation marks to represent it in code.

String poem = """
    I met a traveller from an antique land,
    Who said—“Two vast and trunkless legs of stone
    Stand in the desert. . . . Near them, on the sand,
    Half sunk a shattered visage lies, whose frown,
    And wrinkled lip, and sneer of cold command,
    Tell that its sculptor well those passions read
    Which yet survive, stamped on these lifeless things,
    The hand that mocked them, and the heart that fed;
    And on the pedestal, these words appear:
    My name is Ozymandias, King of Kings;
    Look on my Works, ye Mighty, and despair!
    Nothing beside remains. Round the decay
    Of that colossal Wreck, boundless and bare
    The lone and level sands stretch far away.
    """;

Inside of the this "Multiline String Literal" you don't need to escape quotation marks " and you gain the ability to write newlines without having to use \n.

Concatenation

Any two strings can be concatenated by using the + operator.

String he = "he";
String llo = "llo";

String hello = he + llo;

System.out.println(hello);

This will make a new String where the characters from the first one all appear followed by the characters in the second one.

If you try to concatenate a String to something that is not a String, like an int or a double, then the result will be a new String with the characters from the "string representation" of that other thing.

int numberOfApples = 5;
double dollahs = 1.52;

String message = "I have " + numberOfApples +
    " apples and $" + dollahs + " in my pocket.";

System.out.println(message);

Equality

You can check if two Strings have the same contents by using .equals.

String lyricOne = "Green, Green, Dress";
String lyricTwo = "Green, Green, Dress";

boolean areSameLyric = lyricOne.equals(lyricTwo);
boolean isMyName = lyricOne.equals("Bop Bop");

System.out.println(areSameLyric);
System.out.println(isMyName);

You write one String on the left, .equals, and then the String you want to check it against inside of parentheses.

To see if strings have different contents, you need to use the not operator (!) on the result of .equals.

String bow = "bow";
String wow = "WOW";

boolean areNotSame = !bow.equals(wow);

System.out.println(areNotSame);

Length

The number of chars which comprise a String can be accessed by using .length().1

String fruit = "strawberry";
int numberOfChars = fruit.length();

// strawberry is 10 characters long
System.out.println(
    fruit + " is " numberOfChars + " characters long"
);
1

This is different from the number of unicode codepoints.

Access Individual Characters

Given a String, you can access the individual characters which comprise it by using .charAt.

The first character can be accessed by putting 0 in the parentheses. The second by using 1, and so on.

String spy = "loid";

char l = spy.charAt(0);
System.out.println(l);

char o = spy.charAt(1);
System.out.println(o);

char i = spy.charAt(2);
System.out.println(i);

char d = spy.charAt(3);
System.out.println(d);

We call this number the "index" of the character.1

The index of the character to access can come from a variable.

String assassin = "yor";
int indexOfR = 2;

char r = assassin.charAt(indexOfR);
System.out.println(r);

If you give a number equal to or greater than the length of the String or a number less than zero, you will get an error.

String student = "anya";
// Crash!
student.charAt(999);
String dog = "bond";
// Crash!
dog.charAt(-1);
1
There will be more things
which have their individual elements accessible by indexes. They will all generally start from 0 for the first element
but there are rare exceptions.

Challenges

Remember the rules for this are

  • Try to use only the information given up to this point in this book.
  • Try not to give up until you've given it a solid attempt

Challenge 1

What will this program output when run? Write down your guess and then try running it.

void main() {
    String first = "1";
    String second = "2";
    String result = first + second;

    System.out.println(result);
}

Challenge 2

What will this program output when run? Write down your guess and then try running it.

void main() {
    String first = "1";
    int second = 2;

    System.out.println(first + second);
}

Challenge 3

What will this program output when run? Write down your guess and then try running it.

void main() {
    char first = 'a';
    String second = "b";
    String third = "ab";

    System.out.println((first + second).equals(second));
}

Challenge 4

Make it so this program will output abc by only changing one line and not altering the println statement.

Before your change, why does it output 294?

void main() {
    char a = 'a';
    char b = 'b';
    char c = 'c';
    System.out.println(a + b + c);
}

Challenge 5

Without adding any new printlns, change one line in this program so that it outputs racecar.

Try to find two ways to do that.

void main() {
    String racecar = "racecar";

    int diff = 1;

    int index = 6;

    System.out.print(racecar.charAt(index));
    index += diff;
    System.out.print(racecar.charAt(index));
    index += diff;
    System.out.print(racecar.charAt(index));
    index += diff;
    System.out.print(racecar.charAt(index));
    index += diff;
    System.out.print(racecar.charAt(index));
    index += diff;
    System.out.print(racecar.charAt(index));
    index += diff;
    System.out.println(racecar.charAt(index));
}

Branching Paths

All the code I have shown you so far has run from top to bottom. That is, it has followed a single "path."

Not all programs can follow a single path though.

Imagine trying to rent a car online. The first thing you might be asked is your age. This is because most car rental companies do not want to rent to people under the age of 25.1.

If you enter an age that is less than 25, the program should immediately tell you that you cannot rent a car. If you enter an age that is greater than or equal to 25, the program should continue to prompt you for more information.

There are multiple "branching paths" that the program might take.

1

For insurance reasons.

If

The way to represent a branching path in Java is by using an if statement.

int age = 5; // 👶
if (age < 25) {
    System.out.println("You are too young to rent a car!");
}

You write the word if followed by an expression which evaluates to a boolean inside of ( and ). This expression is the "condition". Then you write some code inside of { and }.

if (CONDITION) {
    <CODE HERE>
}

When the condition evaluates to true, the code inside of the { and } will run. If it evaluates to false that code will not run.

In this example the condition is age < 25. When age is less than 25 it will evaluate to true and you will be told that you cannot rent a car.

int age = 80; // 👵
if (age < 25) {
    System.out.println("You are too young to rent a car!");
}

If this condition evaluates to false, then the code inside of { and } will not run.

Else

When you want to do one thing when a condition evaluates to true and another when that same condition evaluates to false you can use else.

int age = 30; // 🙎‍♀️
if (age < 25) {
    System.out.println("You cannot rent a car!");
}
else {
    System.out.println("You might be able to rent a car.");
}

You write the word else immediately after the } at the end of an if statement, then some code inside of a new { and }.

if (CONDITION) {
    <CODE TO RUN>
}
else {
    <CODE TO RUN>
}

When the condition evaluates to false, the code inside of else's { and } will run.

else cannot exist without a matching if, so this code does not work.

else {
    System.out.println("No if.");
}

Nested Ifs

The code inside of the { and } can be anything, including more if statments.

int age = 5; // 👶
if (age < 25) {
    System.out.println("You are too young to rent a car!");
    if (age == 24) {
        System.out.println("(but it was close)");
    }
}

When an if is inside another if we say that it is "nested".

If you find yourself nesting more than a few ifs that might be a sign that you should reach out for help.

if (...) {
    if (...) {
        if (...) {
            if (...) {
                // Seek professional help
            }
        }
    }
}

Else If

If you have an if nested in an else branch, you can simplify that by using else if.

boolean cool = true; // 🕶️
int age = 30; // 🙎‍♀️
if (age < 25) {
    System.out.println("You cannot rent a car!");
}
else {
    if (!cool) {
        System.out.println("You failed the vibe check.");
    }
    else {
        System.out.println("You are rad enough to rent a car.");
    }
}

So the following will work the same as the code above.

boolean cool = true; // 🕶️
int age = 30; // 🙎‍♀️

if (age < 25) {
    System.out.println("You cannot rent a car!");
}
else if (!cool) {
    System.out.println("You failed the vibe check.");
}
else {
    System.out.println("You are rad enough to rent a car.");
}

You can have as many else ifs as you need. Each one will only run if all the previous conditions evaluate to false.

boolean cool = true; // 🕶️
int age = 100; // 👴

if (age < 25) {
    System.out.println("You cannot rent a car!");
}
else if (!cool) {
    System.out.println("You failed the vibe check.");
}
else if (age > 99) {
    System.out.println("You are too old to safely drive a car!");
}
else if (age > 450) {
    System.out.println("There can only be one! ⚔️🏴󠁧󠁢󠁳󠁣󠁴󠁿");
}
else {
    System.out.println("You are rad enough to rent a car.");
}

Relation to Delayed Assignment

Delayed assignment of variables becomes useful with if and else.

So long as Java can figure out that a variable will always be given an initial value inside of an if and else, you will be allowed to use that variable.

int age = 22;

String message;
if (age > 25) {
    message = "You might be able to rent a car";
}
else {
    message = "You cannot rent a car!";
}

System.out.println(message);

If it will not always be given an initial value, then you will not be allowed to use that variable.

int age = 22;

String message;
if (age > 25) {
    message = "You might be able to rent a car";
}

// message is not always given an initial value
// so you cannot use it.
System.out.println(message);

Conditional Operator

When the only operation being performed inside of an if and else pair is setting the initial value of a variable, you can use the "conditional operator"1 to perform that assignment instead.

int age = 22;

String message = age < 25
    ? "You cannot rent a car!"
    : "You might be able to rent a car";

You write a condition followed by a ?, a value to use when that condition evaluates to true, a :, and then a value to use when that condition evaluates to false.

CONDITION ? WHEN_TRUE : WHEN_FALSE
1
Some people will call this a ternary expression. Ternary meaning "three things."
Same idea as tres leches.

Boolean Expressions

A common thing I've seen students do is set the initial value of some boolean variable based on some condition.

int age = 22;

boolean canRent;
if (age > 25) {
    canRent = true;
}
else {
    canRent = false;
}

// or
// boolean canRent = age > 25 ? true : false;

System.out.println(canRent);

This is valid code, but very often can be made simpler if you remember that the condition itself already evaluates to a boolean. You can directly assign the variable to that value.

int age = 22;
boolean canRent = age > 25;

System.out.println(canRent);

Challenges

Remember the rules for this are

  • Try to use only the information given up to this point in this book.
  • Try not to give up until you've given it a solid attempt

Challenge 1

Write code that will outputs The number is even if x is an even number.

void main() {
    // Change this variable to different numbers
    // to test your code
    int x = 5;

    // < YOUR CODE HERE >
}

Challenge 2

Make it so that your code from the previous problem will also output The number is odd if the number is odd.

Challenge 3

Write code that will output allowed if the the password variable is equal to "abc123" and not allowed if it isn't.

void main() {
    // Change this variable to different strings
    // to test your code
    String password = "apple";

    // < YOUR CODE HERE >
}

Challenge 4

Write code that will assign the string The number is {x} even to message if x is an even number and The number is {x} odd if x is an even number.

So if x is 12 the string you should assign The number 12 is even to message.

void main() {
    String message;

    // Change this variable to different numbers
    // to test your code
    int x = 5;

    // < YOUR CODE HERE >

    System.out.println(message);
}

Loops

if and else let you write programs which can take branching paths, but they will still run from the beginning to the end.

Not all programs can just end though. Video games should draw their world at one second and do it again the next. If you enter the wrong password on your phone, it should ask you for your password again.

This is what "loops" are for. You run code starting from some point and then loop back to that same point and run that code again.

While

One way to make a loop in code is to use while.

int x = 5;
while (x != 0) {
    System.out.println(x);
    x--;
}

You write while followed by a condition inside of ( and ) and some code inside of { and }.

while (CONDITION) {
    <CODE HERE>
}

If the condition evaluates to true then the code inside of { and } will run. After that code runs, the condition will be evaluated again. If it still evaluates to true then the code { and } will run again.

This will continue until the code in the condition evaluates to false.

int glassesOfMilk = 99;
while (glassesOfMilk > 0) {
    System.out.println(
        glassesOfMilk + " glasses of milk left"
    );

    glassesOfMilk--;
}

If a loop is made with while we call it a "while loop."1

1

"We called him Tortoise because he taught us." - Lewis Carroll

Endless Loops

If a while loop will never end, we call that an endless loop.

This can happen if the condition is a constant like while (true)

while (true) {
    System.out.println("This is the song that never ends");
}

Or if the variables tested in the condition are not updated inside of the loop.

// x is never changed
int x = 0;
while (x != 1) {
    System.out.println("It goes on and on my friends");
}

Many games should never really "finish" so at the very start of that sort of program it is not uncommon to see a while (true).

Break

While loops will usually stop running when the condition at the top evaluates to false.

This can be bypassed by using the break statement.

int x = 5;
while (x > 0) {
    if (x == 2) {
        break;
    }
    x--;
}

System.out.println(
    "Final value of x is " + x
);

If a break is reached, the code in the loop stops running immediately. The condition of the loop is not checked again.

This can be useful in a variety of situations, but notably it is the only way to exit from an otherwise endless loop.

while (true) {
    System.out.println(
        "The people started singing it not knowing what it was"
    );

    // Will immediately leave the loop
    break;
}

Continue

Unless there is a break, while loops will usually run all the code in their body from top to bottom.

The only other situation this will not happen is if a continue statement is reached.

// Will output a message for every number except 4
int x = 5;
while (x > 0) {
    if (x == 4) {
        continue;
    }
    System.out.println(x + " is a good number");
    x--;
}

If a continue is reached the code in the loop stops running immediately but, unlike break, the condition of the loop is checked again. If it still evaluates to true then the code in the loop will run again.

Unreachable Code

If you write some code directly after a break or continue that code will be "unreachable."

Java knows this and so won't let any code like that run.

// This will not work
while (true) {
    continue;

    System.out.println("this is unreachable");
}

Do

One variation on a while loop is a "do-while loop."

int x = 0;
do {
    System.out.println(x);
    x++
} while(x < 5);

You write do, some code inside of { and }, and then while, a condition inside of ( and ), and finally a semicolon.

do {
    <CODE HERE>
} while (CONDITION);

In most situations it works exactly the same as a regular while loop. The only difference is that the first time the loop is reached the condition for the loop is not checked.

int x = 0;
do {
    System.out.println("this will run");
} while (x != 0)

while (x != 0) {
    System.out.println("this will not run");
}

One way to remember the difference is that in a "do-while loop" you always "do the thing" at least once.

Nested Loops

Just like with if, The code inside of the { and } can be anything, including more loops.

int x = 5;
int y = 3;

while (x != 0) {
    while (y != 0) {
        System.out.println(
            "x is " + x
        );
        System.out.println(
            "y is " + y
        );

        x--;
        y--;
    }
}

If you are inside such a "nested loop", continue and break apply to the "closest" loop.

That is, if a continue or a break were to appear here

while (x != 0) {
    while (y != 0) {
        if (y == 2) {
            break;
        }

        System.out.println(
            "x is " + x
        );
        System.out.println(
            "y is " + y
        );

        x--;
        y--;
    }
}

Then the y != 0 loop will be broken out of, not the x != 0 one. And if a continue or a break were to appear here

while (x != 0) {
    if (x == 2) {
        break;
    }
    while (y != 0) {


        System.out.println(
            "x is " + x
        );
        System.out.println(
            "y is " + y
        );

        x--;
        y--;
    }
}

Then the x != 0 loop would be the "target."

Labeled Break

If you want to break out of a nested loop from one of the inner loops, you can use a "labeled break."

outerLoop:
while (true) {
    while (true) {
        break outerLoop;
    }
}

To do this, before your outer while or do-while loop you need to add a "label" followed by a :. A label is an arbitrary name just like a variable's name.

<LABEL>:
while (<CONDITION>) {
    <CODE HERE>
}
<LABEL>:
do {
    <CODE HERE>
} while (<CONDITION>);

Then inside of an inner loop, you just need to write break followed by the label name.

int x = 5;
int y = 3;

xLoop:
while (x != 0) {
    while (y != 0) {
        if (x == 2 && y == 2) {
            break xLoop;
        }

        System.out.println(
            "x is " + x
        );
        System.out.println(
            "y is " + y
        );

        x--;
        y--;
    }
}

System.out.println("done.")

In this case the x != 0 loop will be broken out of, not the y != 0 one.

Labeled Continue

In the same way a labeled break can break out of a nested loop, a labeled continue can jump back to the start of a nested loop.

You just write continue followed by the label name.

// Will keep going back to the top of the outer loop
outerLoop:
while (true) {
    System.out.println("inside outer loop");
    while (true) {
        System.out.println("inside inner loop");
        continue outerLoop;
    }
}

Iteration

Loops potentially run code multiple times. Each time one goes from its top to its bottom we call that an "iteration" of the loop.

int x = 0;
while (x < 5) {
    // On the 1st iteration x will be 0
    // On the 2nd iteration x will be 1
    // ...
    // On the final iteration x will be 4
    System.out.println(x);
    x++
}

When the purpose of a loop is to run for every thing in some sequence of things, we say that the loop is "iterating over" those things.

Counting Up

Say your loop is intended to run some code for every number from 1 to 100.

The general pattern for code like this is to have some variable which tracks the current number, a loop whose condition is that the number is less than the number you want to stop at, and a line at the bottom of the loop which increments the current number.

int currentNumber = 1;
while (currentNumber <= 100) {
    System.out.println(currentNumber);
    currentNumber++;
}

Take note that in this example the condition is currentNumber <= 100, so the code in the loop will run when currentNumber is equal to 100. If the condition was currentNumber < 100 it would stop at 99.

int currentNumber = 1;
// Stops at 99
while (currentNumber < 100) {
    System.out.println(currentNumber);
    currentNumber++;
}

Counting Down

If you want to do the opposite, starting from a number like 100 and count down to 1, the pattern will be similar.

You still have some variable tracking the current number, but with a loop whose condition is that the number is greater than the number you want to stop at, and a line at the bottom of the loop which decrements the current number.

int currentNumber = 100;
while (currentNumber >= 1) {
    System.out.println(currentNumber);
    currentNumber--;
}

Similar to when counting up if the condition was not currentNumber >= 1 and instead was currentNumber > 1, the loop would stop at 2

int currentNumber = 100;
// Stops at 2
while (currentNumber > 1) {
    System.out.println(currentNumber);
    currentNumber--;
}

Iterate over a String

This general pattern of counting up and counting down becomes especially useful when you want to iterate over each character in a String.

String name = "Avril";

int index = 0;
while (index < name.length()) {
    System.out.println(name.charAt(index));
    index++;
}

Challenges

Early on, most students tend to have a lot of trouble with loops. Its also what is quizzed on in a lot of standardized tests.

Because of that there will be a lot of challenges in this section for you to practice. Try to at least do the first ten or so to make sure you have the concept down, but the more the better.

It might take awhile before you feel truly comfortable with this. That is normal.

Remember the rules for this are

  • Try to use only the information given up to this point in this book.
  • Try not to give up until you've given it a solid attempt

Challenge 1

Write code that outputs every number from 1 to 10.

void main() {
    <CODE HERE>
}

Challenge 2

What will this program output when run? Write down your guess and then try running it.

void main() {
    int x = 0;
    while (x < 10) {
        System.out.println(x);
        x++;
    }
}

Challenge 3

What will this program output when run? Write down your guess and then try running it.

void main() {
    int x = 0;
    while (x <= 10) {
        System.out.println(x);
        x++;
    }
}

Challenge 4

What will this program output when run? Write down your guess and then try running it.

void main() {
    int x = 0;
    while (x < 10) {
        if (x % 3 == 0) {
            break;
        }
        System.out.println(x);
        x++;
    }
}

Challenge 5

What will this program output when run? Write down your guess and then try running it.

void main() {
    int x = 0;
    while (x < 10) {
        if (x % 3 == 0) {
            continue;
        }
        System.out.println(x);
        x++;
    }
}

Challenge 6

What will this program output when run? Write down your guess and then try running it.

void main() {
    int x = 1;
    while (x < 10) {
        int y = 2;
        while (y < 5) {
            System.out.println(x * y);
            y++;
        }

        x++;
    }
}

Challenge 7

What will this program output when run? Write down your guess and then try running it.

void main() {
    <CODE HERE>
}

Challenge 8

Write code that will output each character of name on its own line.

So for if name is equal to "Bridget", I would expect the following as output.

B
r
i
d
g
e
t
void main() {
    <CODE HERE>
}

Challenge 9

Write code that will output each character of name on its own line, starting with the last character and going backwards.

So for if name is equal to "Samantha", I would expect the following as output.

a
h
t
n
a
m
a
S
void main() {
    // Change this value to test your code.
    String name = "Samantha";

    // <CODE HERE>
}

Challenge 10

Write code that will take a number and if it is divisible by two, divides it by two. If it is not, multiplies it by three and adds one.

Keep doing this until the number equals one. Output it each time.

If the initial number is 6 you should have this as output.

6
3
10
5
16
8
4
2
1

If the initial number is 15 you should have this as output.

15
46
23
70
35
106
53
160
80
40
20
10
5
16
4
2
1
void main() {
    // Change this value to test your code.
    int n = 15;

    // <CODE HERE>
}

Challenge 11

Write code that outputs every third number from 37 to 160.

void main() {
    <CODE HERE>
}

Challenge 12

Write code that outputs the number of vowels in name. Treat y as a vowel.

Treat the characters a, A, e, E, i, I, o, O, u, U, y, and Y as vowels.

void main() {
    // Change this value to test your code.
    String name = "Damian";

    // <CODE HERE>
}

Challenge 13

Write code that outputs {name} is mostly vowels if the number of vowels in name is greater than the number of consonants. and {name} is mostly consonants if the opposite is true. Output {name} has an equal number of vowels and consonants if the count of both is the same.

Make sure to not treat non-alphabetic characters like ! and ? as consonants.

void main() {
    // Change this value to test your code.
    String name = "Messi";

    // <CODE HERE>
}

Challenge 14

Rewrite the following code to not have the shouldBreak variable and instead to use a labeled break.

void main() {
    // Don't think too hard about what these numbers mean.
    int x = 3;
    int y = 0;

    boolean shouldBreak = false;
    while (shouldBreak && x < 100) {
        while (y < 100) {
            System.out.println("x is " + x);
            System.out.println("y is " + y);
            x = x * y;
            if (x == 0) {
                shouldBreak = true;
                break;
            }
            y++;
        }
    }

    System.out.println("Done");
}

Arrays

Arrays are used to represent a fixed-size collection of things.

int[] oddNumbers = { 1, 3, 5, 7, 9 };

Fixed-size means that once an array is made, it will always hold the same number of things.

We call the things stored in an array its "elements."

You can make an array of any type of element by using the name of the type followed by [].

char[] letters = { 'a', 'b', 'c' };
String[] words = { "its", "as", "easy", "as" }
int[] numbers = { 1, 2, 3 };
double[] doubles = { 97.0, 98.0, 99.0, 1.0, 2.0, 3.0 };

Array Initializers

To give an initial value to an array you can use an array initializer.

After the equals sign you write { followed by a comma separated list of elements and a final }.

int[] numbers = { 1, 2, 3 }
             // |---------|
             // this part is
             // the initializer

The elements in an initializer do not have to be literals and can also be variables or expressions.

int two = 2;
// Will hold 1, 2, 3 just like the array above
int[] numbers = { 1, two, two + 1 }

We call them array initializers because you use them to give an initial value to an array.1

1
You may be noticing a pattern. Confusing sounding names are often kinda "obvious"
with enough context.

Length

The number of elements which comprise an array can be accessed by using .length.1

String[] veggies = { "brussels", "cabbage", "carrots" };
int numberOfElements = veggies.length;

// veggies is 3 elements long
System.out.println(
    "veggies is " numberOfElements + " characters long"
);
1

Unlike with a String, you do not write () after .length.

Access Individual Elements

Given an array, you can access any of its elements by index.

You write the name of a variable containing an array, [, a number, and then a ].

The first element can be accessed by using 0, the second by using 1, and so on.

String[] lyrics = { "you", "say", "goodbye" };

String you = lyrics[0];
System.out.println(you);

String say = lyrics[1];
System.out.println(say);

String goodbye = lyrics[2];
System.out.println(goodbye);

The index of the element can also come from a variable.

int index = 2;
String[] lyrics = { "I", "say", "hello" };

System.out.println(lyrics[index]);

If you give a number equal to or greater than the length of the array or a number less than zero, you will get an error.

String[] lyrics = { "I", "say", "hi" };
// Crash!
lyrics[999];
String[] lyrics = { "you", "say", "low" };
// Crash!
lyrics[-1];

Set Individual Elements

You can also set any of the elements of an array to have a new value.

To do this, on the left hand side of an equals sign you write the name of a variable followed by [, an index, and ]. Then on the right hand side of the equals you write the new value.1

String[] sentence = { "you", "are", "found", "guilty" };
System.out.println(sentence);

sentence[1] = "aren't";
System.out.println(sentence);

The index of the element to set can also come from a variable.

int index = 2;
String[] response = { "and", "it", "isn't", "opposite", "day" };
System.out.println(response);

response[2] = "is";
System.out.println(response);

If you give a number equal to or greater than the length of the array or a number less than zero, you will get an error.

String[] response = { "objection" };
// Crash
response[1] = "!";
String[] response = { "sustained" };
// Crash
response[-1] = "not";
1
You cannot change the contents of a `String` like you would an array. This is one of the biggest
differences between a `String` and a `char[]`.

Aliasing

When you assign a variable containing an array to another variable, the array referenced by both variables will be the exact same.

This means that if the contents of the array are updated, that change will be reflected by both variables.

char[] lettersOne = { 'B', 'a', 't', 'm', 'a', 'n' };
char[] lettersTwo = lettersOne;

// Batman
System.out.println(lettersOne);
// Batman
System.out.println(lettersTwo);

lettersOne[0] = 'C';

// Catman
System.out.println(lettersOne);
// Catman
System.out.println(lettersTwo);

lettersTwo[0] = 'R';

// Ratman
System.out.println(lettersOne);
// Ratman
System.out.println(lettersTwo);

When two variables point to the same thing like this we say that both variables are "aliases" for eachother.

Reassignment

The length of an array cannot change, but a variable holding an array can be reassigned to a new array that has a different length.

int[] numbers = { 1, 2 };
// 2
System.out.println(numbers.length);

numbers = { numbers[0], numbers[1], 3 };
// 3
System.out.println(numbers.length);

This reassignment will not be affect any variables which are aliases for the variable's old value.

char[] wordOne = { 'g', 'o' };
char[] wordTwo = wordOne;
// go
System.out.println(wordOne);
// go
System.out.println(wordTwo);

wordOne = { wordOne[0], wordOne[1], 's', 'h' };

// gosh
System.out.println(wordOne);
// go
System.out.println(wordTwo);

wordTwo[0] = 'n';

// gosh
System.out.println(wordOne);
// no
System.out.println(wordTwo);

wordOne[0] = 'p';

// posh
System.out.println(wordOne);
// no
System.out.println(wordTwo);

Relation to Final Variables

Just like anything else, arrays can be stored in variables marked final.

This means that the variable cannot be reassigned, but it does not mean that the array's contents cannot be changed directly or through an alias.

final char[] catchphrase = { 'w', 'o', 'a', 'h', '!' };
// woah!
System.out.println(catchphrase);

// Cannot reassign
// catchphrase = { 'e', 'g', 'a', 'd', 's' }
// but can set elements directly
catchphrase[0] = 'e';
catchphrase[1] = 'g';

// or through an alias
char[] alias = catchphrase;
alias[2] = 'a';
alias[3] = 'd';
alias[4] = 's';

// egads
System.out.println(catchphrase);

Printing the Contents of an Array

If you try to use System.out.println to output a String[] you won't see the contents of the array. Instead you will see something like [Ljava.lang.String;@1c655221.

String[] shout = { "fus", "ro", "dah" };
// [Ljava.lang.String;@5a07e868
System.out.println(shout);

A similar thing will happen with int[], boolean[], and double[].1

int[] nums = { 11, 11, 11 };
// [I@5a07e868
System.out.println(nums);

boolean[] bools = { true, false };
// [Z@5a07e868
System.out.println(bools);

double[] doubles = { 1.1, 1.1, 1.1 };
// [D@5a07e868
System.out.println(bools);

The only kind of array which will include its contents when printed is a char[]. It will be printed as if it were a String.

char[] continent = { 'T', 'a', 'm', 'r', 'i', 'e', 'l' };
// Tamriel
System.out.println(continent);

If you want to actually see the contents of an array, you should use a loop.2

String[] factions = { "empire", "stormcloaks", "dragons" };

int index = 0;
while (index < factions.length) {
    System.out.println(factions[index])
    index++
}
1
What `[I@5a07e868` and co. mean isn't really important. Try not to
get too distracted by it.
2
Later on, there will be easier ways to do this sort of inspection. This is just the
one I can demonstrate now.

Empty Array

If you use an array initializer that has no elements between the { and } you can create an empty array.

char[] emptyCharArray = {};

An empty array is very similar to an empty String. It has a length of 0, it has no elements, and it is generally useful only as a placeholder value for when you have no data yet but will be able to reassign the variable holding it when you get some.

char[] emptyCharArray = {};

// 0
System.out.println(emptyCharArray.length);

// Crash
System.out.println(emptyCharArray[0]);

Difference between Initializer and Literal

The reason { 1, 2, 3 } is called an "array initializer" and not an "array literal" is somewhat subtle.

When you have a literal, like a String literal, you can assign that to a variable and then use that String afterwards.

String name = "Alana";
// l
System.out.println(name.charAt(1));

But you can also perform those operations using the literal itself, without an intermediate variable.

// l
System.out.println("Alana".charAt(1));

Array initializers work in the case where you first assign them to a variable before using the array.

char[] name = { 'A', 'm', 'a', 'n', 'd', 'a' };
// m
System.out.println(name[1]);

But they do not work to perform operations on directly.

// Will not run
System.out.println({ 'A', 'm', 'a', 'n', 'd', 'a' }[1]);

Challenges

Remember the rules for this are

  • Try to use only the information given up to this point in this book.
  • Try not to give up until you've given it a solid attempt

Challenge 1

Loops II

while loops are enough to make any looping logic that you might want, but they aren't the only kind of loops you will see.

There are tasks which would require a while loop, but are common enough that there are other kinds of loops that are shortcuts to writing them.

For

The for loop is a shortcut to writing a while loop which has distinct steps that

  • Declare a variable
  • Check that variable to know whether to stop iterating
  • Update the variable at the end of each iteration

As with many things, this might be easiest to see by looking at an example.

// Will run 10 times
for (int number = 0; number < 10; number++) {
    System.out.println(number);
}

That for loop works about the same as this while loop.

int number = 0;
while (number < 10) {
    System.out.println(number);

    number++;
}

For Syntax

A for loop has three distinct parts.

  1. An initializer.

  2. An expression which evaluates to a boolean.

  3. A statement.

for (<INITIALIZER> ; <EXPRESSION> ; <STATEMENT>) {
    <CODE HERE>
}

The initializer is a statement which declares and initializes a variable like int number = 0.

The expression is some check like number < 5 that is checked each iteration to know if the loop should continue.

The statement is ran at the end of every iteration, generally updating the variable tracked by the initializer and expression.

These can be thought of as being the same as a while loop written like so.

<INITIALIZER>;
while (<EXPRESSION>) {
    <CODE HERE>

    <STATEMENT>;
}

Counting Up and Down

One of the easiest things to do with a for loop is count up to or down from a given number.

// Goes from 1 to 100
for (int currentNumber = 1; currentNumber <= 100; currentNumber++) {
    System.out.println(currentNumber);
}

// Goes from 100 to 1
for (int currentNumber = 100; currentNumber >= 1; currentNumber--) {
    System.out.println(currentNumber);
}

You use the initializer to set some variable to a starting number like int currentNumber = 1, have the expression check if the number is at the target end number like currentNumber <= 100, and use the statement to change the number by one like currentNumber++.1

1
Very often, if you are given a test on `for` loops it will focus on doing all sorts of counting up, down, and around.
Be prepared.

Iterate over a String

As was shown with while loops, being able to count up and down lets you iterate over each character in a String.

String name = "Lavigne";

for (int index = 0; index < name.length(); index++) {
    System.out.println(name.charAt(index));
}

Iterate over an Array

In the same way you can use a for loop to go through each character of a String, you can use it to go through each element in an array.

int[] numbers = { 4, 1, 6, 9 };

for (int index = 0; index < numbers.length; index++) {
    System.out.println(numbers[index]);
}

The only difference from Strings is that instead of .length() and .charAt(...), you use .length and [].

Comparison to while

If you were to compare the code needed to loop over an array using a for loop and the code needed with a while loop, there might not seem like much of a difference.

double[] numbers = { 4.4, 1.1, 4.1, 4.7 };

for (int index = 0; index < numbers.length; index++) {
    System.out.println(numbers[index]);
}

int index = 0;
while (index < numbers.length) {
    System.out.println(numbers[index]);
    index++;
}

This is doubly true when we are looking at toy examples where the only thing done with the element is System.out.println.

The biggest benefit to a for is subtle. With a while based loop, the initializer and boolean expression can potentially be many lines from the statement which updates the variable.

int index = 0;
while (index < numbers.length) {
    /*
    Can


    potentially

    have

    arbitrary

    code

    you want to run

    a bunch

    of times
    */

    index++;
}

Us humans, with our tiny monkey brains, can get very lost when things that are related to eachother are separated by long distances.

In this dimension, for loops are superior. All the bits of code that "control the loop" can be right at the top.

for (int index = 0; index < numbers.length; index++) {
    /*
    Can


    potentially

    have

    arbitrary

    code

    you want to run

    a bunch

    of times
    */
}

i

One thing you will very often see if you read other peoples' code is that the variable being tracked in a for loop is often called i.

String word = "bird";

for (int i = 0; i < array.length; i++) {
    char letter = word.charAt(i);
    System.out.println(letter);
}

// b
// i
// r
// d

While usually naming variables with single letters isn't a great idea, most developers carve out an exception for cases like this. Writing index gets tedious.

Its also helpful to go i -> j -> k when you end up nesting for loops.1

char[] letters = { 'A', 'B', 'C' };
int[] numbers = { 1, 2 };

for (int i = 0; i < letters.length; i++) {
    for (int j = 0; j < numbers.length; j++) {
        System.out.print(letters[i]);
        System.out.println(numbers[j]);
    }
}

// A1
// A2
// B1
// B2
// C1
// C2

Just do not start naming all your variables single letters.

1

j and k standing for jindex an kindex respectfully.

Break

break works the same with for loops as it does with while loops. Any time you hit a line with break you will immediately exit the loop.

for (int i = 0; i < 1000; i++) {
    if (i == 5) {
        break;
    }
    System.out.println(i);
}
System.out.println("Over");

// 0
// 1
// 2
// 3
// 4
// Over

Continue

continue works slightly differently with for loops than how it does with while loops.

Any time you hit a line with continue you will immediately jump back to the top of the loop, but unlike with a while loop, the statement which updates your variable will still run.

for (int i = 0; i < 5; i++) {
    if (i == 2) {
        // i++ will still run
        continue;
    }
    System.out.println(i);
}

// 0
// 1
// 3
// 4

So the above for loop is not equivalent to this while loop.

int i = 0;
while (i < 5) {
    if (i == 2) {
        continue;
    }
    System.out.println(i);

    i++;
}

// 0
// 1
// ... spins forever ...

It is equivalent to this one.

int i = 0;
while (i < 5) {
    if (i == 2) {
        i++
        continue;
    }
    System.out.println(i);

    i++;
}

// 0
// 1
// 3
// 4

Delayed Assignment

The initializer of a for loop can give an initial value to a variable declared outside of the loop.

int number;
for (number = 0; number < 5; number++) {
    System.out.println("At: " + number);
}

You might choose to do this so that after the loop is finished, you can still access the variable.

int number;
for (number = 0; number < 5; number++) {
    System.out.println("At: " + number);
}

// This will work, we can access the variable still.
System.out.println("Ended at: " + number);

If you had put both the declaration and initial value inside the initializer, you won't be able to use that variable after the loop

for (int number = 0; number < 5; number++) {
    System.out.println("At: " + number);
}

// This will not work. number is no longer available
System.out.println("Ended at: " + number);

Inferred Types

The initializer of a for loop works the same as any variable assignment, so you still are allowed to use var so that the type of the declared variable is inferred.

for (var i = 0; i < 10; i++) {
    System.out.println(i);
}

var is the same number of letters as int so you aren't gaining much when your for loop is just counting over numbers.

But if your for loop is doing something more exotic, it might make sense.

for (var repeated = ""; repeated.length() < 5; repeated = repeated + "a") {
    System.out.println(repeated);
}

// a
// aa
// aaa
// aaaa

Empty Initializers

You are allowed to leave the initializer part of a for loop blank so long as you still have the ;.

int number = 0;
for (;number < 5; number++) {
    System.out.println(number);
}

You might choose to do this for the same reasons you might choose to split the declaration and assignment of the "loop variable." So that the variable will be accessible after the end of the loop.

This way its initialization and declaration can be on the same line, which might be desirable.

int number = 0;
for (;number < 5; number++) {
    System.out.println(number);
}
System.out.println("Still have number: " + number);

Empty Expressions

You are also allowed to leave the expression part of a for loop blank.

for (int i = 0;;i++) {
    System.out.println(i);
}
// 0
// 1
// 2
// 3
// ... and so on

This means that each time through there is no check to see if the loop will exit. The loop will only exit if there is an explicit break somewhere.

for (int i = 0;;i++) {
    if (i == 5) {
        break;
    }
    System.out.println(i);
}
// 0
// 1
// 2
// 3
// 4

Empty Statements

You can even leave the statement part of a for loop blank. This means that at the end of an iteration there is nothing guarenteed to run.

for (int i = 6; i > 2;) {
    System.out.println(i);
    i--;
}

// 6
// 5
// 4
// 3
// 2

If you leave both the initializer and statement blank, that will be functionally identical to a while loop.1

int number = 1;
for (;number < 10;) {
    System.out.println(number);
    number *= 2;
}

// Same logic as above
int number2 = 1;
while (number2 < 10) {
    System.out.println(number2);
    number2 *= 2;
}

If you leave the initializer, expression, and statement blank it will be the same as a while (true) loop.

for (;;) {
    System.out.println("The people stated singing it...");
}
// Runs forever

The only difference is that (;;) looks somewhat like

  • A spider
  • The Pokémon Kabuto
  • A person crying

And that can be fun.

Final Variables

The initializer of a for loop can also declare final variables.

int i = 0;
for (final String name = "Bob"; i < 5; i++) {
    System.out.println(name + ": " + i);
}

This doesn't have much use with loops that track ints and Strings, but if you are feeling clever you can use this ability along with arrays or other things you can change without reassigning a variable.

for (final char[] letters = { 'I', 'O', 'U' }; letters[0] != 'A';) {
    for (int i = 0; i < letters.length; i++) {
        letters[i] -= 1;
        System.out.print(letters[i]);
    }
    System.out.println();
}

// HNT
// GMS
// FLR
// EKQ
// DJP
// CIO
// BHN
// AGM

There aren't many reasons to do this, but it is in fact not against the law and I cannot stop you.

Labeled Break

Labeled breaks work the same with for loops as they do with while loops.

outerLoop:
for (;;) {
    for (;;) {
        break outerLoop;
    }
}

This applies also to when while loops are nested within for loops or the other way around.

outerForLoop:
for (int i = 0; i < 10; i++) {
    System.out.println(i);
    while (i < 100) {
        if (i == 5) {
            break outerForLoop;
        }
        i++;
    }
    System.out.println(i);
}

// 0

Labeled Continue

Labeled continues also work the same in for loops as while loops, but with the hopefully expected caveat that the statement of a for loop will always run when you get to the top of it.1

label:
for (int i = 0; i < 4; i++) {
    for (int j = 0; j < 3; j++) {
        System.out.println ("" + i + ", " + j);
        if (i == 2) {
            // i++ will run
            continue label;
        }
    }
}
// 0, 0
// 0, 1
// 0, 2
// 1, 0
// 1, 1
// 1, 2
// 2, 0
// 3, 0
// 3, 1
// 3, 2

Drawing Right Triangles

One of the more fun things to do with for loops1 is to use them to print out shapes.

Say you wanted to draw this right triangle.

*
**
***

There is one *, then two *s on the next line, and three *s on the last.

If you were to write the code out to print this explicitly it would look like this.

System.out.print("*\n**\n**\n");

Where \n is explicitly putting in the new lines.

Since counting up 1 -> 2 -> 3 is easy with for loops, you can translate this

for (int numberOfStars = 1; numberOfStars <= 3; numberOfStars++) {
    for (int i = 0; i < numberOfStars; i++) {
        System.out.print("*");
    }
    // Same as System.out.print("\n");
    System.out.println();
}

Which makes it easy to make one of these triangles however tall you want.

int height = 6;
for (int numberOfStars = 1; numberOfStars <= height; numberOfStars++) {
    for (int i = 0; i < numberOfStars; i++) {
        System.out.print("*");
    }
    System.out.println();
}
*
**
***
****
*****
******

Drawing Isosceles Triangles

Another fun shape is the isosceles triangle.

  *
 ***
*****

For this one, the each row of the triangle needs to have spaces before it to shift it in to the center. How much each row needs to be shifted depends on how big the trangle will be overall.

In this case with three rows of *s, the top * needs two space characters before it and the second row needs one space character.

System.out.println("   *\n  ***\n*****");

So any loop we make needs to take this pattern into account.

int totalRows = 5;
for (int row = 1; row <= totalRows; row++) {
    for (int i = 0; i < totalRows - row; i++) {
        System.out.print(" ");
    }
    for (int i = 0; i < row * 2 - 1; i++) {
        System.out.print("*");
    }
    System.out.println();
}
    *
   ***
  *****
 *******
*********

Which can get tricky. For now, you can just study the code that does it for this shape. There will be more things to draw in the challenges section.1

1

The reason I'm focusing on this isn't because its likely you will get a job drawing shapes, but if you can draw a shape you can dodge a ball.

Challenges

Remember the rules for this are

  • Try to use only the information given up to this point in this book.
  • Try not to give up until you've given it a solid attempt

You are extremely likely to be quizzed on for loops on any standardized tests, so these challenges are going to include a lot of repetition and sometimes a tricky case to handle. Its for your own good, I hope.

Challenge 1

Write code that will output every number from 0 to 15, including 0 and 15.

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Do it using a for loop and again using a while loop.

Challenge 2

Write code that will output every number from 15 to 0, including 0 and 15.

15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0

Do it using a for loop and again using a while loop.

Challenge 3

Write code that will output every number from 15 to 0, excluding 0 and 15.

14
13
12
11
10
9
8
7
6
5
4
3
2
1

Do it using a for loop and again using a while loop.

Challenge 4.

Write code that will output every third number from 51 to 66.

53
56
59
62
65

Do it using a for loop and again using a while loop.

Challenge 5.

Draw a square.

Make it so that you can make the square bigger or smaller by changing a variable at the start of the program.

*****
*****
*****
*****

Challenge 6.

Draw a rectangle.

Make it so that you can make the rectangle bigger or smaller in either dimension by changing a variable at the start of the program.

******
******
******

Challenge 7.

Draw a circle!

Make it so that you can make the circle bigger or smaller by changing a variable at the start of the program.

    **
   ****
  ******
 ********
  ******
   ****
    **

Challenge 8.

Draw a smiley face!

Make it so that you can make the smile bigger or smaller by changing a variable at the start of the program.

Methods

All the code you have seen up until this point has lived inside of void main() {}.

void main() {
    System.out.println("CODE GO HERE");
}

This isn't sustainable for a few reasons. One is that code can get big. Putting a thousand lines inside of one place can be a lot, let alone the hundreds of thousands you need to be Minecraft or the millions you need to be Google.

Another is that there is almost always code that you will want to run at multiple places in a program. Copy pasting that code can get old.

This is what methods are for. Methods let you split up your code into smaller, reusable chunks.1

1

The word method comes from a "method of getting things done." You might also hear methods referred to as "functions".

Declaration

The simplest kind of method is declared by writing void followed by some name, (), and some code inside of a { and }.

void doThing() {
    System.out.println("Hello from inside a method!");
}

Invocation

Once you've declared a method you can run the code inside of it by writing the name of the method followed by () in a statement.

void doThing() {
    System.out.println("Hello from inside a method!");
}

void main() {
    doThing();
}

Running the code in a method can be called a few things. "Running a method", "Calling a method", or "Invoking a method."1

You can call a method multiple times. If you do, then the code inside of it will be run multiple times.

void doThing() {
    System.out.println("Hello from inside a method!");
}

void main() {
    doThing();
    doThing();
}
1

I like that last one because "invoking" makes me sound like a Wizard.

Scope

Methods can contain any code, including variable declarations.

void sayMathStuff() {
    int x = 1;
    int y = 2;
    System.out.println("x is " + x);
    System.out.println("y is " + y);
    System.out.println("x + y is " + (x + y));
}

void main() {
    sayMathStuff();
}

When a method declares a variable inside of its body, that declaration is "scoped" to that method. Other code cannot see that variable.

void sayMathStuff() {
    int x = 1;
    int y = 2;
    System.out.println("x is " + x);
    System.out.println("y is " + y);
    System.out.println("x + y is " + (x + y));
}

void main() {
    sayMathStuff();
    // Error, x doesn't exist here
    System.out.println(x);
}

This is why we have called variables "local variables." They are local to the "scope" of the method they are declared in.

Return

Anywhere inside of a method you can write return to immediately exit that method.

void willReturnEarly() {
    for (int i = 0; i < 10; i++) {
        System.out.println(i);
        if (i == 5) {
            // Will stop at 5 because we exit the method
            return;
        }
    }

    System.out.println("THIS WONT RUN");
}

void main() {
    willReturnEarly();
}

This will break out of any loops and skip running any other code in the method.

void escapeFromLoops() {
    while (true) {
        for (;;) {
            for (;;) {
                while (true) {
                    // Escape!
                    return;
                }
            }
        }
    }
}

void main() {
    escapeFromLoops();
}

Unreachable Statements

If Java can figure out that some line of code is unreachable because it will always come after a return, then it will not run your code.

void doThing() {
    System.out.println("A");
    return;
    // unreachable statement
    System.out.println("B");
}

void main() {
    doThing();
}

Java is easy to trick though.1

void doThing() {
    System.out.println("A");
    if (true) {
        return;
    }
    System.out.println("B");
}

void main() {
    doThing();
}
1

This will always return before the println, but Java chooses to not figure that out. It can't be smart enough to see through every if, so it doesn't try for any of them.

main

The main method works the same as any other method. Java just treats it special by choosing to call it in order to start your programs.

void main() {
    System.out.println("Java will start here");
}

This means you can do anything in your main method you can do in any other method, including returning early.

void main() {
    int x = 5;

    if (x == 5) {
        return;
    }

    System.out.println("WONT RUN");
}

Challenges

Remember the rules for this are

  • Try to use only the information given up to this point in this book.
  • Try not to give up until you've given it a solid attempt

Challenge 1.

Declare a method named printSquare. When invoked it should print a square.

// CODE HERE

void main() {
    printSquare();
}

Challenge 2.

Declare a method named printSquareThreeTimes. When invoked it should print three squares by invoking a method named printSquare three times.

// CODE HERE

// Code from challenge 1 here

void main() {
    printSquareThreeTimes();
}

Challenge 3.

Write a program that contains at least four methods. Have fun with it.

void main() {
    // sing a song or something.
}

Arguments

If methods always had to do the same thing each time they were run, they wouldn't be that useful.

The way to customize what happens when a method is called is to have them take "arguments."

void sayHello(String name) {
    System.out.println("Hello " + name + "!");
}

void main() {
    // Hello Joshua!
    sayHello("Joshua");
    // Hello Claire!
    sayHello("Claire");
}

Declaration

To declare a method which takes arguments, instead of putting () after the method name you need to put a comma separated list of argument declarations.

Each argument declaration looks the same as a variable declaration and has both a type and a name.

// This declares a single argument named "food" that
// has a type of "String".
void eat(String food) {
    System.out.println("I ate " + food);
}

// This declares two arguments
// "to", which is a String and
// "age", which is an int.
void happyBirthday(String to, int age) {
    System.out.println(
        "Happy " + age + "th birthday " + to + "!"
    );
}

Invocation with Arguments

To invoke a method which takes arguments you need to, instead of writing () after the method name, write ( followed by a comma separated list of literals or variable names ending with ).

void eat(String food) {
    System.out.println("I ate " + food);
}

void happyBirthday(String to, int age) {
    System.out.println(
        "Happy " + age + "th birthday " + to + "!"
    );
}

void main() {
    // This calls the 'eat' method with the String "cake"
    // as an argument.
    eat("Cake");

    // You can also call methods using values stored in
    // variables.
    String veggie = "carrot";
    eat(veggie);

    // For more than one argument, you separate them with commas
    happyBirthday("Charlotte", 24);
}

Reassignment

Inside of a method, arguments work the same as normal variable declarations. This means that their value can be reassigned within the method body;

void eat(String food) {
    System.out.println("I ate " + food);
    food = "nothing";
    System.out.println("Now I have " + food)
}

void main() {
    eat("Cake");
}

Reassigning an argument's value will not affect the value assigned to any variables passed to the method by the caller.

void eat(String food) {
    System.out.println("I ate " + food);
    food = "nothing";
    System.out.println("Now I have " + food)
}

void main() {
    String fruit = "apple";
    eat(fruit);
    System.out.println(
        "But in the caller I still have an " + fruit
    );
}

Final Arguments

Just like normal variable declarations, arguments can be marked final. This makes it so that they cannot be reassigned.

void eat(final String food) {
    System.out.println("I ate " + food);
}

void main() {
    eat("Welsh Rarebit");
}

If you try to reassign a final argument, Java will not accept your program.

void eat(final String food) {
    System.out.println("I ate " + food);
    // Will not work
    food = "toast";
    System.out.println(food);
}

void main() {
    eat("Welsh Rarebit");
}

This has the same use as regular final variables. If there are lots of lines of code where a variable might be reassigned, it can be useful to not have to read all that code to know that it does happen.1

1
Adding `final` to all arguments can make it harder to read the code, simply
because of visual noise.

Aliasing

Because arguments work like variables, if you pass something like an array as an argument the array referenced by the argument will be the exact same as the array referenced by the variable given to the method.

void incrementFirst(int[] numbers) {
    numbers[0] = numbers[0] + 1;
}

void main() {
    int nums = new int[] { 8 };

    // The first number is 8
    System.out.println(
        "The first number is " + nums[0]
    );

    incrementFirst(nums);

    // Now it is 9
    System.out.println(
        "Now it is " + nums[0]
    );
}

The argument aliases the value passed to the method.

Overloading

Multiple methods can be declared that have the same name. This is allowed so long as each method takes different types or different numbers of arguments.

void doThing(int x) {
    System.out.println(x);
}

void doThing(String name) {
    System.out.println("Hello " + name);
}

void doThing(int x, int y) {
    System.out.println(x + y);
}

When you call the method, Java will know what code to run because it knows the types of and number of arguments you are passing.

void main() {
    // Java can figure out what to do
    doThing(1);
    doThing("abc");
    doThing(1, 2);
}

When there are multiple methods that have the same name but take different arguments, those methods are considered "overloads" of eachother1

1
"Overloading" in this context means when one word has more than
one possible meaning depending on how it is used. Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo.

Inferred Types

With variable declarations, you can use var to let Java figure out the type of the variable.

var name = "Jupiter";

This is not allowed with argument declarations.

// You aren't allowed to use var for arguments!
void makeHorchata(var milkFatPercent) {
    // ...
}

You must always explicitly write out the types of arguments.

void makeHorchata(double milkFatPercent) {
    System.out.println(
        "Making a horchata with " + milkFatPercent + "% milk."
    );
}

Challenges

Remember the rules for this are

  • Try to use only the information given up to this point in this book.
  • Try not to give up until you've given it a solid attempt

Challenge 1.

Write a method named printSquare which takes one int argument named size.

The size argument should control how big of a square is output.

// CODE HERE

void main() {
    printSquare(4);
    System.out.println();

    printSquare(3);
    System.out.println();

    printSquare(2);
    System.out.println();

    printSquare(1);
    System.out.println();
}

Challenge 2.

What happens if a negative number is given to your printSquare?

Make it so that if a negative number is given, it works the same as if a positive number was given.

// CODE HERE

void main() {
    printSquare(3);
    System.out.println();
    printSquare(-3);
    System.out.println();

    System.out.println();
    printSquare(-2);
    System.out.println();
    printSquare(2);
}

Challenge 3.

Return Values

In addition to running some code, a method can return a value to the code that is calling it.

To do this, instead of writing void before a method, you should write the name of a type like int. Then at the end of the method you need to write return followed by something which is that type.

int returnsEight() {
    return 8;
}

When the method is called, that expression can be used on the right hand side of an = to get the value returned by the method.

int returnsEight() {
    return 8;
}

void main() {
    int value = returnsEight();
    System.out.println(value);
}

The method call can also be used directly in expressions without assigning its value to a variable first.

String returnsName() {
    return "Mariah";
}

void main() {
    System.out.println(returnsName() + " is my name");
}

void

All methods have to declare some return type. void is what you write when a method won't return any value.

// Returns a String
String title() {
    return "All Night";
}

// Returns an int
int views() {
    return 4071;
}

// Doesn't return any value.
void talkAboutVideo() {
    System.out.println(title() + " only has " + views() + " views.");
}

// This is what the void in "void main()" means
void main() {
    talkAboutVideo();
}

Conversion

When a value is returned, Java will want to coerce it into the type of value that the method says it returns.

If Java knows how to do that conversion, then it can happen automatically.

// This method declares a return type of double.
double returnFive() {
    // x is an int
    int x = 5;
    // When it is returned, it will be turned into a double
    return x;
}

But if that conversion might potentially be lossy or, as with converting doubles to ints, you must do it yourself.

double returnNine() {
    double nine = 9.0;
    // The (int) explicitly converts the double to an int
    return (int) nine;
}

Pure Functions

When a method only uses its arguments in order to compute a return value but doesn't otherwise change the outside world, we call those methods "pure functions."

// square just uses x to compute the square of x
int square(int x) {
    return x * x;
}

If a method changes any values non-local to it, such as by assigning values to an array, we consider it to be "impure."

void multiplyAllByTwo(int[] numbers) {
    for (int i = 0; i < numbers.length; i++) {
        // This assignment is "impure" since it changes
        // something outside the method.
        numbers[i] = numbers[i] * 2;
    }
}

The term "pure" comes from the notion of "pure mathematics."

Pure functions are useful in the sense that they can be easier to understand on account of having what they do only depend on their inputs.

They can also be easier to verify. To know if a pure function does what you expect it to, you can give it example arguents and check to see that its return values are what you expect.

Impure Functions

User Input

Up until now all the code you have written has been "in its' own world."

Identity Types

Comparison with ==

Primitive Types

null

There is a special value called null which is assignable to any String

Checking for null

Field Access

Instance Methods

Boxed Primitives

Primitives

int, double, char, and bool are classified as "primitive types.

  1. Using ==will tell you

and types like String or int[] are

Integer

Double

Character

Boolean

Unboxing Conversion

Boxing Conversion

Arrays of Boxed Primitives

Challenges

Remember the rules for this are

  • Try to use only the information given up to this point in this book.
  • Try not to give up until you've given it a solid attempt

Challenge 1.

Write a method named printSquare which takes one int argument named size.

The size argument should control how big of a square is output.

// CODE HERE

void main() {
    printSquare(4);
    System.out.println();

    printSquare(3);
    System.out.println();

    printSquare(2);
    System.out.println();

    printSquare(1);
    System.out.println();
}

Challenge 2.

What happens if a negative number is given to your printSquare?

Make it so that if a negative number is given, it works the same as if a positive number was given.

// CODE HERE

void main() {
    printSquare(3);
    System.out.println();
    printSquare(-3);
    System.out.println();

    System.out.println();
    printSquare(-2);
    System.out.println();
    printSquare(2);
}

Challenge 3.

Arrays II

Default Values

Classes

Up until now all the data types you have used - int, String, etc. - came with Java. This works for awhile, but eventually you will want or need to define your own types.

The way to do this is with a "class."

class Person {

}

Every A class can be thought of as a "blueprint" for making an to represent things in your programs.

Methods can only have one return value. This means that if you wanted to make a method that returned two values, such as the location of buried treasure, you would have trouble.

// Can only declare one "thing" that will be returned
double getTreasureLocation() {
    // Can't return two values.
    return 43.8803, 103.4538
}

This is the first1 use of classes. You can declare your own class which can hold multiple values and use that to smuggle them across a method return.

class Location {
    double latitude;
    double longitude;
}

Location getTreasureLocation() {
    Location treasure = new Location();
    treasure.latitude = 43.8803;
    treasure.longitude = 103.4538;
    return treasure;
}

void main() {
    Location treasure = getTreasureLocation();

    System.out.println(
        "The treasure is at " +
        treasure.latitude +
        "N, " +
        treasure.longitude +
        "W."
    );
}
1

of many

Class Declaration

User Defined Types

Declaring a class

Naming Classes

Field Declaration

Field Access

Naming Fields

Fields are generally named camelCase, the same as local variables.1

class Example {
    int x;
    String name;
    int[] timesOfRacers;
    String[] namesOfClowns;
}
1

If you break a social rule, something Bad happens.

new

Zero Values

Aliasing

null

Constructors

this

The Default Constructor

Final Fields

Multiple Constructors

Instance Methods

Declaration

Invocation

this

Aliasing

Derived Values

Primitive Classes

Reference Classes