0% found this document useful (0 votes)
686 views137 pages

Learn Access, Encapsulation, and Scope: Instructions

The document discusses the concepts of access and scope in Java programs. It explains that access and scope determine which parts of a program can interact with variables and methods in other parts. The key points covered are: - The public and private keywords control access to classes, variables, constructors, and methods. - Accessor and mutator methods are used to control access to private variables through getter and setter methods. - Local variables have a narrower scope than instance variables. - An example program demonstrates errors from trying to access private variables, and how to fix it by making the variables public.

Uploaded by

IliasAhmed
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
686 views137 pages

Learn Access, Encapsulation, and Scope: Instructions

The document discusses the concepts of access and scope in Java programs. It explains that access and scope determine which parts of a program can interact with variables and methods in other parts. The key points covered are: - The public and private keywords control access to classes, variables, constructors, and methods. - Accessor and mutator methods are used to control access to private variables through getter and setter methods. - Local variables have a narrower scope than instance variables. - An example program demonstrates errors from trying to access private variables, and how to fix it by making the variables public.

Uploaded by

IliasAhmed
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 137

My Home

Course Menu -java
Connected to Codeca

Access, Encapsulation, and Scope: What are Access and Scope?

Narrative and Instructions

Learn
ACCESS, ENCAPSULATION, AND SCOPE
What are Access and Scope?
As our Java programs begin to get bigger and we begin to have multiple Objects and Classes that
interact with each other, the concepts of access and scope come into play. To oversimplify
things, the concepts of access and scope both center around what parts of your programs can
interact with specific variables or methods from other parts of your program. Let’s take a brief
look at some of the concepts we’ll cover:

Access

 The public and private keywords and how they relate to Classes, variables, constructors,


and methods
 The concept of encapsulation
 Accessor methods, sometimes known as “getters”
 Mutator methods, sometimes known as “setters”

Scope

 Local variables vs. instance variables


 The this keyword

Let’s get started!

Instructions

For now, let’s get a preview of how access works in Java. In the code editor, you should see two
files - Bank.java and CheckingAccount.java. Take a look at each file and notice the instance
variables are declared using the private keyword. When you’re ready, select the Bank.java file,
and run your code.
You should get two errors! Take a look at the main() method in Bank.java. Our Bank is trying to
access some instance variables from a CheckingAccount that is marked as private! Take a look at
the error message to see which variables are giving us trouble.
Bank.java

public class Bank{

private CheckingAccount accountOne;

private CheckingAccount accountTwo;

public Bank(){

accountOne = new CheckingAccount("Zeus", 100);

accountTwo = new CheckingAccount("Hades", 200);

public static void main(String[] args){

Bank bankOfGods = new Bank();

System.out.println(bankOfGods.accountOne.name);

System.out.println(bankOfGods.accountOne.balance);

Checkingaccount.java

public class CheckingAccount{

private String name;

private int balance;

public CheckingAccount(String inputName, int inputBalance){


name = inputName;

balance = inputBalance;

}
My Home
Course Menu
Connected to Codecademy
Get Unstuck
Tools

Access, Encapsulation, and Scope: The public Keyword

Narrative and Instructions

Learn
ACCESS, ENCAPSULATION, AND SCOPE
The public Keyword
After running the code in the last exercise, you should be developing an intuition on what
the public and private keywords are doing. These keywords are defining what parts of your code
have access to other parts of your code.

We can define the access of many different parts of our code including instance variables,
methods, constructors, and even a class itself. If we choose to declare these as public this means
that any part of our code can interact with them - even if that code is in a different class!

The way we declare something to be public is to use the public keyword in the declaration


statement. In the code block below, we have a public class, constructor, instance variables, and
method. Notice the five different uses of public.

public class Dog{


  public String name;
  public int age;

  public Dog(String input_name, int input_age){


    name = input_name;
    age = input_age;
  }

  public void speak() {


    System.out.println("Arf Arf! My name is " + name + " and I am
a good dog!");
  }
}
Since everything about a Dog is public, any other class can access anything about a Dog. For
example, let’s say there was a DogSchool class. Any method of the DogSchool class could make a
new Dog using the public Dog constructor, directly access that Dog’s instance variables, and
directly use that Dog’s methods:

public class DogSchool{


  public void makeADog(){
    Dog cujo = new Dog("Cujo", 7);
    System.out.println(cujo.age);
    cujo.speak();
  }
}
Notice that the DogSchool class and the makeADog() method are also public. This means that if
some other class created a DogSchool, they would have access to these methods as well! We have
public methods calling public methods!

One final thing to note is that for the purposes of this lesson, we’ll almost always make our
classes and constructors public. While you can set them to private, it’s fairly uncommon to do
so. Instead, we’ll focus on why you might make your instance variables and methods private.
We’ll start looking into the private keyword in the next exercise.

Instructions

1.
Once again we’ve given you a Bank class and a CheckingAccount class. First, take a look
at CheckingAccount.java to see what methods and variables have been set to private or public.
Then, switch to Bank.java, look at the main method, and hit the “Run” button. You should get
an error. Why?
Checkpoint 2 Passed

Hint
The main method is trying to access three different fields from CheckingAccount that are
all private. Those would need to be public in order for Bank‘s main() method to run.
2.
In Bank.java‘s main() method, we’re trying to access three different private fields from
the CheckingAccount class. Edit the checking account class to make those fields public. Make
sure to edit only the fields you need in order to make Bank‘s main() method run — don’t change
any of the other fields in CheckingAccount.

After you’re done editing CheckingAccount.java, go back to Bank.java and run your code.


A Bank should now have access to these fields from a CheckingAccount.
Hint
Bank‘s main() method is trying to directly access a CheckingAccount‘s .name instance variable.
That variable is private. It’s also trying to use CheckingAccount‘s private .addFunds() method.
Finally, Bank‘s main() method is trying to call its own .getInfo() method. This method tries to
print the private .address instance variable of all of its CheckingAccounts.
Checkingaccount.java

public class Bank{

private CheckingAccount accountOne;

private CheckingAccount accountTwo;

public Bank(){

accountOne = new CheckingAccount("ilias", 100, "1");

accountTwo = new CheckingAccount("ahmed", 200, "2");

public static void main(String[] args){

Bank bankOfGods = new Bank();

System.out.println(bankOfGods.accountOne.name);

bankOfGods.accountOne.addFunds(5);

bankOfGods.accountOne.getInfo();

My Home
Course Menu
Workspace restored.
Get Unstuck
Tools
Access, Encapsulation, and Scope: The public Keyword

Narrative and Instructions

Learn
ACCESS, ENCAPSULATION, AND SCOPE
The public Keyword
After running the code in the last exercise, you should be developing an intuition on what
the public and private keywords are doing. These keywords are defining what parts of your code
have access to other parts of your code.

We can define the access of many different parts of our code including instance variables,
methods, constructors, and even a class itself. If we choose to declare these as public this means
that any part of our code can interact with them - even if that code is in a different class!

The way we declare something to be public is to use the public keyword in the declaration


statement. In the code block below, we have a public class, constructor, instance variables, and
method. Notice the five different uses of public.

public class Dog{


  public String name;
  public int age;

  public Dog(String input_name, int input_age){


    name = input_name;
    age = input_age;
  }

  public void speak() {


    System.out.println("Arf Arf! My name is " + name + " and I am
a good dog!");
  }
}
Since everything about a Dog is public, any other class can access anything about a Dog. For
example, let’s say there was a DogSchool class. Any method of the DogSchool class could make a
new Dog using the public Dog constructor, directly access that Dog’s instance variables, and
directly use that Dog’s methods:

public class DogSchool{


  public void makeADog(){
    Dog cujo = new Dog("Cujo", 7);
    System.out.println(cujo.age);
    cujo.speak();
  }
}
Notice that the DogSchool class and the makeADog() method are also public. This means that if
some other class created a DogSchool, they would have access to these methods as well! We have
public methods calling public methods!

One final thing to note is that for the purposes of this lesson, we’ll almost always make our
classes and constructors public. While you can set them to private, it’s fairly uncommon to do
so. Instead, we’ll focus on why you might make your instance variables and methods private.
We’ll start looking into the private keyword in the next exercise.

Instructions

1.
Once again we’ve given you a Bank class and a CheckingAccount class. First, take a look
at CheckingAccount.java to see what methods and variables have been set to private or public.
Then, switch to Bank.java, look at the main method, and hit the “Run” button. You should get
an error. Why?
Checkpoint 2 Passed

Hint
The main method is trying to access three different fields from CheckingAccount that are
all private. Those would need to be public in order for Bank‘s main() method to run.
2.
In Bank.java‘s main() method, we’re trying to access three different private fields from
the CheckingAccount class. Edit the checking account class to make those fields public. Make
sure to edit only the fields you need in order to make Bank‘s main() method run — don’t change
any of the other fields in CheckingAccount.

After you’re done editing CheckingAccount.java, go back to Bank.java and run your code.


A Bank should now have access to these fields from a CheckingAccount.
Checkpoint 3 Passed

Hint
Bank‘s main() method is trying to directly access a CheckingAccount‘s .name instance variable.
That variable is private. It’s also trying to use CheckingAccount‘s private .addFunds() method.
Finally, Bank‘s main() method is trying to call its own .getInfo() method. This method tries to
print the private .address instance variable of all of its CheckingAccounts.

Checkingaccount.java

public class CheckingAccount{

public String name;

private int balance;


private String id;

public CheckingAccount(String inputName, int inputBalance, String inputId){

name = inputName;

balance = inputBalance;

id = inputId;

public void addFunds(int fundsToAdd){

balance += fundsToAdd;

public void getInfo(){

System.out.println("This checking account belongs to " + name +". It has " + balance + " dollars in it.");

Bank.java

public class Bank{

private CheckingAccount accountOne;

private CheckingAccount accountTwo;

public Bank(){

accountOne = new CheckingAccount("ilias", 100, "1");

accountTwo = new CheckingAccount("ahmed", 200, "2");


}

public static void main(String[] args){

Bank bankOfGods = new Bank();

System.out.println(bankOfGods.accountOne.name);

bankOfGods.accountOne.addFunds(5);

bankOfGods.accountOne.getInfo();

}
My Home
Course Menu
Connected to Codecademy
Get Unstuck
Tools

Access, Encapsulation, and Scope: The private Keyword and Encapsulation

Narrative and Instructions

Learn
ACCESS, ENCAPSULATION, AND SCOPE
The private Keyword and Encapsulation
By now you’re probably catching onto what the private keyword does. When a Class’ instance
variable or method is marked as private, that means that you can only access those structures
from elsewhere inside that same class. Let’s look back at our DogSchool example:

public class DogSchool{

  public void makeADog(){


    Dog cujo = new Dog("Cujo", 7);
    System.out.println(cujo.age);
    cujo.speak();
  }
}
makeADog is trying to directly access Dog‘s .age variable. It’s also trying to use
the .speak() method. If those are marked as private in the Dog class, the DogSchool class won’t be
able to do that. Other methods within the Dog class would be able to use .age or .speak() (for
example, we could use cujo.age within the Dog class), but other classes won’t have access.

Keep Reading: AP Computer Science A Students

At this point, you might be thinking to yourself “Why even bother with any of this? In the last
exercise, my code was broken until I flipped some variables and methods to public. Why don’t I
just make everything public?”

While those are valid points, sometimes restricting our code is actually useful from a design
perspective. This is one of the core ideas behind encapsulation. By making our instance variables
(and some methods) private, we encapsulate our code into nice little bundles of logic.
For example, a Bank object doesn’t necessarily need to know the inner workings of
a CheckingAccount object. It doesn’t need to know that the money is stored in a field
named money, or that interest is added to an account by using a method named .addInterest(). In
fact, if it had access to those fields or methods, it’s possible that someone using a Bank object
could change things in a CheckingAccount without realizing it. By limiting access by using
the private keyword, we are able to segment, or encapsulate, our code into individual units.

Note that we don’t necessarily want to completely block everything from other classes. In the
next exercise, we’ll get into when you might want to make methods public — we’ll take a look
at getter and setter methods.

Instructions

1.
We’ve changed the variables and methods in CheckingAccount.java back to private. To begin,
go to Bank.java and run your code. Let’s confirm that we get errors when a Bank tries to
access private data from a CheckingAccount
2.
A Bank couldn’t access a CheckingAccount‘s private structures. Let’s prove to ourselves
that CheckingAccount can access its own private fields.

Go to CheckingAccount.java. In the main() method, create a


new CheckingAccount named myAccount. You’ll have to use the constructor that takes a String and
an int.

Run CheckingAccount.java to create this object.


Hint
You can create a new CheckingAccount like this:

CheckingAccount myAccount = new CheckingAccount("Lisa", 2000);


3.
Let’s confirm that we can access a CheckingAccount‘s private fields since we’re writing
in CheckingAccount‘s main() method. Still in CheckingAccount.java, print
out myAccount‘s balance.
Hint
You’ll want to print myAccount.balance
4.
Let’s also confirm that we can use private methods. Call addFunds() to add 5 dollars
to myAccount‘s balance. Then print the balance again to confirm the money was added. Continue
to do this work in the main() method of CheckingAccount.java.
Hint
You’ll want to call myAccount.addFunds() and use 5 as an argument to the method.

Bank.java
public class Bank{

private CheckingAccount accountOne;

private CheckingAccount accountTwo;

public Bank(){

accountOne = new CheckingAccount("Zeus", 100);

accountTwo = new CheckingAccount("Hades", 200);

public static void main(String[] args){

Bank bankOfGods = new Bank();

System.out.println(bankOfGods.accountOne.name);

bankOfGods.accountOne.addFunds(5);

bankOfGods.accountOne.getInfo();

CheckingCCCOUNT.JAVA

public class Bank{

private CheckingAccount accountOne;

private CheckingAccount accountTwo;

public Bank(){

accountOne = new CheckingAccount("Zeus", 100);


accountTwo = new CheckingAccount("Hades", 200);

public static void main(String[] args){

Bank bankOfGods = new Bank();

System.out.println(bankOfGods.accountOne.name);

bankOfGods.accountOne.addFunds(5);

bankOfGods.accountOne.getInfo();

public class CheckingAccount{

private String name;

private int balance;

public CheckingAccount(String inputName, int inputBalance){

name = inputName;

balance = inputBalance;

private void addFunds(int fundsToAdd){

balance += fundsToAdd;

}
private void getInfo(){

System.out.println("This checking account belongs to " + name +". It has " + balance + " dollars in it.");

public static void main(String[] args){

}
My Home
Course Menu
Workspace restored.
Get Unstuck
Tools

Access, Encapsulation, and Scope: The private Keyword and Encapsulation

Narrative and Instructions

Learn
ACCESS, ENCAPSULATION, AND SCOPE
The private Keyword and Encapsulation
By now you’re probably catching onto what the private keyword does. When a Class’ instance
variable or method is marked as private, that means that you can only access those structures
from elsewhere inside that same class. Let’s look back at our DogSchool example:

public class DogSchool{

  public void makeADog(){


    Dog cujo = new Dog("Cujo", 7);
    System.out.println(cujo.age);
    cujo.speak();
  }
}
makeADog is trying to directly access Dog‘s .age variable. It’s also trying to use
the .speak() method. If those are marked as private in the Dog class, the DogSchool class won’t be
able to do that. Other methods within the Dog class would be able to use .age or .speak() (for
example, we could use cujo.age within the Dog class), but other classes won’t have access.

Keep Reading: AP Computer Science A Students

At this point, you might be thinking to yourself “Why even bother with any of this? In the last
exercise, my code was broken until I flipped some variables and methods to public. Why don’t I
just make everything public?”

While those are valid points, sometimes restricting our code is actually useful from a design
perspective. This is one of the core ideas behind encapsulation. By making our instance variables
(and some methods) private, we encapsulate our code into nice little bundles of logic.
For example, a Bank object doesn’t necessarily need to know the inner workings of
a CheckingAccount object. It doesn’t need to know that the money is stored in a field
named money, or that interest is added to an account by using a method named .addInterest(). In
fact, if it had access to those fields or methods, it’s possible that someone using a Bank object
could change things in a CheckingAccount without realizing it. By limiting access by using
the private keyword, we are able to segment, or encapsulate, our code into individual units.

Note that we don’t necessarily want to completely block everything from other classes. In the
next exercise, we’ll get into when you might want to make methods public — we’ll take a look
at getter and setter methods.

Instructions

1.
We’ve changed the variables and methods in CheckingAccount.java back to private. To begin,
go to Bank.java and run your code. Let’s confirm that we get errors when a Bank tries to
access private data from a CheckingAccount
Checkpoint 2 Passed

2.
A Bank couldn’t access a CheckingAccount‘s private structures. Let’s prove to ourselves
that CheckingAccount can access its own private fields.

Go to CheckingAccount.java. In the main() method, create a


new CheckingAccount named myAccount. You’ll have to use the constructor that takes a String and
an int.

Run CheckingAccount.java to create this object.


Checkpoint 3 Passed

Hint
You can create a new CheckingAccount like this:

CheckingAccount myAccount = new CheckingAccount("Lisa", 2000);


3.
Let’s confirm that we can access a CheckingAccount‘s private fields since we’re writing
in CheckingAccount‘s main() method. Still in CheckingAccount.java, print
out myAccount‘s balance.
Checkpoint 4 Passed

Hint
You’ll want to print myAccount.balance
4.
Let’s also confirm that we can use private methods. Call addFunds() to add 5 dollars
to myAccount‘s balance. Then print the balance again to confirm the money was added. Continue
to do this work in the main() method of CheckingAccount.java.
Checkpoint 5 Passed

Hint
You’ll want to call myAccount.addFunds() and use 5 as an argument to the method.

public class CheckingAccount{


private String name;

private int balance;

public CheckingAccount(String inputName, int inputBalance){

name = inputName;

balance = inputBalance;

private void addFunds(int fundsToAdd){

balance += fundsToAdd;

private void getInfo(){

System.out.println("This checking account belongs to " + name +". It has " + balance + " dollars in it.");

public static void main(String[] args){

CheckingAccount myAccount = new CheckingAccount("Lisa", 2000);

System.out.println(myAccount.balance);

myAccount.addFunds(5);

System.out.println(myAccount.balance);

BANK.JAVA
public class Bank{

private CheckingAccount accountOne;

private CheckingAccount accountTwo;

public Bank(){

accountOne = new CheckingAccount("Zeus", 100);

accountTwo = new CheckingAccount("Hades", 200);

public static void main(String[] args){

Bank bankOfGods = new Bank();

System.out.println(bankOfGods.accountOne.name);

bankOfGods.accountOne.addFunds(5);

bankOfGods.accountOne.getInfo();

}
My Home
Course Menu
Connected to Codecademy
Get Unstuck
Tools

Access, Encapsulation, and Scope: Accessor and Mutator Methods

Narrative and Instructions

Learn
ACCESS, ENCAPSULATION, AND SCOPE
Accessor and Mutator Methods
When writing classes, we often make all of our instance variables private. However, we still
might want some other classes to have access to them, we just don’t want those classes to know
the exact variable name. To give other classes access to a private instance variable, we would
write an accessor method (sometimes also known as a “getter” method).

public class Dog{


  private String name;

  //Other methods and constructors

  public String getName() {


    return name;
  }
}
Even though the instance variable name is private, other classes could call
the public method getName() which returns the value of that instance variable. Accessor methods
will always be public, and will have a return type that matches the type of the instance variable
they’re accessing.

Similarly, private instance variables often have mutator methods (sometimes known as


“setters”). These methods allow other classes to reset the value stored in private instance
variables.

public class Dog{


  private String name;

  //Other methods and constructors


  public void setName(String newName) {
    name = newName;
  }

  public static void main(String[] args){


    Dog myDog = new Dog("Cujo");
    myDog.setName("Lassie");
  }
}
Mutator methods, or “setters”, often are void methods — they don’t return anything, they just
reset the value of an existing variable. Similarly, they often have one parameter that is the same
type as the variable they’re trying to change.

Instructions

1.
Take a look at the main() method of Bank.java. Right now it’s trying to directly access and
change the balance in a checking account. Unfortunately, that instance variable is private. Run
your code with Bank.java open. You should expect an error.
2.
Let’s go to CheckingAccount.java and write an accessor method for the balance instance field.
Your method should be named getBalance(). This method should be public.

When you’re done writing that method, go back to the main() method in Bank.java and change
the code to use that new method.
Hint
getBalance() should return an int. Then, in Bank.java, replace the reference
to bankOfGods.accountOne.balance with bankOfGods.accountOne.getBalance().
3.
Let’s do the same for a mutator method. In CheckingAccount.java, write a mutator method
named setBalance() that has an int parameter named newBalance. The method should set
the balance instance variable to the value passed into the method.

After writing this method, go back to Bank.java and add a line of code to your main() method
where you use setBalance() to set accountOne‘s balance to 5000.

After setting the balance to 5000, use your .getBalance() method again to print out the new
balance.
Hint
Your method should be a void method — it doesn’t return anything. In Bank.java,
use bankOfGods.accountOne.setBalance(5000).

public class Bank{

private CheckingAccount accountOne;


private CheckingAccount accountTwo;

public Bank(){

accountOne = new CheckingAccount("ilias", 100, "1");

accountTwo = new CheckingAccount("ahmed", 200, "2");

public static void main(String[] args){

Bank bankOfGods = new Bank();

System.out.println(bankOfGods.accountOne.getBalance());

bankOfGods.accountOne.setBalance(5000);

System.out.println(bankOfGods.accountOne.getBalance());

public class CheckingAccount{

private String name;

private int balance;

private String id;

public CheckingAccount(String inputName, int inputBalance, String inputId){

name = inputName;

balance = inputBalance;

id = inputId;
}

public int getBalance(){

return balance;

public void setBalance(int newBalance){

balance = newBalance;

}
My Home
Course Menu
Connected to Codecademy
Get Unstuck
Tools

Access, Encapsulation, and Scope: Scope: Local Variables

Narrative and Instructions

Learn
ACCESS, ENCAPSULATION, AND SCOPE
Scope: Local Variables
In addition to access modifiers like public and private, the scope of the variable also determines
what parts of your code can access that variable.

The scope of a variable is determined by where the variable is declared. For example, because
instance variables are declared inside a class but outside any methods or constructors, all
methods and constructors are within the scope of that variable. For example, in the code block
below, constructors and methods of the Dog class are using the Dog instance variables
like name and age:

class Dog{
  public String name;
  public int age;
  public int weight;

  public Dog(){
    name = "Winston";
    age = 8;
    weight = 30;
  }

  public void speak(){


    System.out.println("My name is " + name);
  }
}
However, if we have a variable declared inside a method, that variable can only be used inside
that method. The same is true for parameters. The scope of those parameters is only the method
they’re associated with. If you try to use a parameter outside the function it’s defined in, you’ll
get an error. These variables are often called local variables. Note that we don’t
use public or private when declaring local variables.

This idea of scope extends to conditionals and loops as well. If you declare a variable inside the
body of a conditional or in a loop, that variable can only be used inside that structure. This also
includes the variable you’re using as your looping variable. For example, consider the following
block of code:

for(int i = 0; i < 10; i++){


  // You can use i here
}
// i is out of scope here
You can only use i between the curly braces of the for loop. In general, whenever you see curly
braces, be aware of scope. If a variable is defined inside curly braces, and you try to use that
variable outside of those curly braces, you will likely see an error!

Instructions

1.
Take a look at the main() method which tries to sum the values from a list. Right now, we’re
looping through the values and trying to store the sum in a variable called sum. However, that
variable is declared inside the for loop.

There are two problems with this. The first is a logical error. Since we’re setting int sum = 0; at
the start of the loop, every time the loop runs, sum gets reset back to 0.

However, there is also a syntactical error. Right now we try to print sum after the loop. But that’s
outside of sum‘s scope since the variable was declared inside the loop.

Run your code as-is. You should expect to get an error related to the scope of sum.
2.
Move the line of code int sum = 0; to be above the for loop. Now the for loop has access
to sum and we’re able to return sum after the loop finishes.

After moving the line of code, run your code to test the main() method.
Hint
Your code should be structured like this. Notice the location of sum‘s declaration:

public static void main(String[] args){

  int[] myArray = {1, 2, 3, 4};


  int sum = 0;

  for(int i = 0; i < myArray.length; i++){


      sum += myArray[i];
  }
}

scopeexample.java

public class ScopeExample{

public static void main(String[] args){

int[] myArray = {1, 2, 3, 4};

int sum = 0;

for(int i = 0; i < myArray.length; i++){

sum += myArray[i];

System.out.println(sum);

}
ACCESS, ENCAPSULATION, AND SCOPE
Scope: The this Keyword
Often times when creating classes, programmers will create local variables
with the same name as instance variables. For example, consider the code
block below:

public class Dog{


  public String name;

  public Dog(String inputName){


    name = inputName;
  }

  public void speakNewName(String name){


    System.out.println("Hello, my new name is" + name);
  }

  public static void main(String[] args){


    Dog myDog = new Dog("Winston");
    myDog.speakNewName("Darla"); // Prints "Darla" - "Winston"
ignored

  }
}
We have an instance variable named name, but the method speakNewName has a
parameter named name. So when the method tries to print name, which variable
will be printed? By default, Java refers to the local variable name. So in this
case, the value passed to the parameter will be printed and not the instance
variable.

If we wanted to access the instance variable and not the local variable, we
could use the this keyword.

public class Dog{


  public String name;

  public Dog(String inputName){


    name = inputName;
  }
  public void speakNewName(String name){
    System.out.println("Hello, my new name is" + this.name);
  }

  public static void main(String[] args){


    Dog a = new Dog("Fido");
    Dog b = new Dog("Odie");

    a.speakNewName("Winston");
    // "Fido", the instance variable of Dog a is printed.
"Winston" is ignored

    b.speakNewName("Darla");
    // "Odie", the instance variable of Dog b is printed.
"Darla" is ignored.
  }
}
The this keyword is a reference to the current object. We used this.name in
our speakNewName() method. This caused the method to print out the value
stored in the instance variable name of whatever Dog Object
called speakNewName(). (Note that in this somewhat contrived example, the local
variable name used as a parameter gets completely ignored).

Oftentimes, you’ll see constructors have parameters with the same name as
the instance variable. For example, you might see something like:

public Dog(String name){


  this.name = name;
}
You can read this as “set this Dog‘s instance variable name equal to the variable
passed into the constructor”. While this naming is a common convention, it
can also be confusing. There’s nothing wrong with naming your parameters
something else to be more clear. Sometimes you will see something like:

public Dog(String inputName){


  this.name = inputName;
}
This is now a little clearer — we’re setting the Dog‘s instance variable name equal
to the name we give the constructor.

Finally, mutator methods also usually follow this pattern:

public void setName(String name){


  this.name = name;
}
We reset the instance variable to the value passed into the parameter.

Throughout the rest of this lesson, we’ll use this. when referring to an


instance variable. This isn’t always explicitly necessary — if there’s no local
variable with the same name, Java will know to use the instance variable with
that name. That being said, it is a good habit to use this. when working with
your instance variables to avoid potential confusion.

Instructions

1.
Take a look at the instance variables for our SavingsAccount class. There are
three of them. owner, balanceDollar, balanceEuro. Next, take a look at the
constructor we’ve started for you. The job of the constructor is to initialize
these instance variables.

Complete the constructor to give value to all three instance variables. The
instance variable owner should be set to the local variable owner. The instance
variable balanceDollar should be set equal to the local variable balanceDollar.
Finally, the instance variable balanceEuro should be set equal to the local
variable balanceDollar multiplied by 0.85. (Right now, every dollar is
worth 0.85 euros.)
Hint
You can set the instance variable owner equal to the local variable owner by
writing this.owner = owner; inside the constructor.
2.
Next, look at the addMoney() method. This method should add the value stored
in the parameter balanceDollar to the instance variable balanceDollar. Before
adding the money to the account, print out the statement "Adding ____
dollars to the account.".After adding the money, print the statement "The new
balance is _____ dollars.". Be careful of spacing, capitalization, and
punctuation with your print statements.

Call the addMoney() method once in the main() method to test your code.


Add 2000 dollars to Zeus’s account.

(Note that this function should probably be updating balanceEuro as well


based on the parameter. We won’t test your code for that, but you can try
implementing it yourself. Also, note that balanceDollar is a pretty bad name for
the parameter of this function. Something like moneyToAdd would make more
sense. But for the sake of practicing local variables vs instance variables, keep
the parameter named balanceDollar.)
Hint
The first print statement should be System.out.println("Adding " +
balanceDollar + " dollars to the account.")

When you update the balance, you should do this.balanceDollar +=


balanceDollar.

Finally, when writing the second print statement, make sure to print the
instance variable, using this.balanceDollar.

In the main method, call zeusSavingsAccount.addMoney(2000);

Savingaccount.java

public class SavingsAccount{

public String owner;

public int balanceDollar;

public double balanceEuro;

public SavingsAccount(String owner, int balanceDollar){


// Complete the constructor

this.owner = owner;

this.balanceDollar = balanceDollar;

this.balanceEuro = balanceDollar * 0.85;

public void addMoney(int balanceDollar){

// Complete this method

System.out.println("Adding " + balanceDollar + " dollars to the account.");

this.balanceDollar += balanceDollar;

System.out.println("The new balance is " + this.balanceDollar + " dollars.");

public static void main(String[] args){

SavingsAccount zeusSavingsAccount = new SavingsAccount("Zeus", 1000);

// Make a call to addMoney() to test your method

zeusSavingsAccount.addMoney(2000);

}
My Home
Course Menu
Workspace restored.
Get Unstuck
Tools

Access, Encapsulation, and Scope: Using this With Methods

Narrative and Instructions

Learn
ACCESS, ENCAPSULATION, AND SCOPE
Using this With Methods
We’ve seen how the this works with variables, but we can also use the this with methods.

Recall how we’ve been calling methods up to this point:

public static void main(String[] args){


  Dog myDog = new Dog("Odie");
  myDog.speak();
}
Here we’re creating an instance of a Dog and using that Dog to call the speak() method. However,
when defining methods, we can also use the this keyword to call other methods. Consider the
code block below:

public class Computer{


  public int brightness;
  public int volume;

  public void setBrightness(int inputBrightness){


    this.brightness = inputBrightness;
  }

  public void setVolume(int inputVolume){


    this.volume = inputvolume;
  }

  public void resetSettings(){


    this.setBrightness(0);
    this.setVolume(0);
  }
}
Take a look at the resetSettings() method in particular. This method calls other methods from
the class. But it needs an object to call those methods! Rather than create a new object (like we
did with the Dog named myDog earlier), we use this as the object. What this means is that the
object that calls resetSettings() will be used to call setBrightness(0) and setVolume(0).

public static void main(String[] args){


  Computer myComputer = new Computer();
  myComputer.resetSettings();
}
In this example, calling myComputer.resetSettings() is as if we
called myComputer.setBrightness(0) and myComputer.setVolume(0). this serves as a placeholder
for whatever object was used to call the original method.

Keep Reading: AP Computer Science A Students

Finally, this can be used as a value for a parameter. Let’s say a method exists that takes
a Computer as a parameter (that method’s signature might be something like public void
pairWithOtherComputer(Computer other) . If you’re writing another method of the Computer, and
want to call the pairWithOtherComputer() method, you could use this as the parameter. That call
might look something like this.pairWithOtherComputer(this). You’re using the current object to
call the method and are passing that object as that method’s parameter.

public void pairWithOtherComputer(Computer other){


  // Code for method that uses the parameter other
}

public void setUpConnection(){


  // We use "this" to call the method and also pass "this" to the
method so it can be used in that method
  this.pairWithOtherComputer(this);
}

Instructions

1.
We’ve given you a Person class with three instance variables — age, wisdom, and fitness. Those
values all get initialized to different values when the constructor is called. We’ve also provided
you with mutator methods for all three variables.

Complete the hasBirthday() method. This method should call the mutator methods to


increase age by 1, increase wisdom by 5, and decrease fitness by 3.

When you’re done writing hasBirthday() look at the main() method to see how we’re calling it.
Checkpoint 2 Passed

Hint
Within the hasBirthday() method, you should be calling three methods using the this keyword
— this.setAge(), this.setWisdom() and this.setFitness().

Each of those methods take a parameter. The parameter for setAge() should be this.age + 1 —
we’re setting the new age to be the current age plus one.

public class Person{

public int age;

public int wisdom;

public int fitness;

public Person(int inputAge){

this.age = inputAge;

this.wisdom = inputAge * 5;

this.fitness = 100 - inputAge;

public void setAge(int newAge){

this.age = newAge;

public void setWisdom(int newWisdom){

this.wisdom = newWisdom;

public void setFitness(int newFitness){

this.fitness = newFitness;

}
public void hasBirthday(){

//Complete this method

this.setAge(this.age + 1);

this.setWisdom(this.wisdom + 5);

this.setFitness(this.fitness - 3);

public static void main(String[] args){

Person emily = new Person(20);

emily.hasBirthday();

System.out.println("New age is: " + emily.age);

System.out.println("New wisdom is: " + emily.wisdom);

System.out.println("New fitness is: " + emily.fitness);

}
My Home
Course Menu
Workspace restored.
Get Unstuck
Tools

Access, Encapsulation, and Scope: Other Private Methods

Narrative and Instructions

Learn
ACCESS, ENCAPSULATION, AND SCOPE
Other Private Methods
Now that we’ve seen how methods can call other methods using this., let’s look at a situation
where you might want to use private methods. Oftentimes, private methods are helper methods
— that is to say that they’re methods that other, bigger methods use.

For example, for our CheckingAccount example, we might want a public method


like getAccountInformation() that prints information like the name of the account owner, the
amount of money in the account, and the amount of interest the account will make in a month.
That way, another class, like a Bank, could call that public method to get all of that information
quickly.

Well, in order to get that information, we might want to break that larger method into several
helper methods. For example, inside getAccountInformation(), we might want to call a function
called calculateNextMonthInterest(). That helper method should probably be private. There’s
no need for a Bank to call these smaller helper methods — instead, a Bank can call the
one public method, and rely on that method to do all of the complicated work by calling
smaller private methods.

Instructions

1.
Let’s implement what we described in the narrative. We’ve written
our getAccountInformation() method in the CheckingAccount.java class. But we haven’t yet
implemented the calculateNextMonthInterest() method. This should be a private method and
return a double — the balance of the account multiplied by the interestRate. Write that function.

Then flip back to Bank.java and take a look at the main() method. We’re


calling bankOfGods.accountOne.getAccountInformation();. Will a Bank be able to do this? Run
your code to find out.
Checkpoint 2 Passed
Hint
getAccountInformation() is public, so you should be able to use it in the Bank class.
2.
Nice work! We were able to get all of the account information, including the next month’s
interest, even though calculateNextMonthInterest() is private.

Let’s prove to ourselves that we can’t call this private method from a Bank.


In Bank.java‘s main() method, try
calling bankOfGods.accountOne.calculateNextMonthInterest(); .

You should see an error since you’re trying to use a Bank to call a private method from
a Checking

Bank.java

public class Bank{

private CheckingAccount accountOne;

private CheckingAccount accountTwo;

public Bank(){

this.accountOne = new CheckingAccount("Zeus", 100, "1");

this.accountTwo = new CheckingAccount("Hades", 200, "2");

public static void main(String[] args){

Bank bankOfGods = new Bank();

bankOfGods.accountOne.getAccountInformation();

bankOfGods.accountOne.calculateNextMonthInterest();

}
Checkingaccount.java

--------------------------/

public class CheckingAccount{

private String name;

private int balance;

private String id;

private double interestRate;

public CheckingAccount(String inputName, int inputBalance, String inputId){

this.name = inputName;

this.balance = inputBalance;

this.id = inputId;

this.interestRate = 0.02;

public void getAccountInformation(){

System.out.println("Money in account: " + this.getBalance());

System.out.println("Next Month's Interest: " + this.calculateNextMonthInterest());

private int getBalance(){

return this.balance;

}
// Write the calculateNextMonthInterest() here

private double calculateNextMonthInterest(){

return this.interestRate * this.balance;

}
My Home
Course Menu
Connected to Codecademy
Get Unstuck
Tools

Access, Encapsulation, and Scope: Revi ew

Narrative and Instructions

Learn
ACCESS, ENCAPSULATION, AND SCOPE
Review
Nice work! In this lesson, we dove into some of the more subtle features of classes with a focus
on access, encapsulation, and scope. Here are some of the main takeaways from this lesson:

 The public and private keywords are used to define what parts of code have access to


other classes, methods, constructors, and instance variables.
 Encapsulation is a technique used to keep implementation details hidden from other
classes. Its aim is to create small bundles of logic.
 The this keyword can be used to designate the difference between instance variables and
local variables.
 Local variables can only be used within the scope that they were defined in.
 The this keyword can be used to call methods when writing classes.

Instructions

We’ve given you our full code for our Bank and CheckingAccount classes. Feel free to continue to
experiment with the public and private keywords to get a better understanding of what code has
access to certain structures.

https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html
My Home
Course Menu
Workspace restored.
Get Unstuck
Tools

Static Variables and Methods: Static Variables

Narrative and Instructions

Learn
STATIC VARIABLES AND METHODS
Static Variables
We’ll begin writing our own static methods soon, but before we do, let’s take a look at static
variables. Much like static methods, you can think of static variables as belonging to the class
itself instead of belonging to a particular object of the class.

Just like with static methods, we can access static variables by using the name of the class and
the . operator. Finally, we declare static variables by using the static keyword during
declaration. This keyword usually comes after the variable’s access modifier (public or private).

When we put this all together, we might end up with a class that looks something like this:

public class Dog{

  // Static variables


  public static String genus = "Canis";

  //Instance variables
  public int age;
  public String name;

  public Dog(int inputAge, String inputName){


    this.age = inputAge;
    this.name = inputName;
  }
}
Since all dogs share the same genus, we could use a static variable to store that information for
the entire class. However, we want each dog to have it’s own unique name and age, so those
aren’t static. We could now access this static variable in a main() function like so:
public class Dog{
  //Variables, constructors and methods defined here

  public static void main(String[] args){


    System.out.println(Dog.genus); // Prints Canis
  }
}
Unlike static methods, you can still access static variables from a specific object of the class.
However, no matter what object you use to access the variable, the value will always be the
same. You can think of it as all objects of the class sharing the same variable

public static void main(String[] args){


  Dog snoopy = new Dog(3, "Snoopy");
  Dog ringo = new Dog(5, "Ringo");

  System.out.println(Dog.genus); // Prints Canis


  System.out.println(snoopy.genus); // Prints Canis
  System.out.println(ringo.genus); // Prints Canis
}
Finally, you might have seen a few static variables before. If you want easy access to the largest
possible integer, you can get it by using Integer.MAX_VALUE. If you look at the official
documentation you’ll see that this variable is public, static, and final. (final means that you
can’t change the variable’s value after creating it.) We’re starting to know a lot of Java
keywords!

Instructions

1.
We’re going to be building out an ATM class that has both static and non-static variables. We’ve
started by giving you an ATM class with non-static variables, a constructor, and some methods.
In the main() method, use the constructor to create two ATMs named firstATM and secondATM. Use
the constructor so the first ATM has 1000 dollars in it and the second has 500.

If you’d like, you could print out each ATM‘s money variable to confirm you created them
successfully.
Checkpoint 2 Passed

Hint
You can use the constructor to create an ATM with 50 dollars in it like so:

ATM myATM = new ATM(50);


2.
Let’s create two static variables.

First, we want to create a variable to keep track of how much money is in the system across
all ATMs. This should be a public static int variable and should be named totalMoney. This
variable should begin with a value of 0.
Second, we want to know how many ATMs there are in the system. Again, this should be a public
static int variable that has an initial value of 0. Name this variable numATMs.
Checkpoint 3 Passed

Hint
Create these two variables where you would create your instance variables. The first should
be public static int totalMoney = 0;.
3.
Let’s take a look at the first of these static variables. In the main() method, print
your totalMoney variable three different times. The first time, you should use ATM.totalMoney, the
second time you should use firstATM.totalMoney, and the third time you should
use secondATM.totalMoney. Do you expect these print statements to be the same or different?

Right now the value stored in totalMoney doesn’t actually represent the total amount of money
stored in all ATMs. In the next exercise, we’ll look into how to change the value of static
variables.
Checkpoint 4 Passed

Hint
You should see the same value printed each time. Every ATM object shares the
same totalMoney variable.

public class ATM{

// Step 2: Create your static variables here

public static int totalMoney = 0;

public static int numATMs = 0;

// Instance variables

public int money;

public ATM(int inputMoney){

this.money = inputMoney;

public void withdrawMoney(int amountToWithdraw){

if(amountToWithdraw <= this.money){


this.money -= amountToWithdraw;

public static void main(String[] args){

// Step 1: Create your two ATMs here

ATM firstATM = new ATM(1000);

ATM secondATM = new ATM(500);

System.out.println(firstATM.money);

System.out.println(secondATM.money);

// Step 3: Print your static variable in three different ways here

System.out.println(ATM.totalMoney);

System.out.println(firstATM.totalMoney);

System.out.println(secondATM.totalMoney);

My Home
Course Menu
Connected to Codecademy
Get Unstuck
Tools
Static Variables and Methods: Modifying Static Variables

Narrative and Instructions

Learn
STATIC VARIABLES AND METHODS
Modifying Static Variables
Now that we’ve created a couple of static variables, let’s start to edit them. The good news is that
editing static variables is similar to editing any other variable. Whether you’re writing code in a
constructor, a non-static method, or a static method, you have access to static variables.

Before we jump into the checkpoints, let’s think about times when you might want to edit static
variables. Often times, you’ll see static variables used to keep track of information about all
objects of a class. For example, our variable numATMs is keeping track of the total number of ATMs
in the system. Therefore, every time an ATM is created (using the constructor), we should increase
that variable by 1. If we could somehow destroy an ATM, the method that destroys it should
decrease numATMs static variable by 1.

Similarly, we have a variable named totalMoney. This variable is keeping track of all money
across all ATMs. Whenever we remove money from an ATM using the non-
static withdrawMoney() method, we should modify the money instance variable for that particular
ATM as well as the totalMoney variable. In doing so, all ATMs will know how much money is in
the system.

Instructions

1.
Edit the constructor to increase numATMs by 1 every time an ATM is created. In the main method,
we’re printing out numATMs before and after creating some ATMs. You should expect to see that
number go up as you create ATMs.
Hint
In the constructor, you’ll want to add numATMs += 1;
2.
Edit the constructor so when a new ATM is created, the amount of money that ATM starts with gets
added to the static variable totalMoney.
Hint
You’ll want to add inputMoney to totalMoney.
3.
Edit the withdrawMoney() method so when money is taken out of a specific ATM, the static
variable totalMoney also reflects that change.
Take a look at the main() method — we’re printing totalMoney before and after withdrawing
money from a couple of ATMs.
Hint
Right after this.money -= amountToWithdraw;, write totalMoney -= amountToWithdraw;.

public class ATM{

// Static variables

public static int totalMoney = 0;

public static int numATMs = 0;

// Instance variables

public int money;

public ATM(int inputMoney){

this.money = inputMoney;

// Steps 1 and 2: Edit numATMs and total money here

public void withdrawMoney(int amountToWithdraw){

if(amountToWithdraw <= this.money){

this.money -= amountToWithdraw;

// Step 3: Edit totalMoney here

public static void main(String[] args){


System.out.println("Total number of ATMs: " + ATM.numATMs);

ATM firstATM = new ATM(1000);

ATM secondATM = new ATM(500);

System.out.println("Total number of ATMs: " + ATM.numATMs);

System.out.println("Total amount of money in all ATMs: " + ATM.totalMoney);

firstATM.withdrawMoney(500);

secondATM.withdrawMoney(200);

System.out.println("Total amount of money in all ATMs: " + ATM.totalMoney);

}
My Home
Course Menu
Workspace restored.
Get Unstuck
Tools

Static Variables and Methods: Modifying Static Variables

Narrative and Instructions

Learn
STATIC VARIABLES AND METHODS
Modifying Static Variables
Now that we’ve created a couple of static variables, let’s start to edit them. The good news is that
editing static variables is similar to editing any other variable. Whether you’re writing code in a
constructor, a non-static method, or a static method, you have access to static variables.

Before we jump into the checkpoints, let’s think about times when you might want to edit static
variables. Often times, you’ll see static variables used to keep track of information about all
objects of a class. For example, our variable numATMs is keeping track of the total number of ATMs
in the system. Therefore, every time an ATM is created (using the constructor), we should increase
that variable by 1. If we could somehow destroy an ATM, the method that destroys it should
decrease numATMs static variable by 1.

Similarly, we have a variable named totalMoney. This variable is keeping track of all money
across all ATMs. Whenever we remove money from an ATM using the non-
static withdrawMoney() method, we should modify the money instance variable for that particular
ATM as well as the totalMoney variable. In doing so, all ATMs will know how much money is in
the system.

Instructions

1.
Edit the constructor to increase numATMs by 1 every time an ATM is created. In the main method,
we’re printing out numATMs before and after creating some ATMs. You should expect to see that
number go up as you create ATMs.
Checkpoint 2 Passed

Hint
In the constructor, you’ll want to add numATMs += 1;
2.
Edit the constructor so when a new ATM is created, the amount of money that ATM starts with gets
added to the static variable totalMoney.
Checkpoint 3 Passed
Hint
You’ll want to add inputMoney to totalMoney.
3.
Edit the withdrawMoney() method so when money is taken out of a specific ATM, the static
variable totalMoney also reflects that change.

Take a look at the main() method — we’re printing totalMoney before and after withdrawing


money from a couple of ATMs.
Checkpoint 4 Passed

Hint
Right after this.money -= amountToWithdraw;, write totalMoney -= amountToWithdraw;.

Atm.java

public class ATM{

// Static variables

public static int totalMoney = 0;

public static int numATMs = 0;

// Instance variables

public int money;

public ATM(int inputMoney){

this.money = inputMoney;

// Steps 1 and 2: Edit numATMs and total money here

numATMs += 1;

totalMoney += inputMoney;

public void withdrawMoney(int amountToWithdraw){

if(amountToWithdraw <= this.money){


this.money -= amountToWithdraw;

// Step 3: Edit totalMoney here

totalMoney -= amountToWithdraw;

public static void main(String[] args){

System.out.println("Total number of ATMs: " + ATM.numATMs);

ATM firstATM = new ATM(1000);

ATM secondATM = new ATM(500);

System.out.println("Total number of ATMs: " + ATM.numATMs);

System.out.println("Total amount of money in all ATMs: " + ATM.totalMoney);

firstATM.withdrawMoney(500);

secondATM.withdrawMoney(200);

System.out.println("Total amount of money in all ATMs: " + ATM.totalMoney);

Review
Great work! You now have an understanding of what the static keyword does.
In fact, if you’ve made it this far in your Java lessons, you probably have a
pretty good sense of what all the keywords and jargon are doing in public
static void main(String[] args). Take a moment to celebrate — that line of
code can be incredibly intimidating for new learners and it’s a real
accomplishment to learn about all of those different pieces.

To review, here are some of the main takeaways about static methods and
variables:

 Static methods and variables are associated with the class as a whole,
not objects of the class.
 Static methods and variables are declared as static by using
the static keyword upon declaration.
 Static methods cannot interact with non-static instance variables. This is
due to static methods not having a this reference.
 Both static methods and non-static methods can interact with static
variables.

Instructions

We’ve given you the complete co

public class ATM{

// Static variables

public static int totalMoney = 0;

public static int numATMs = 0;

// Instance variables

public int money;

public ATM(int inputMoney){

this.money = inputMoney;

numATMs += 1;
totalMoney += inputMoney;

public void withdrawMoney(int amountToWithdraw){

if(amountToWithdraw <= this.money){

this.money -= amountToWithdraw;

totalMoney -= amountToWithdraw;

public static void averageMoney(){

System.out.println(totalMoney / numATMs);

public static void main(String[] args){

System.out.println("Total number of ATMs: " + ATM.numATMs);

ATM firstATM = new ATM(1000);

ATM secondATM = new ATM(500);

System.out.println("Total number of ATMs: " + ATM.numATMs);

System.out.println("Total amount of money in all ATMs: " + ATM.totalMoney);

firstATM.withdrawMoney(500);

secondATM.withdrawMoney(200);

System.out.println("Total amount of money in all ATMs: " + ATM.totalMoney);


// Call averageMoney() here

ATM.averageMoney();

}
Project:

LEARN JAVA
2D Arrays: Image Manipulation Project
In this project, you will be creating an application which is able to modify
images as well as create new images using 2D arrays! The first section covers
stretching the image horizontally, shrinking the image vertically, negating the
color, applying a color filter, and inverting the image. The second section
covers creating an image consisting of random pixels, placing a rectangle in
the image, and using the method to randomly place many rectangles in the
image.

Here is an overview about how images work in Java:

Images consist of pixels which are the individual points in the image
containing some color. Each pixel has some red, green, blue, and alpha value
which represents the amount of each of those colors in the pixel. The red,
green, and blue values can be mixed to create all of the visible colors on your
screen. The alpha value represents the transparency of the pixel (or how close
the color of the pixel is to the background color of the image). A higher
resolution image means that there are more pixels contained within it.

In Java, a loaded image is stored into a BufferedImage object. From this object,


we can extract each pixel value and store it into a 2D array which we can
manipulate. The pixel values are stored as ints because each pixel value in
the BufferedImage object is represented by a hexadecimal value which contains
the red, green, blue, and alpha components. The maximum value of any of the
RGBA values is 255 and the minimum is 0. There are some methods provided
for you in this project which handle the conversion between images and 2D
arrays as well as extracting the R, G, B, and A values from a pixel. You will only
need to implement methods which work with the 2D arrays.

Each of these methods is executable independently so you can select which


methods you want to complete or you can complete all of them. You also may
want to adjust the window sizes in the workspace to better see the code and
the image. You can drag the window borders to adjust the size.
There are a lot of different parts to this project, so you may feel overwhelmed
when first looking at it. Remember, the goal here is to practice using 2D
arrays. We’ve included the solution code as a file named Solution.java in case
you get stuck.

Tasks

64/64 Complete
Mark the tasks as complete by checking them off
Provided Method Details
1.
The first two sections of this project have you investigating the code that we
have provided for you. You won’t need to write any code, but it’s important to
understand the input and output of each of these methods.

There are four utility methods provided for you. The first method
called imgToTwoD() accepts a String which can be a file path or image URL. It
returns a 2D array of integers that contains every pixel from the image stored
as int hexadecimal values containing the RGBA values for the pixel. Take a
look at how the method works in the code editor. In the main() method, we
can load image data into a 2D array of ints using the imgToTwoD() method.
Note that you can use one of the provided images or load one from a URL.

We’ve provided "./apple.jpg", "./flower.jpg", and "./kitten.jpg".


2.
The second provided method is called twoDToImage(). It accepts a 2D array of
integers and a String for the file name. It converts the 2D array of int pixel
data into an image and saves it.

We’ll use this method to create images after we modify the 2D array of ints.

Take a look at how the method works in the code editor.


3.
The third provided method is the getRGBAFromPixel() method. This method
accepts an int value representing the pixel hexadecimal value and returns a 4
element int array consisting of the R, G, B, and A values (between 0 and 255).
Take a look at how the method works in the code editor. In Java, pixels are
stored as hexadecimal values. This method is used to extract the color
components from the hexadecimal value for the pixel.
4.
The fourth provided method is the getColorIntValFromRGBA() method. This
method accepts an array of integers that represent the RGBA values and
convert it into a single int value representing the pixel hexadecimal value.
Take a look at how the method works in the code editor. Since pixels in Java
are stored as hexadecimal values, this method converts the array of red, green,
blue, and alpha values back into a hexadecimal value.
5.
In addition to these utility methods, there is a method used for extracting a
3x3 section from the top left of the image called viewImageData. This method is
used to view the structure of the image data in both the raw pixel form and
the extracted RGBA form. In the main() method, uncomment the call
to viewImageData after the image is loaded (This should be line 14 if you
haven’t edited the code yet). Save the code and take a look at the console
output.

After looking at the output, feel free to re-comment this line of code to help
clean up your output for the rest of the project.
Example Method Walkthrough
6.
To start this project, we will look at an example of how to load, manipulate,
and save an image step-by-step with provided code. We will look at
the trimBorders() method. This method accepts a 2D array of int pixel data
and the number of pixels to trim off of the borders of the image. It returns the
modified image 2D array. Start by scrolling to where this method is defined in
the project code.
7.
Try looking through the method and following along with the code. Look at
how a portion of the original image is copied over to the new modified image.
The input of this method is a 2D array containing the input image data and
the output of this method is a new 2D array representing the modified image.
A detailed description of this method is in the hint for this task.
The main takeaways are that given a 2D array of ints, we make a new 2D array,
and fill that array with some values from the given array. There’s some fancy
math to make sure we fill the new array with the correct values, but the
essential thing you should focus on is the fact that given a 2D array, we return
a new 2D array.
Stuck? Get a hint
8.
Once we have completed iterating, we return the modified image data. Now
scroll back to the main() method in the code.

In the main() method, we load image data into a 2D array of ints using


the imgToTwoD() method. Note that you can use the provided image or load
one from a URL. After this, we can simply call our method we created by
passing in the loaded image data and storing the returned modified image
data into a new 2D array of ints. Finally, we can call the twoDToImage() method
using the modified image data to save the new image with a provided file
name.
9.
Save the code in the editor which will run the application. Now we can view
this modified image by entering the image file name which we saved into the
browser on the side of the workspace. The project defaults
to http://localhost:8000/apple.jpg so change the last part of the URL to match
the image name which was saved. Hit enter and the image will appear in the
browser window. You can also try changing the file name and loading the
image in the browser.
Stuck? Get a hint
Create a Negative Version of the Image
10.
Now let’s fill in the negativeColor() method. This method will replace the color
of each pixel in the image with the negative version of the pixel. This means
that each color component of the pixel (R, G, and B) will be replaced with 255
minus the current value. We’ll be aiming to create an image that looks like
this:
Scroll down to where this method is defined.
11.
Begin by creating a new 2D array of ints which is the same size as the input
image and setting up nested for loops that iterate through every pixel in the
input image. It’s probably easiest to iterate through the pixels in row-major
order.
Stuck? Get a hint
12.
Within the inner for loop, we need to get the R, G, B, and A values from each
pixel. You can use the provided method getRGBAFromPixel() to accomplish this.
This returns an array where each of the four elements corresponds to the
RGBA values. Elements 0 to 2 represent red, green, and blue while element 3
represents alpha. Using the method will look something like: int[] rgba =
getRGBAFromPixel(imageTwoD[i][j]); depending on your iterator names.
Stuck? Get a hint
13.
Now that you have the array containing the RGBA values, you need three lines
of code which set the first three elements to 255 minus itself.
Stuck? Get a hint
14.
Afterwards add another line of code which gets the int hexadecimal pixel data
from the RGBA array. you can use the
provided getColorIntValFromRGBA() method. You then need to store this value
in the new image you created.
Stuck? Get a hint
15.
Once the for loops are complete, you need to return the modified image. In
the main() method, load an image and pass it into the negativeColor() method.
Save the modified image and view it in the browser.
Stretch the Image Horizontally
16.
For this task, you will be implementing the method stretchHorizontally(). This
method will double the width of the provided image data. For every pixel in
the original image, you will copy it and place two duplicate pixels side-by-side
into the new modified image. You’ll be looking to create an image like this:

In the code editor, scroll to this empty method.


17.
The first thing you should do in the method is to create a new 2D array of ints
to hold the modified image data. The number of rows (or height) should be
the same, but the number of columns (or width) should be the twice the
number of columns from the original image. You can set the new 2D array to
equal: new int[imageTwoD.length][imageTwoD[0].length*2]
Stuck? Get a hint
18.
Next, set up nested for loops to iterate through every pixel in the input image
using row-major order. To make things easier for us in the future, we can
create an additional variable which will keep track of which position we are in
for the modified image (since it is double the width). This variable will equal
double the column index in the inner for loop. For example, if our inner loop is
using columnIndex as the iterator. We can set our variable to equal: it =
columnIndex*2;
Stuck? Get a hint
19.
After we have created that additional iterator, we can now copy and duplicate
each pixel from the input image. We need two lines of code. One to copy the
current pixel to the modifiedImage[rowIndex][it] position and one to copy the
current pixel to the modifiedImage[rowIndex][it+1] position. it is the doubled
iterator from the last step and the current pixel from the input image is
accessed using the outer and inner loop iterators. In the example we can
assume that those are rowIndex and columnIndex, but it depends on the variable
names you use.
Stuck? Get a hint
20.
Once the for loops are complete, you need to return the modified image. Now
in the main() method, you can load whatever image you want (either the
provided image or one from a URL) as long as the resolution is not extremely
high since the storage space of the workspace is limited. Pass the loaded
image into the stretchHorizontally() method then click on the Save button in
the workspace in order to run the code and save the image. Finally, enter the
file name in the browser to view your modified image!
Stuck? Get a hint
Shrink the Image Vertically
21.
In order to shrink the image vertically, you will be halfing the height of the
image and selecting every other pixel down each column to place in the
modified image. We’re trying to create an image that looks something like this
(note that this ends up looking fairly similar to the stretched image!):

This logic should be added in the shrinkVertically() method.


22.
Begin by creating a new 2D array of ints which has half the number of rows of
the input image and the same number of columns.
Stuck? Get a hint
23.
Next use nested for loops to iterate through each pixel in the input image
using column-major order. Make the inner loop iterator increment by 2. We
also need to end one pixel early in the vertical direction. Since we divided the
height of the image by two and we could be working with an odd number of
pixels in the vertical direction, we want to make sure that we do not try and
access an out of bounds element.
Stuck? Get a hint
24.
Inside the inner for loop, place the current pixel from the input image at the
row index divided by 2 and the current column index. For
example: manipulatedImg[j/2][i] = imageTwoD[j][i];.
Stuck? Get a hint
25.
Once the for loops are complete, you need to return the modified image. In
the main() method, load an image and pass it into
the shrinkVertically() method. Save the modified image and view it in the
browser.
Invert the Image
26.
Next, you will invert the image. You will edit the invertImage() method in order
to flip the image vertically and horizontally. Your final result should look
something like this:

27.
Begin by creating a new 2D array which is the same size as the input image.
28.
Next, iterate through each pixel in the input image using nested for loops.
29.
Within the inner for loop, you will copy the final row position minus the
current row index and the final column position minus the column index. This
is similar logic to the negativeColor() method, but taking the negative of the
pixel positions instead of the color values. It will look something like
this: invertedImg[i][j] = imageTwoD[(imageTwoD.length-1)-i]
[(imageTwoD[i].length-1)-j];. See the image for an example of what takes
place.
In this image, the pixels are numbered to help show how they change position
when the image is inverted.
30.
Once the for loops are complete, you need to return the modified image. In
the main() method, load an image and pass it into the invertImage() method.
Save the modified image and view it in the browser.
Applying a Color Filter
31.
For this task you will implement the colorFilter() method. This method
modifies every pixel in the image by provided R, G, and B values as input
parameters. You must make sure that each color value does not leave the
range of 0-255.

This is an example of a filter where the filter was -75, 30, -30 (Meaning the
red values were decreased by 75, the green values were increased by 30, and
the blue values were decreased by 30)
32.
Begin by creating a new 2D array which is the same size as the input image.
33.
Loop through each pixel in the input image using nested for loops.
34.
For every pixel in the input image, extract the RGBA color values using the
provided method getRGBAFromPixel().
Stuck? Get a hint
35.
After retrieving the array of RGBA data, store the values of each color plus the
modifier value (which can be positive or negative).
Stuck? Get a hint
36.
For each of the new color values, test that it does not go outside of the range
0 to 255. If it is less than 0, set it equal to 0. If it is greater than 255, set it equal
to 255.
Stuck? Get a hint
37.
Set the values in the RGBA array to equal the new color values which you
calculated.
Stuck? Get a hint
38.
Convert the RGBA array to a single int containing the hexadecimal pixel data
using the provided method getColorIntValFromRGBA() and store it in the new
image.
Stuck? Get a hint
39.
Once the for loops are complete, you need to return the modified image. In
the main() method, load an image and pass it into the colorFilter() method
along with modifier values for red, green, and blue. Save the modified image
and view it in the browser.
Further Challenges: Painting an Image of Random
Colors
40.
Good Job! You have finished the image processing application! You have seen
how images can be converted to 2D arrays of pixels in order to modify them.
You got to write methods that manipulate images. Feel free to keep adding to,
and experimenting with, your image processing application!

In the next sections, we dive into how to use the Random class to paint random
shapes on your images. Consider these sections to be further challenges — if
you’re looking for more practice with 2D arrays, these may prove to be
interesting challenges, but if you’re feeling worn out, this is a good time to
take a break or move on to the next lesson!

The next method you will be implementing is the paintRandomImage() method.


It will modify the image passed in by replacing every pixel with a randomly
colored pixel.
41.
Begin by creating a new object of the Random class. This class will be used to
generate random numbers for us: Random rand = new Random();.
42.
Next, iterate through each pixel in the provided image using nested for loops.
43.
Within the inner for loop, we need to generate a randomly colored pixel. In
order to do this, we can use rand.nextInt(256). This will generate a random
integer between 0 and 255. Store three of these random ints by
calling rand.nextInt(256) three times.
Stuck? Get a hint
44.
The three randomly generated values will need to be the first, second, and
third elements in a new int array. The fourth element should be 255 since that
represents the alpha value (which controls transparency).
Stuck? Get a hint
45.
After storing those values in an int array, pass it into the
provided getColorIntValFromRGBA() method and store it into the input image.
Note that this is accessing the input image instead of a newly created image
like in the image manipulation methods.
Stuck? Get a hint
46.
Once the for loops are complete, return the modified input image.
47.
In the main() method, create a new 2D array of ints which will be our blank
canvas for the painting methods. 500x500 is a good size for it. Pass the new
2D array into the paintRandomImage() method. Save the image and view it in the
browser.
Stuck? Get a hint
Drawing a Rectangle on an Image
48.
You will be implementing a method that draws a rectangle on an image using
a provided width, height, rowPosition, columnPosition, and color. The image
below shows what each of the input parameter does when creating the
rectangle.
It’s useful to think of these rectangles being drawn from the top left corner.
49.
Begin by iterating through every pixel in the input image using
nested for loops.
50.
For every pixel, check if the current row index is greater than or equal to the
provided rowPosition and also that the index is less than or equal to
the rowPosition plus the width: i>=rowPosition && i<=rowPosition + width.
51.
Additionally, check if the current column index is greater than or equal to the
provided colPosition and also that the index is less than or equal to
the colPosition plus the height: j>=colPosition && j<=colPosition + height.
52.
If both of the previous tests are true, then paint the pixel the provided color
since the pixel position lies within the rectangle shape.
Stuck? Get a hint
53.
Once the iterations are complete, return the modified input image.
54.
In the main() method, pass an image into the paintRectangle() method and
save the image. Enter in the desired values for your rectangle. You can create a
color using an array such as: int[] rgba = {255, 255, 0, 255}; and passing it
into the getColorIntValFromRGBA() method. Save the image and view it in the
browser.
Stuck? Get a hint
Create Abstract Geometric Art Utilizing the
paintRectangle Method
55.
Finally, you will implement the generateRectangles() method. This will use
the paintRectangles() method you created in order to paint a piece of art. It
will generate randomly positioned, sized, and colored rectangles based on the
provided number. The input parameter, numRectangles will determine how
many randomly generated rectangles will be placed in the image.
56.
Firstly, create an object of the Random class to use.
Stuck? Get a hint
57.
Next, iterate for the number of rectangles provided using a for loop.
Stuck? Get a hint
58.
Generate and store two random integers for the width and height of the
rectangle. For width, pass in the number of columns in the 2D array to
the rand.nextInt(num) method. For height, pass in the number of rows into
the rand.nextInt(num) method.
Stuck? Get a hint
59.
Generate and store two random integers for the row position and column
position. For row position, pass in the number of rows in the image minus the
randomly generated height from the previous step. This will ensure that the
rectangle does not get created outside of the image. For the column position
generate a random integer using the number of columns in the image minus
the randomly generated width from the last step. The following image shows
why we perform this calculation.
In this image, the starting position of the rectangle can only be inside the
shaded box. If we were to try to put the top left corner outside the shaded
box, part of the rectangle would be drawn outside of the image, and we would
get an error.
Stuck? Get a hint
60.
Next, create a random color to paint the rectangle. You can do this in a similar
way to the method used in paintRandomImage() make sure the three random
color values are between 0 and 255. Store them in an array with 255 for the A
value and convert it to the int value using getColorIntValFromRGBA.
Stuck? Get a hint
61.
Finally, call the paintRectangle() method using all of the values and the input
image and overwrite the input image.
Stuck? Get a hint
62.
After the iterations are complete, return the modified input image.
63.
In the main() method, pass an image into the generateRectangles() method and
a number of rectangles to generate, 1000 rectangles is a good number to use.
Save the image and view the image in the browser.
Conclusion
64.
Wow, you made it through the bonus work. Pat yourself on the back, this was
quite a difficult project! Reflect on all the different ways you used loops and
2D arrays to create these images.
Hint
Some additional challenges you can do are: adding more parameters to the
image manipulation methods (such as a factor to stretch or shrink by),
painting with different shapes (triangles, circles), and more complex image
filters (saturation).
My Home
Course Menu
Workspace restored.
Get Unstuck
Tools

2D Arrays: Java: Declaration, Initialization, and Assignment

Narrative and Instructions

Learn
2D ARRAYS: JAVA
Declaration, Initialization, and Assignment
When declaring 2D arrays, the format is similar to normal, one-dimensional arrays, except that
you include an extra set of brackets after the data type. In this example, int represents the data
type, the first set of brackets [] represent an array, and the second set of brackets [] represent
that we are declaring an array of arrays.

int[][] intTwoDArray;
You can think of this as creating an array ([]) of int arrays (int[]). So we end up with int[][].

Now that we’ve declared a 2D array, let’s look at how to initialize it with starting values. When
initializing arrays, we define their size. Initializing a 2D array is different because, instead of
only including the number of elements in the array, you also indicate how many elements are
going to be in the sub-arrays. This can also be thought of as the number of rows and columns in
the 2D matrix.

int[][] intArray1;
intArray1 = new int[row][column];
Here is an example of initializing an empty 2D array with 3 rows and 5 columns.

int[][] intArray2;
intArray2 = new int[3][5];
This results in a matrix which looks like this:
If you already know what values are going to be in the 2D array, you can initialize it and write
all of the values into it at once. We can accomplish this through initializer lists

 In Java, initializer lists are a way of initializing arrays and assigning values to them at the
same time
 We can use this for 2D arrays as well by creating an initializer list of initializer lists

An example of an initializer list for a regular array would be:

char[] charArray = {'a', 'b', 'c', 'd'};


Similar to how a regular initializer list defines the size and values of the array, nested initializer
lists will define the number of rows, columns, and the values for a 2D array.

There are three situations in which we can use initializer lists for 2D arrays:

1. In the case where the variable has not yet been declared, we can provide an abbreviated
form since Java will infer the data type of the values in the initializer lists:

double[][] doubleValues = {{1.5, 2.6, 3.7}, {7.5, 6.4, 5.3},


{9.8,  8.7, 7.6}, {3.6, 5.7, 7.8}};

2. If the variable has already been declared, you can initialize it by creating a new 2D array
object with the initializer list values:

String[][] stringValues;
stringValues = new String[][] {{"working", "with"}, {"2D",
"arrays"}, {"is", "fun"}};

3. The previous method also applies to assigning a new 2D array to an existing 2D array
stored in a variable.

In the next exercise, we’ll look at how to assign values of individual elements.

Instructions

1.
Declare a 2D array of float values called floatTwoD.
Checkpoint 2 Passed

Stuck? Get a hint


2.
Initialize the 2D array from the last step to an empty 2D array consisting of 4 arrays with 10
elements each. Do this on a new line under the declaration.
Checkpoint 3 Passed

Stuck? Get a hint


3.
On a single line, declare and initialize an empty 2D array of ints consisting of 15 rows and 8
columns called dataChart.
Checkpoint 4 Passed

Stuck? Get a hint


4.
Create a 2D char array called ticTacToe representing this tic-tac-toe board. Use the
characters 'X', 'O', and ' '.
(Note that you should use a capitalized O, not the number 0.)
Checkpoint 5 Passed

Stuck? Get a hint


5.
When no one is looking, you want to modify the game so 'O' wins. Replace the game board so
that all X’s are O’s and all O’s are X’s. Do this in one line with initializer lists. Do not
declare ticTacToe again.

public class Exercise2 {

public static void main(String[] args) {

// Declare a 2d array of float values called floatTwoD

float[][] floatTwoD;

// Initialize the 2d array from the last step to an empty 2d array consisting of 4 arrays
with 10 elements each

floatTwoD = new float[4][10];

// Declare and initialize an empty 2d array of integers consisting of 15 rows and 8


columns called dataChart

int[][] dataChart = new int[15][8];

// Create a 2D char array called ticTacToe representing the provided tic-tac-toe board
using initializer lists. Use the characters 'X', 'O', and ' '.

char[][] ticTacToe = {{'X', 'O', 'O'}, {'O', 'X', ' '}, {'X', ' ', 'X'}};

// When no one is looking, you want to modify the game to where you, 'O', wins the
game. Replace the game board so that all X’s are O’s and all O’s are X’s. Do this in one line with
initializer lists.

ticTacToe = new char[][] {{'O', 'X', 'X'}, {'X', 'O', ' '}, {'O', ' ', 'O'}};
}

}
My Home
Course Menu
Workspace restored.
Get Unstuck
Tools

2D Arrays: Java: Accessing Elements in a 2D Array

Narrative and Instructions

Learn
2D ARRAYS: JAVA
Accessing Elements in a 2D Array
Let’s first review how to access elements in regular arrays.

For a normal array, all we need to provide is an index (starting at 0) which represents the position
of the element we want to access. Let’s look at an example!

Given an array of five Strings:

String[] words = {"cat", "dog", "apple", "bear", "eagle"};


We can access the first element using index 0, the last element using the length of the array
minus one (in this case, 4), and any of the elements in between. We provide the index of the
element we want to access inside a set of brackets. Let’s see those examples in code:

// Store the first element from the String array


String firstWord = words[0];

// Store the last element of the String array


String lastWord = words[words.length-1];

// Store an element from a different position in the array


String middleWord = words[2];
Now for 2D arrays, the syntax is slightly different. This is because instead of only providing a
single index, we provide two indices. Take a look at this example:

// Given a 2D array of integer data


int[][] data = {{2,4,6}, {8,10,12}, {14,16,18}};

// Access and store a desired element


int stored = data[0][2];
There are two ways of thinking when accessing a specific element in a 2D array.

 The first way of thinking is that the first value represents a row and the second value
represents a column in the matrix
 The second way of thinking is that the first value represents which subarray to access
from the main array and the second value represents which element of the subarray is
accessed

The above example of the 2D array called data can be visualized like so. The indices are labeled
outside of the matrix:
Using this knowledge, we now know that the result of int stored = data[0][2]; would store the
integer 6. This is because the value 6 is located on the first row (index 0) and the third column
(index 2). Here is a template which can be used for accessing elements in 2D arrays:

datatype variableName = existing2DArray[row][column];


Here is another way to visualize the indexing system for our example integer array seen above.
We can see what row and column values are used to access the element at each position.
When accessing these elements, if either the row or column value is out of bounds, then
an ArrayIndexOutOfBoundsException will be thrown by the application.

Instructions

1.
Access the integer at the first row and fourth column of intMatrix and store it in a variable
called retrievedInt.

If you’d like to check your work, print retrievedInt after creating it.


Checkpoint 2 Passed

Stuck? Get a hint


2.
Print the center value of intMatrix multiplied by 3 to the console. Make sure to access the correct
element!
Checkpoint 3 Passed

Stuck? Get a hint

public class Exercise3 {

public static void main(String[] args) {

// Using the provided 2D array

int[][] intMatrix = {

{1, 1, 1, 1, 1},

{2, 4, 6, 8, 0},

{9, 8, 7, 6, 5}

};

// Access the integer at the first row and fourth column of intMatrix and store it in a
variable called retrievedInt

int retrievedInt = intMatrix [0][3];

// Print 3 times the center value of intMatrix to the console. Make sure to access the
correct element!

System.out.println(intMatrix[1][2] * 3);
}

}
My Home
Course Menu
Workspace restored.
Get Unstuck
Tools

2D Arrays: Java: Modifying Elements in a 2D Array

Narrative and Instructions

Learn
2D ARRAYS: JAVA
Modifying Elements in a 2D Array
Now let’s review how to modify elements in a normal array.

For a one dimensional array, you provide the index of the element which you want to modify
within a set of brackets next to the variable name and set it equal to an acceptable value:

storedArray[5] = 10;
For 2D arrays, the format is similar, but we will provide the outer array index in the first set of
brackets and the subarray index in the second set of brackets. We can also think of it as
providing the row in the first set of brackets and the column index in the second set of brackets if
we were to visualize the 2D array as a rectangular matrix:

twoDArray[1][3] = 150;
To assign a new value to a certain element, make sure that the new value you are using is either
of the same type or is castable to the type already in the 2D array.

Let’s say we wanted to replace four values from a new 2D array called intTwoD. Look at this
example code to see how to pick individual elements and assign new values to them.

int[][] intTwoD = new int[4][3];

intTwoD[3][2] = 16;
intTwoD[0][0] = 4;
intTwoD[2][1] = 12;
intTwoD[1][1] = 8;
Here is a before and after image showing when the 2D array was first initialized compared to
when the four elements were accessed and modified.
Instructions

1.
Replace the number 4 in intMatrix with the number 0.

Again, feel free to print the matrix to confirm you changed the correct number. To print a 2D
array, use

System.out.println(Arrays.deepToString(intMatrix));
Checkpoint 2 Passed

Stuck? Get a hint


2.
Declare and initialize a new empty 2x2 int 2D array called subMatrix.
Checkpoint 3 Passed

Stuck? Get a hint


3.
Using 4 lines of code, multiply each of the elements in the 2x2 top left corner of intMatrix by 5
and store the results in the subMatrix you created. Notice how we have to write a similar line of
code 4 times. Afterwards, uncomment the provided print statement to see the result. In the next
exercise, we’ll start looking into how to use loops to make this process quicker.
Checkpoint 4 Passed

Stuck? Get a hint

import java.util.Arrays;

public class Modifying {

public static void main(String[] args) {

// Using the provided 2D array

int[][] intMatrix = {

{1, 1, 1, 1, 1},

{2, 4, 6, 8, 0},

{9, 8, 7, 6, 5}

};

// Replace the number 4 in the 2D array with the number 0

intMatrix[1][1] = 0;

// Declare and initialize a new empty 2x2 integer 2D array called subMatrix
int[][] subMatrix = new int[2][2];

// Using 4 lines of code, multiply each of the elements in the 2x2 top left corner of
intMatrix by 5 and store the results in the subMatrix you created. Afterwards, uncomment the
provided print statement below.

subMatrix[0][0] = intMatrix[0][0] * 5;

subMatrix[0][1] = intMatrix[0][1] * 5;

subMatrix[1][0] = intMatrix[1][0] * 5;

subMatrix[1][1] = intMatrix[1][1] * 5;

System.out.println(Arrays.deepToString(subMatrix));

}
My Home
Course Menu
Workspace restored.
Get Unstuck
Tools

2D Arrays: Java: Review of Nested Loops

Narrative and Instructions

Learn
2D ARRAYS: JAVA
Review of Nested Loops
We’re about to look at how we can use loops to make our lives easier when working with 2D
arrays. But before we do that, let’s take a moment to refresh ourselves on how nested loops
work.

Nested loops consist of two or more loops placed within each other. We will be looking at one
loop nested within another for 2D traversal.

The way it works is that, for every iteration of the outer loop, the inner loop finishes all of its
iterations.

Here is an example using for loops:

for(int outer = 0; outer < 3; outer++){


    System.out.println("The outer index is: " + outer);
    for(int inner = 0; inner < 4; inner++){
        System.out.println("\tThe inner index is: " + inner);
    }
}
The output of the above nested loops looks like so:

The outer index is: 0


    The inner index is: 0
    The inner index is: 1
    The inner index is: 2
    The inner index is: 3
The outer index is: 1
    The inner index is: 0
    The inner index is: 1
    The inner index is: 2
    The inner index is: 3
The outer index is: 2
    The inner index is: 0
    The inner index is: 1
    The inner index is: 2
    The inner index is: 3
From this example we can see how every time the outer loop iterates one time, the inner loop
iterates fully.

This is an important concept for 2D array traversal, because for every row in a two dimensional
matrix, we want to iterate through every column. We will look more at this in the next exercise.

Nested loops can consist of any type of loop and with any combination of loops. Let’s take a
look at a few more interesting examples.

Here is an example of nested while loops:

int outerCounter = 0;


int innerCounter = 0;
while(outerCounter<5){
    outerCounter++;
    innerCounter = 0;
    while(innerCounter<7){
        innerCounter++;
    }
}
We can even have some interesting combinations. Here is an enhanced for loop inside of a while
loop:

int outerCounter = 0;


int[] innerArray = {1,2,3,4,5};

while(outerCounter<7){
    System.out.println();
    for(int number : innerArray){
        System.out.print(number * outerCounter + " ");
    }
    outerCounter++;
}
The output of the above example creates a multiplication table:

0 0 0 0 0
1 2 3 4 5
2 4 6 8 10
3 6 9 12 15
4 8 12 16 20
5 10 15 20 25
6 12 18 24 30
This is an interesting example, because for every iteration of the while loop, we iterate through
every element of an array using an enhanced for loop. This is similar to the iteration pattern we
use for 2D array traversal. We will be going over that in the next exercise.

Let’s practice using nested loops!

You are in charge of controlling the amount of people who reserve seats for the world famous
programming contest. You have two long arrays of integers which represent the contestant’s IDs
for two days of the competition. The index of the array represents their seat number. You need to
use nested for loops to find if a contestant tried to register for both days. Print out the ID of the
contestants who tried to register twice as well as their seat numbers for both days.

Instructions

1.
Fix the outer loop header to iterate through the first array of seats.
Checkpoint 2 Passed

Hint
For array traversal, remember to use the format: for(int iterator = 0; iterator <
array.length; iterator++) .

Be careful to fix the iterator! If you leave it as -- it’s pretty easy to create a loop that will never
end and you’ll need to refresh the page after running your code.
2.
Fix the inner loop header to iterate through the second array of seats.
Checkpoint 3 Passed

Hint
For array traversal, remember to use the format: for(int iterator = 0; iterator <
array.length; iterator++) .
3.
Replace 1==2 with conditional logic to check if an element in the first array matches an element
in the second array.
Checkpoint 4 Passed

Hint
Use array[index] == array2[otherIn

Nested.java

public class NestedLoops {

public static void main(String[] args) {

int[] seatsDayOne = {850007, 841141, 150017, 622393, 178505, 952093, 492450,


790218, 515994, 926666, 476090, 709827, 908660, 718422, 641067, 624652, 429205, 394328, 802772,
468793, 901979, 504963, 733939, 706557, 724430, 663772, 577480, 886333, 323197, 283056, 378922,
628641, 494605, 606387, 179993, 755472, 253608, 975198, 328457, 885712, 411958, 418586, 254970,
299345, 632115, 915208, 661570, 328375, 538422, 321303};

int[] seatsDayTwo = {740912, 209431, 310346, 316462, 915797, 850440, 803140,


459194, 293277, 302424, 790507, 711980, 639916, 707446, 940339, 613076, 524157, 189604, 595934,
509691, 234133, 787575, 674602, 944308, 710345, 889699, 622393, 151931, 964325, 944568, 357684,
933857, 541190, 935076, 468848, 449446, 278951, 885503, 539124, 278723, 998622, 846182, 394328,
914002, 803795, 851135, 828760, 504936, 504322, 648644};

int matchCounter = 0;

// Fix the outer loop header to iterate through the first array of seats

for(int i = 0; i < seatsDayOne.length; i++) {

// Fix the inner loop header to iterate through the second array of seats

for(int j = 0; j < seatsDayTwo.length; j++) {

// Replace 1==2 with conditional logic to check if an element in the


first array matches an element in the second array

if(seatsDayOne[i] == seatsDayTwo[j]) {

matchCounter++;

System.out.println("Contestant: " + seatsDayOne[i] + ", Seat


Day One: " + i + ", Seat Day Two: " + j);

break;

System.out.println("The total number of contestants reserving seats on both days


was: " + matchCounter);

}
}

public class Introduction {

public static void main(String[] args) {

//Given the provided 2d array

int[][] intMatrix = {

{ 4, 6, 8, 10, 12, 14, 16},

{18, 20, 22, 24, 26, 28, 30},

{32, 34, 36, 38, 40, 42, 44},

{46, 48, 50, 52, 54, 56, 58},

{60, 62, 64, 66, 68, 70, 79}

};

// Store the number of subarrays of intMatrix into a variable called 'numSubArrays'

int numSubArrays = intMatrix.length;

// Store the length of the subarrays using the first subarray in intMatrix. Store it in a
variable called subArrayLength.

int subArrayLength = intMatrix[0].length;

// Store the number of columns in intMatrix into a variable called 'columns'

int columns = subArrayLength;

// Store the number of rows in intMatrix into a variable called 'rows'

int rows = numSubArrays;

// Replace the outer and inner for loop headers to iterate through the entire 2D array.
Use the iterators `i` for the outer loop and `j` for the inner loop.
int sum = 0;

for(int i=0; i<intMatrix.length; i++) {

for(int j = 0; j < intMatrix[i].length; j++) {

// Insert a line of code to increase the variable `sum` by each accessed


element

sum+=intMatrix[i][j];

System.out.println(sum);

}
My Home
Course Menu
Workspace restored.
Get Unstuck
Tools

2D Arrays: Java: Traversing 2D Arrays: Practice with Loops

Narrative and Instructions

Learn
2D ARRAYS: JAVA
Traversing 2D Arrays: Practice with Loops
We have seen how to traverse 2D arrays using standard for loops, but in this exercise, we will
practice traversing them using some other loop types. For example, you may want to only
retrieve elements without keeping track of the indices using enhanced for loops, or you could
continuously update the 2D array until a condition is met using while loops.

In enhanced for loops, each element is iterated through until the end of the array. When we think
about the structure of 2D arrays in Java (arrays of array objects) then we know that the outer
enhanced for loop elements are going to be arrays.

Let’s take a look at an example:

Given this 2D array of character data:

char[][] charData = {{'a', 'b', 'c', 'd', 'e', 'f'},{'g', 'h', 'i',
'j', 'k', 'l'}};
Print out every character using enhanced for loops:

for(char[] charRow : charData) {


    for(char c : charRow) {
        System.out.print(c + " ");
    }
    System.out.println();
}
Remember that the syntax for enhanced for loops looks like so: for( datatype elementName :
arrayName){. Since 2D arrays in Java are arrays of arrays, each element in the outer
enhanced for loop is an entire row of the 2D array. The nested enhanced for loop is then used to
iterate through each element in the extracted row. Here is the output of the above code:
a b c d e f 
g h i j k l
Here is an example which accomplishes the same thing, but using while loops:

int i = 0, j=0;


while(i<charData.length) {
    j = 0;
    while(j<charData[i].length) {
        System.out.print(charData[i][j] + " ");
        j++;
    }
    System.out.println();
    i++;
}
Here is the output of the above code:

a b c d e f 
g h i j k l
Notice how we can use different loop types for traversal, but still receive the same result.

Let’s work some example problems using different loop types!

Instructions

1.
Use nested enhanced for loops to calculate the total number of characters in the wordData 2D
array and print the result to the console. (Get the string .length() of each element)
Checkpoint 2 Passed

Hint
Make sure to look at each array in the outer nested for loop for(String[] wordRow :
wordData) and then each string within the subarray in the inner loop for(String word : wordRow).
2.
Using nested while loops, iterate through all of the elements in the 2D array and print them to the
console using the format: word [row][column]. The print statement has been provided (you will
need to modify it if you use iterators other than i and j).
Checkpoint 3 Passed

Hint
Remember to check the iterators in the while loop headers and to manually increment the
iterators at the end of each loop. The inner while loop’s iterator should be set to 0 again before
entering the inner while loop. The provided print statement should be placed in the
inner while loop. The print statement also assumes that you are using the iterators i and j.

public class LoopPractice {

public static void main(String[] args) {


String[][] wordData = {{"study", "consider", "examine", "learn"}, {"ponder", "read",
"think", "cogigate"}};

//Use nested enhanced for loops to calculate the total number of characters in the
wordData 2D array and print the result to the console. (Get the string .length() of each element)

int characterCount = 0;

for(String[] stringRow : wordData) {

for(String s : stringRow) {

characterCount += s.length();

System.out.println(characterCount);

//Using nested while loops, iterate through all of the elements in the 2D array and
print them to the console using the format: word [row][column]. The print statement has been
provided.

int i = 0, j = 0;

while(i<wordData.length) {

j=0;

while(j<wordData[i].length) {

System.out.println(wordData[i][j] + ": [" + i + "]" + "[" + j + "]");

j++;

i++;

}
}
My Home
Course Menu
Workspace restored.
Get Unstuck
Tools

2D Arrays: Java: Traversing 2D Arrays: Row-Major Order

Narrative and Instructions

Learn
2D ARRAYS: JAVA
Traversing 2D Arrays: Row-Major Order
Row-major order for 2D arrays refers to a traversal path which moves horizontally through each
row starting at the first row and ending with the last.

Although we have already looked at how 2D array objects are stored in Java, this ordering
system conceptualizes the 2D array into a rectangular matrix and starts the traversal at the top
left element and ends at the bottom right element.

Here is a diagram which shows the path through the 2D array:


This path is created by the way we set up our nested loops. In the previous exercise, we looked at
how we can traverse the 2D array by having nested loops in a variety of formats, but if we want
to control the indices, we typically use standard for loops.

Let’s take a closer look at the structure of the nested for loops when traversing a 2D array:

Given this 2D array of strings describing the element positions:

String[][] matrix = {{"[0][0]", "[0][1]", "[0][2]"},


                     {"[1][0]", "[1][1]", "[1][2]"},
                     {"[2][0]", "[2][1]", "[2][2]"},
                     {"[3][0]", "[3][1]", "[3][2]"}};
Lets keep track of the total number of iterations as we traverse the 2D array:

int stepCount = 0;

for(int a = 0; a < matrix.length; a++) {


    for(int b = 0; b < matrix[a].length; b++) {
        System.out.print("Step: " + stepCount);
        System.out.print(", Element: " + matrix[a][b]);
        System.out.println();
        stepCount++;
    }
}
Here is the output of the above code:

Step: 0, Element: [0][0]


Step: 1, Element: [0][1]
Step: 2, Element: [0][2]
Step: 3, Element: [1][0]
Step: 4, Element: [1][1]
Step: 5, Element: [1][2]
Step: 6, Element: [2][0]
Step: 7, Element: [2][1]
Step: 8, Element: [2][2]
Step: 9, Element: [3][0]
Step: 10, Element: [3][1]
Step: 11, Element: [3][2]

The step value increases with every iteration within the inner for loop. Because of this, we can
see the order in which each element is accessed. If we follow the step value in the output shows
us that the elements are accessed in the same order as the row-major diagram above. Now why is
that?

This is because in our for loop, we are using the number of rows as the termination condition
within the outer for loop header a < matrix.length; Additionally, we are using the number of
columns b < matrix[a].length as the termination condition for our inner loop. Logically we are
saying: “For every row in our matrix, iterate through every single column before moving to the
next row”. This is why our above example is traversing the 2D array using row-major order.

Here is a diagram showing which loop accesses which part of the 2D array for row-major order:
Why Use Row-Major Order?

Row-major order is important when we need to process data in our 2D array by row. You can be
provided data in a variety of formats and you may need to perform calculations of rows of data at
a time instead of individual elements. Let’s take one of our previous checkpoint exercises as an
example. You were asked to calculate the sum of the entire 2D array of integers by traversing
and accessing each element. Now, if we wanted to calculate the sum of each row, or take the
average of each row, we can use row-major order to access the data in the order that we need.
Let’s look at an example!

Given a 6X3 2D array of doubles:

double[][] data = {{0.51,0.99,0.12},


                   {0.28,0.99,0.89},
                   {0.05,0.94,0.05},
                   {0.32,0.22,0.61},
                   {1.00,0.95,0.09},
                   {0.67,0.22,0.17}};
Calculate the sum of each row using row-major order:

double rowSum = 0.0;


for(int o = 0; o < data.length; o++) {
    rowSum = 0.0;
    for(int i = 0; i < data[o].length; i++) {
        rowSum += data[o][i];
    }
    System.out.println("Row: " + o +", Sum: " + rowSum);
}
The output of the above code is:

Row: 0, Sum: 1.62


Row: 1, Sum: 2.16
Row: 2, Sum: 1.04
Row: 3, Sum: 1.15
Row: 4, Sum: 2.04
Row: 5, Sum: 1.06
An interesting thing to note is that, due to the way 2D arrays are structured in Java,
enhanced for loops are always in row-major order. This is because an enhanced for loop iterates
through the elements of the outer array which causes the terminating condition to be the length of
the 2D array which is the number of rows.

Instructions

1.
You are provided with some runner lap data. Take a look at the loops we’re using to iterate
through this 2D array. Replace the incorrect for loop headers to perform row-major traversal.
Use the iterators outer and inner for the outer and inner loops.
Checkpoint 2 Passed

Hint
Row-major order uses the length of the 2D array as the terminating condition for the outer loop
and the length of a subarray as the termination condition of the inner loop.
2.
Enter the missing line of code within the nested for loop to sum up the values for each row in the
runner data.

We’ve already created a variable named runnerTime that you can use to sum these values.
Checkpoint 3 Passed

Hint
Use the 2D array accessor: twoDArray[row][column]. Add that value to runnerTime using +=.
3.
We’ve given you a variable named averageVal that currently stores 0. Edit that line of code to
find the average time of each runner.
Checkpoint 4 Passed

Hint
Divide the result by the length of the subarray.

public class RowMajor {

public static void main(String[] args) {

// Given runner lap data

double[][] times = {{64.791, 75.972, 68.950, 79.039, 73.006, 74.157}, {67.768, 69.334,
70.450, 67.667, 75.686, 76.298}, {72.653, 77.649, 74.245, 62.121, 63.379, 79.354}};

// Replace the incorrect for loop headers, use the iterators 'outer' and 'inner' for the
outer and inner loops

double runnerTime = 0.0;

for(int outer = 0; outer < times.length; outer++) {

runnerTime = 0.0;

for(int inner = 0; inner < times[outer].length; inner++) {

System.out.println("Runner index: " + outer + ", Time index: " + inner);

// Enter the missing line of code to sum up the values in each row. Use
the variable runnerTime

runnerTime+=times[outer][inner];
}

// Enter the missing line of code to find the average time of each runner. Use
the variable averageVal

double averageVal = 0;

averageVal = runnerTime / times[outer].length;

System.out.println("Sum of runner " + outer + " times: " + runnerTime);

System.out.println("Average of runner " + outer + ": " + averageVal);

}
My Home
Course Menu
Connected to Codecademy
Get Unstuck
Tools

2D Arrays: Java: Traversing 2D Arrays: Column-Major Order

Narrative and Instructions

Learn
2D ARRAYS: JAVA
Traversing 2D Arrays: Column-Major Order
Column-major order for 2D arrays refers to a traversal path which moves vertically down each
column starting at the first column and ending with the last.

This ordering system also conceptualizes the 2D array into a rectangular matrix and starts the
traversal at the top left element and ends at the bottom right element. Column-major order has
the same starting and finishing point as row-major order, but it’s traversal is completely different

Here is a diagram which shows the path through the 2D array:


In order to perform column-major traversal, we need to set up our nested loops in a different
way. We need to change the outer loop from depending on the number of rows, to depending on
the number of columns. Likewise we need the inner loop to depend on the number of rows in its
termination condition.

Let’s look at our example 2D array from the last exercise and see what needs to be changed.

Given this 2D array of strings describing the element positions:

String[][] matrix = {{"[0][0]", "[0][1]", "[0][2]"},


                     {"[1][0]", "[1][1]", "[1][2]"},
                     {"[2][0]", "[2][1]", "[2][2]"},
                     {"[3][0]", "[3][1]", "[3][2]"}};
Let’s keep track of the total number of iterations as we traverse the 2D array. We also need to
change the termination condition (middle section) within the outer and inner for loop.

int stepCount = 0;

for(int a = 0; a < matrix[0].length; a++) {


    for(int b = 0; b < matrix.length; b++) {
        System.out.print("Step: " + stepCount);
        System.out.print(", Element: " + matrix[b][a]);
        System.out.println();
        stepCount++;
    }
}    
Here is the output of the above code:

Step: 0, Element: [0][0]


Step: 1, Element: [1][0]
Step: 2, Element: [2][0]
Step: 3, Element: [3][0]
Step: 4, Element: [0][1]
Step: 5, Element: [1][1]
Step: 6, Element: [2][1]
Step: 7, Element: [3][1]
Step: 8, Element: [0][2]
Step: 9, Element: [1][2]
Step: 10, Element: [2][2]
Step: 11, Element: [3][2]
As you can see in the code above, the way we accessed the elements from our 2D array of strings
called matrix is different from the way we accessed them when using row-major order. Let’s
remember that the way we get the number of columns is by using matrix[0].length and the way
we get the number of rows is by using matrix.length. Because of these changes to our for loops,
our iterator a now iterates through every column while our iterator b iterates through every row.
Since our iterators now represent the opposite values, whenever we access an element from our
2D array, we need to keep in mind what indices we are passing to our accessor. Remember the
format we use for accessing the elements matrix[row][column]? Since a now iterates through our
column indices, we place it in the right set of brackets, and the b is now placed in the left set of
brackets.

Here is a diagram showing which loop accesses which part of the 2D array for column-major
order:
Why Use Column-Major Order?

Column major order is important because there are a lot of cases when you need to process data
vertically. Let’s say that we have a chart of information which includes temperature data about
each day. The top of each column is labeled with a day, and each row represents an hour. In
order to find the average temperature per day, we would need to traverse the data vertically since
each column represents a day. As mentioned in the last exercise, data can be provided in many
different formats and shapes and you will need to know how to traverse it accordingly.

Let’s look at our sum example from the last exercise, but now using column-major order.

Given a 6X3 2D array of doubles:

double[][] data = {{0.51,0.99,0.12},


                   {0.28,0.99,0.89},
                   {0.05,0.94,0.05},
                   {0.32,0.22,0.61},
                   {1.00,0.95,0.09},
                   {0.67,0.22,0.17}};
Calculate the sum of each column using column-major order:

double colSum = 0.0;


for(int o = 0; o < data[0].length; o++) {
    colSum = 0.0;
    for(int i = 0; i < data.length; i++) {
        colSum += data[i][o];
    }
    System.out.println("Column: " + o +", Sum: " + colSum);
}
The output of the above code is:

Column: 0, Sum: 2.83


Column: 1, Sum: 4.31
Column: 2, Sum: 1.93
Let’s try an example!

We will be using the same runner data from the last exercise, but this time we are going to take
the average times per lap rather than per runner. This requires that we use column-major
traversal.

Instructions

1.
You are provided with some runner lap data. Take a look at the loops we’re using to iterate
through this 2D array. Replace the incorrect for loop headers to perform column-major traversal.
Use the iterators outer and inner for the outer and inner loops.
Hint
Remember that we flip the outer and inner loop terminating conditions for column-major order
as well as the indices in the accessors.
2.
Enter the missing line of code within the nested for loop to sum up the values for each column in
the runner data.

We’ve already created a variable named lapTime that you can use to sum these values.
Hint
Use the 2D array accessor: twoDArray[row][column]. Add that value to lapTime using +=.
Remember that the iterators in column-major order need to be flipped since the direction we are
traversing has flipped — the inner for loop variable controls the rows and the outer for loop
variable controls the columns.
3.
We’ve given you a variable named averageVal that currently stores 0. Edit that line of code to
find the average time of each lap.
Hint
Remember to flip the order of the iterators, since we have flipped the direction we are traversing.
Columnmajor.java

public class ColumnMajor {

public static void main(String[] args) {

// Given runner lap data

double[][] times = {{64.791, 75.972, 68.950, 79.039, 73.006, 74.157}, {67.768, 69.334,
70.450, 67.667, 75.686, 76.298}, {72.653, 77.649, 74.245, 62.121, 63.379, 79.354}};

// Replace the incorrect for loop headers, use the iterators 'outer' and 'inner' for the
outer and inner loops

double lapTime = 0.0;

for(int outer = 0; outer < times[0].length; outer++){

lapTime = 0.0;

for(int inner = 0; inner < times.length; inner++){

System.out.println("Lap index: " + outer + ", Time index: " + inner);

// Enter the missing line of code to sum up the values in each row. Use
the variable lapTime

lapTime+=times[inner][outer];
}

// Enter the missing line of code to find the average time of each lap. Use the
variable averageVal

double averageVal = 0;

averageVal = lapTime / times.length;

System.out.println("Sum of lap " + outer + " times: " + lapTime);

System.out.println("Average time for lap " + outer + ": " + averageVal);

}
My Home
Course Menu
Connected to Codecademy
Get Unstuck
Tools

2D Arrays: Java: Combining Traversal and Conditional Logic

Narrative and Instructions

Learn
2D ARRAYS: JAVA
Combining Traversal and Conditional Logic
When working with 2D arrays, it is important to be able to combine traversal logic with
conditional logic in order to effectively navigate and process the data. Here are a few ways in
how conditional logic can affect 2D array traversal:

 Skipping or selecting certain rows and columns


 Modifying elements only if they meet certain conditions
 Complex calculations using the 2D array data
 Formatting the 2D array
 Avoiding exceptions / smart processing

Let’s go over a few examples which use these ideas:

First, let’s think about a situation where you have some string data inside a 2D array. We have an
application which allows users to input events on a calendar. This is represented by a 5x7 2D
array of strings. Due to the fact that the number of days in each month is slightly different and
that there are less than 35 days in a month, we know that some of our elements are going to be
empty. We want our application to do a few things:

 Detect which days of which weeks have something planned and alert us about the event.
 Count the number of events for each week
 Count the number of events for each day

Here is a visualization of what our calendar data looks like after a user has entered in some event
information:
Here’s what our calendar data looks like in our application

String[][] calendar = {{"volunteer", "delivery", null, null, "doctor",


null, "soccer"}, {null, "exam 1", null, "mechanic", null, null,
"soccer"}, {"volunteer", "off work", null, "birthday", null,
"concert", null}, {null, "exam 2", null, null, "doctor", null,
"soccer"}, {"visit family", null, null, null, null, null, null}};
Let’s look at some code which accomplishes the requirements above. Carefully look through
each line of code and read all of the comments.

There are a few things to note:

 Row-major or column-major order can be used to access the individual events


 Row-major order must be used to count the number of events per week since each row
represents a week

Let’s take care of the first 2 requirements in one set of nested row-major loops

for(int i = 0; i < calendar.length; i++) {


    numberOfEventsPerWeek = 0;
    for(int j = 0; j < calendar[i].length; j++) {
        // We need conditional logic to ensure that we do not count
the empty days
        String event = calendar[i][j];
        if(event!=null && !event.equals("")) {
            // If the day does not have a null value or empty string
for an event, then we print it and count it
            System.out.println("Week: " + (i+1) + ", Day: " + (j+1)
+ ", Event: " + event);
            numberOfEventsPerWeek++;
        }
    }
    System.out.println("Total number of events for week "+ (i+1) +": "
+ numberOfEventsPerWeek + "\n");
}
The above code produces this output:

Week: 1, Day: 1, Event: volunteer


Week: 1, Day: 2, Event: delivery
Week: 1, Day: 5, Event: doctor
Week: 1, Day: 7, Event: soccer
Total number of events for week 1: 4

Week: 2, Day: 2, Event: exam 1


Week: 2, Day: 4, Event: mechanic
Week: 2, Day: 7, Event: soccer
Total number of events for week 2: 3

Week: 3, Day: 1, Event: volunteer


Week: 3, Day: 2, Event: off work
Week: 3, Day: 4, Event: birthday
Week: 3, Day: 6, Event: concert
Total number of events for week 3: 4

Week: 4, Day: 2, Event: exam 2


Week: 4, Day: 5, Event: doctor
Week: 4, Day: 7, Event: soccer
Total number of events for week 4: 3

Week: 5, Day: 1, Event: visit family


Total number of events for week 5: 1
Now let’s complete the third requirement. Since we need to count all of the events for each of the
weekdays, we will need to traverse the calendar vertically.

int numberOfEventsPerWeekday = 0;


// We will use this array of day strings for our output later on so we
don't have (day: 1)
String[] days = {"Sundays", "Mondays", "Tuesdays", "Wednesdays",
"Thursdays", "Fridays", "Saturdays"};
for(int i = 0; i < calendar[0].length; i++) {
    numberOfEventsPerWeekday = 0;
    for(int j = 0; j < calendar.length; j++) {
        // Don't forget to flip the iterators in the accessor since we
are flipping the direction we are navigating.
        // Remember, i now controls columns and j now controls rows
        String event = calendar[j][i];
        if(event!=null && !event.equals("")) {
            // Make sure we have an event for the day before counting
it
            numberOfEventsPerWeekday++;
        }
    }
    // Use the days string array from earlier to convert the day index
to a real weekday string
    System.out.println("Number of events on " + days[i] + ": "
+ numberOfEventsPerWeekday);
}
The output is:

Number of events on Sundays: 3


Number of events on Mondays: 4
Number of events on Tuesdays: 0
Number of events on Wednesdays: 2
Number of events on Thursdays: 2
Number of events on Fridays: 1
Number of events on Saturdays: 3
This example uses many of the concepts we have learned before. We use row-major order,
column-major order, as well as including conditional logic to ensure that we have data for the
elements we are accessing.

Additionally, we can use conditional logic to skip portions of the 2D array. For example, let’s
say we wanted to print the events for weekdays only and skip the weekends.

We could use a conditional statement such as if(j!=0 && j!=6) in order to skip Sunday (0) and
Saturday (6).

These modifications to our 2D array traversal are very common when processing data in
applications. We need to know which cells to look at (skipping column titles for example), which
cells to ignore (empty data, invalid data, outliers, etc.), and which cells to convert (converting
string input from a file to numbers).

Let’s try an example!

We are making a simple grayscale image editor program and we want to apply some
modifications to the image. We have a 4x8 pixel image that is stored as a 2D array of integers.
The integer value represents the brightness of the pixel, where the acceptable values are
between 0 and 255, inclusive.

Instructions

1.
First, we want to crop the image down to a 4x6 image, removing the right 2 columns. Declare
and initialize a new 2D array of integers with 4 rows and 6 columns called newImage.
Hint
Remember to create a new 2D array using this format: datatype[][] variableName = new
datatype[rows][columns];.
2.
Now that you have your empty image, use nested for loops to copy over the data from the
original image (stored in imageData) to the new image, make sure not to include the cropped out
columns (right 2 columns).
Hint
To copy over the values, use: new2DArray[row][col] = old2DArray[row][col].
3.
You want to decrease the brightness of the new image by 50 units. The way this works is that for
every integer in the new 2D array, we will subtract the value by 50. Remember that the value
range for the pixel is 0-255, so if the result tries to go below 0, just set it equal to 0.
Hint
Remember to check if the value minus 50 is less than 0 when iterating through the elements of
the new image: if(newImage[row][column]-50<0). If that condition is true, then set the element to
equal 0 else subtract 50 from the element.

import java.util.Arrays;

public class Combining {

public static void main(String[] args) {

int[][] imageData={{100,90,255,80,70,255,60,50},

{255,10,5,255,10,5,255,255},

{255,255,255,0,255,255,255,75},

{255,60,30,0,30,60,255,255}};

//First, we want to crop the image down to a 4x6 image, removing the right 2
columns. Declare and initialize a new 2D array of integers with 4 rows and 6 columns called
`newImage`.

int[][] newImage = new int[4][6];

//Now that you have your empty image, use nested **for** loops to copy over the
data from the original image to the new image, make sure not to include the cropped out columns.

for(int i=0; i<newImage.length; i++){

for(int j=0; j<newImage[i].length; j++){

newImage[i][j] = imageData[i][j];

System.out.println(Arrays.deepToString(newImage));
//You want to decrease the brightness of the new image by 50 units. The way this
works is that for every integer in the new 2D array, we will subtract the value by 50. Remember that
the value range for the pixel is 0-255, so if the result tries to go below 0, just set it equal to 0.

for(int i=0; i<newImage.length; i++){

for(int j=0; j<newImage[i].length; j++){

if(newImage[i][j]-50<0){

newImage[i][j] = 0;

else{

newImage[i][j]-=50;

System.out.println(Arrays.deepToString(newImage));

}
My Home
Course Menu
Workspace restored.
Get Unstuck
Tools

2D Arrays: Java: 2D Array Review

Narrative and Instructions

Learn
2D ARRAYS: JAVA
2D Array Review
Let’s review the concepts we have learned throughout this lesson.

Arrays are objects in Java, we can have arrays of objects, therefore we can also have arrays of
arrays. This is the way 2D arrays are structured in Java.

We can declare and initialize 2D arrays in a few different ways depending on the situation:

// Declaring without initializing


int[][] intTwoD;

// Initializing an empty 2D array which has already been declared


intTwoD = new int[5][5];

// Declaring and initializing an empty 2D array at once


String[][] stringData = new String[3][6];

// Declaring and initializing a 2D array using initializer lists


double[][] doubleValues = {{1.5, 2.6, 3.7}, {7.5, 6.4, 5.3},
{9.8,  8.7, 7.6}, {3.6, 5.7, 7.8}};

// Initializing a 2D array using initializer lists after it has


already been declared, or already contains data;
char[][] letters = new char[100][250];
letters = new char[][]{{'a', 'b', 'c'}, {'d', 'e', 'f'}};
We retrieve elements in a 2D array by providing a row and column index char c = letters[0]
[1];

 We can also think of them as the index of the outer array and the index of the subarray
 We can modify elements the same way letters[1][2] = 'z';

We traverse 2D arrays using nested loops.

 We can use loops of any type, but we typically use nested for loops to keep track of the
indices
 Row-major order traverses through each row moving horizontally to the right through
each row
 Column-major order traverses through each column moving vertically down through each
column
 Row-major order and column-major order start and end on the same elements, but the
paths are different.
 In order to convert row-major to column-major, we need to make the outer loop
terminating condition depend on the number of columns, make the inner loop terminating
condition depend on the number of rows, and flip the variables in our accessor within the
inner loop to ensure that we don’t try to access outside of the 2D array since we flipped
the direction of traversal.

Here are examples of row-major and column-major order:

// Row-major order
for(int o = 0; o < letters.length; o++) {
    for(int i = 0; i < letters[o].length; i++) {
        char c = letters[o][i];
    }
}

// Column-major order
for(int o = 0; o < letters[0].length; o++) {
    for(int i = 0; i < letters.length; i++) {
        char c = letters[i][o];
    }
}
Conditional logic in our 2D array traversal allows us to use the data in a meaningful way. We
can control which rows and columns we look at, ensure that the data we are looking at is what
we want, perform calculations on specific elements, avoid throwing exceptions, and more.

Here is an example of traversal with conditional logic.

Given this 2D array of Strings:

String[][] words = {{"championship", "QUANTITY", "month"},{"EMPLOYEE",


"queen", "understanding"},{"method", "writer", "MOVIE"}};
We are going to flip the capitalization of the words:
System.out.println("Before...");
System.out.println(Arrays.deepToString(words).replace("],", "],\n")
+ "\n");

for(int i=0; i<words.length; i++) {


    for(int j = 0; j<words[i].length; j++) {
        if(words[i][j]!=null) {

            // Check the capitalization


            boolean allCaps = true;
            for(char c : words[i][j].toCharArray())
                if(!Character.isUpperCase(c))
                    allCaps = false;

            // Flip the capitalization


            if(allCaps)
                words[i][j] = words[i][j].toLowerCase();
            else
                words[i][j] = words[i][j].toUpperCase();
        }
    }
}

System.out.println("After...");
System.out.println(Arrays.deepToString(words).replace("],", "],\n")
+ "\n");
Here is the output of the above code:

Before...
[[championship, QUANTITY, month],
[EMPLOYEE, queen, understanding],
[method, writer, MOVIE]]

After...
[[CHAMPIONSHIP, quantity, MONTH],
[employee, QUEEN, UNDERSTANDING],
[METHOD, WRITER, movie]]
Time to work some review problems!

After learning about 2D arrays, you have decided to become a CS professor and you are now
teaching your class about 2D arrays. You are making an application which will keep track of
their exam grades and show you statistics about their performance. You will be using 2D arrays
to keep track of their exam grades

Instructions
1.
First, declare and initialize a 4x3 2D array of doubles called scores which will contain the exam
data for four students. The rows will represent the student and the columns will represent the
exam number. You already know the first exam scores (80.4, 96.2, 100.0, 78.9). Use initializer
lists to store the first exam scores in the first column and -1 for the remaining exams. Use the
provided print statement to print the result in the console.
Checkpoint 2 Passed

Hint
Remember to use nested initializer lists like so: datatype[][] variable = {{val1, val2, val3},
{val4, val5, val6}, {val7, val8, val9}};.
2.
The next set of exams have occurred. Using 4 lines of code, manually enter the scores (89.7,
90.5, 93.6, 88.1) for the second exam (column 1). Use the provided print statement to print the
updated 2D array as well.
Checkpoint 3 Passed

Hint
Remember to access and modify elements using: twoDArray[row][col] = val;.
3.
You have realized that you will only be keeping track of 2 exam grades instead of 3. Declare and
initialize an empty 4x2 2D array of double values called newScores.
Checkpoint 4 Passed

Hint
Declare and initialize an empty 2D array like so: datatype[][] variable = new datatype[row]
[col];.
4.
Using loops, copy all of the scores for exam 1 and 2 into the new 2D array. (Do not include the
-1 values)
Checkpoint 5 Passed

Hint
Remember to copy values over using: twoDArrayOne[i][j] = twoDArrayTwo[i][j]; when in a
nested loop.
5.
You have allowed the students to complete an extra credit activity to contribute towards their
scores. For all exam grades less than 90, add 2 additional points to the grade in newScores.
Checkpoint 6 Passed

Hint
Remember to test the elements to see if they are under 90: if(newScores[row][column]<90). If the
condition is true then increase the element by 2.

Review.java

import java.util.Arrays;

public class Review {

public static void main(String[] args) {

//First, declare and initialize a 4x3 2D array of doubles called `scores` which will contain the exam
data for four students. The rows will represent the student and the columns will represent the exam
number. You already know the first exam scores (80.4, 96.2, 100.0, 78.9). Use initializer lists to store
the first exam scores in the first column and -1 for the remaining exams. Use the provided print
statement to print the result in the console.

double[][] scores = {{80.4, -1, -1}, {96.2, -1, -1}, {100.0, -1, -1}, {78.9, -1, -1}} ;

System.out.println(Arrays.deepToString(scores));

//The next set of exams have occurred. Using 4 lines of code, manually enter the scores (89.7, 90.5,
93.6, 88.1) for the second exam (column 1). Use the provided print statement to print the updated 2D
array as well.

scores[0][1] = 89.7;

scores[1][1] = 90.5;

scores[2][1] = 93.6;

scores[3][1] = 88.1;

System.out.println(Arrays.deepToString(scores));

//You have realized that you will only be keeping track of 2 exam grades instead of 3. Declare and
initialize an empty 4x2 2D array of double values called newScores

double[][] newScores = new double[4][2];

//Using loops, copy all of the scores for exam 1 and 2 into the new 2D array. (do not include the -1
values)

for(int i = 0; i < newScores.length; i++){

for(int j = 0; j < newScores[i].length; j++){

newScores[i][j] = scores[i][j];
}

System.out.println(Arrays.deepToString(newScores));

//You have allowed the students to complete an extra credit activity to contribute towards their
scores. For all exam grades less than 90, add 2 additional points to the grade in `newScores`

for(int i = 0; i < newScores.length; i++){

for(int j = 0; j < newScores[i].length; j++){

if(newScores[i][j]<90){

newScores[i][j]+=2;

System.out.println(Arrays.deepToString(newScores));

}
https://curl.se/

https://www.codecademy.com/paths/create-rest-apis-with-spring-and-java/tracks/spring-apis-web-
and-spring-basics/modules/how-spring-works/articles/what-is-curl-article
https://developer.android.com/studio/intro

You might also like