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
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.
Ferris | Meaning |
---|---|
This code does not compile! | |
This code panics! | |
This 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.
Click it and sign up for an account.
Step 2. Create a Java REPL
Find the "Create REPL" button and click it.
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".
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".
Click it and you should see the text Hello, world!
appear under the console window.
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 l
in
e.
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.
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);
}
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.
funToBeAround | believesInFundamentalHumanRights | willAskOnDate |
---|---|---|
true | true | true |
true | false | false |
false | true | false |
false | false | false |
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.
dogLooksNice | personLooksNice | willAskToPetDog |
---|---|---|
true | true | true |
true | false | true |
false | true | true |
false | false | false |
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.
haveOreosInHouse | stuckToCalorieLimit |
---|---|
false | true |
true | false |
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.
hasIceCream | hasCookie | validChoice |
---|---|---|
true | true | false |
true | false | true |
false | true | true |
false | false | false |
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 int
s 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 int
s 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 int
s 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 int
s 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 int
s can be inspected to see if their value is equal by using the ==
operator.
Unlike the previous operators, which all take int
s and produce int
s as their result, ==
takes two int
s
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 !=
, int
s 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;
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;
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.
- 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.
- 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 double
s 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 double
s 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 double
s 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 double
s 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
With the caveat that the result is now potentially inaccurate.
Equality
Just like int
s, double
s 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 !=
, doubles
s can be compared to see if one is bigger than another using
>
, <
, >=
, and <=
.
This works the same as it does with int
s.
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 double
s the same as they do with int
s.
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.
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 int
s are
representable as double
s 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 int
s is being assigned to
a double
, the computation will still be performed using the same rules int
s 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 char
s 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);
char
s will be automatically converted to int
s 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.
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 = '👨🍳';
char
s 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
String
s. - 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 String
s 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 char
s 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"
);
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);
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 println
s,
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.
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 if
s 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 if
s 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
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
"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
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"
);
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";
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++
}
What `[I@5a07e868` and co. mean isn't really important. Try not to
get too distracted by it.
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.
-
An initializer.
-
An expression which evaluates to a
boolean
. -
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
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 String
s 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.
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 int
s and String
s, 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
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
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();
}
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();
}
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
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
"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 double
s to int
s,
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.
- 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."
);
}
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;
}
If you break a social rule, something Bad happens.