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, it is theirs.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. I just don't know any other way to help you build an understanding of mechanics.
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 particuarly 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.
If I fail, 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 reccomend 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.
public class Main {
public static void main(String[] args) {
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.
public class Main {
public static void main(String[] args) {
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.
Unfortunately, for reasons that are impossible to explain with the context you have at this point, half of this probably reads as cryptic nonsense.
public class Main {
public static void main(String[] args) {
I don't want it to stay cryptic nonsense, but until we get there all you truly need to know is that Java uses all of that to know where to start the program.
public class Main {
public static void main(String[] args) {
< 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 the part you are squinting past, looks like this.
public class Main {
public static void main(String[] args) {
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.
public class Main {
public static void main(String[] args) {
// 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.
public class Main {
public static void main(String[] args) {
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.
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.
public class Main {
public static void main(String[] args) {
/*
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!");
}
}
Then, when there is a }
everything is "de-dented" one level.
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.
✅
public class Main {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
And not like this.
❌
public class Main
{
public static void main(String[] args)
{
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.
public class Main {
public static void main(String[] args) {
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?
public class Main {
public static void main(String[] args) {
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".
public class Main {
public static void main(String[] args) {
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.
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.
public class Main {
public static void main(String[] args) {
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.
public class Main {
public static void main(String[] args) {
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.
public class Main {
public static void main(String[] args) {
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
public class Main {
public static void main(String[] args) {
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.
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.
public class Main {
public static void main(String[] args) {
final String coolestChef = "Anthony Bourdain";
System.out.println(coolestChef);
}
}
If you try to reassign a final variable, Java will not accept your program.
public class Main {
public static void main(String[] args) {
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.
public class Main {
public static void main(String[] args) {
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.
public class Main {
public static void main(String[] args) {
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?
public class Main {
public static void main(String[] args) {
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
public class Main {
public static void main(String[] args) {
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.
public class Main {
public static void main(String[] args) {
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.
public class Main {
public static void main(String[] args) {
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.
public class Main {
public static void main(String[] args) {
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.
public class Main {
public static void main(String[] args) {
// 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 / 2;
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.
public class Main {
public static void main(String[] args) {
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.
public class Main {
public static void main(String[] args) {
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.
public class Main {
public static void main(String[] args) {
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.
public class Main {
public static void main(String[] args) {
System.out.println(5 / 0);
}
}
Challenge 5
What can you write in the spot marked that will make the program output 2?
public class Main {
public static void main(String[] args) {
int x = 5;
int y = <CODE HERE>;
System.out.println(x + y);
}
}
Challenge 6
What is the output of this code.1
public class Main {
public static void main(String[] args) {
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.
public class Main {
public static void main(String[] args) {
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.
public class Main {
public static void main(String[] args) {
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?
public class Main {
public static void main(String[] args) {
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
.
public class Main {
public static void main(String[] args) {
// 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.
public class Main {
public static void main(String[] args) {
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.
public class Main {
public static void main(String[] args) {
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 = spi.charAt(0);
System.out.println(l);
char o = spi.charAt(1);
System.out.println(o);
char i = spi.charAt(2);
System.out.println(i);
char d = spi.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.
public class Main {
public static void main(String[] args) {
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.
public class Main {
public static void main(String[] args) {
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.
public class Main {
public static void main(String[] args) {
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
?
public class Main {
public static void main(String[] args) {
char a = 'a';
char b = 'b';
char c = 'c';
// Change above this line
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.
public class Main {
public static void main(String[] args) {
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.
public class Main {
public static void main(String[] args) {
// 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.
public class Main {
public static void main(String[] args) {
// 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
.
public class Main {
public static void main(String[] args) {
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
.
public class Main {
public static void main(String[] args) {
<CODE HERE>
}
}
Challenge 2
What will this program output when run? Write down your guess and then try running it.
public class Main {
public static void main(String[] args) {
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.
public class Main {
public static void main(String[] args) {
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.
public class Main {
public static void main(String[] args) {
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.
public class Main {
public static void main(String[] args) {
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.
public class Main {
public static void main(String[] args) {
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.
public class Main {
public static void main(String[] args) {
int x = 0;
String scream = "a";
while (!scream.equals("aaaaaaaa")) {
scream = scream + "a";
System.out.println(x);
System.out.println(scream);
}
}
}
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
public class Main {
public static void main(String[] args) {
// Change this value to test your code.
String name = "Bridget";
// <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
public class Main {
public static void main(String[] args) {
// 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
public class Main {
public static void main(String[] args) {
// 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
.
public class Main {
public static void main(String[] args) {
<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.
public class Main {
public static void main(String[] args) {
// 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.
public class Main {
public static void main(String[] args) {
// 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.
public class Main {
public static void main(String[] args) {
// 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]);