Scope has to do with the accessibility of the variable in the program. Where can the variable be accessed and used?
public class ScopingDemo implements Runnable {
}
public class ScopingDemo implements Runnable {
public void run() {
int age = 18;
}
}
A variable is created (declared and initialized) inside a method and is therefore only avaiable within the run()
method (more precise: after the declaration itself)
It is possible to define an even smaller
scopes.
public class ScopingDemo implements Runnable {
public void run() {
int age = 18;
for (int i = 0; i < 10 ; i++) {
SaxionApp.printLine(i);
}
SaxionApp.printLine("Variable `i` is NOT available here!");
}
}
Note: that i
is declared in the for loop. This makes i
only available in the body of the for-loop.
If you want i
to have broader scope. Move it up
.
public class ScopingDemo implements Runnable {
public void run() {
int age = 18;
int i;
for (i = 0; i < 10 ; i++) {
SaxionApp.printLine(i);
}
SaxionApp.printLine("Variable 'i' IS available here");
}
}
(Note: i
is not a very desciptive name, fine to use in a for loop as index, but not outside.)
This works the same for other scope blocks {
}
as well. Examples if
statements, switch
statements, while loops
and enhanced for-loops
.
See below a while-loop
example.
public class ScopingDemo implements Runnable {
public void run() {
int counter = 0;
while (counter < 10) {
int counterPlus10 = counter + 10;
counter++;
}
SaxionApp.printLine("Variable counter is available here, but counterPlus10 is NOT");
}
}
public class ScopingDemo implements Runnable {
public void run() {
int age = 18;
}
public void print() {
SaxionApp.printLine(age);
}
}
So, this program does not compile, since age is declared in the run()
method and is only available there.
What if you want to make the value of age available in the print()
method as well, you have 2 options:
1) Pass the variable as a argument to the print()
method. (called: parameter scoping
)
public class ScopingDemo implements Runnable{
public void run() {
int age = 18;
print(age);
}
public void print(int ageParameter) {
SaxionApp.printLine(ageParameter);
}
}
2) Declare age
on class level (called: instance variable scoping
)
public class ScopingDemo implements Runnable{
int age = 10;
public void run() {
SaxionApp.printLine(age); // prints: 10
age = 20; // age is set to 20
print();
}
public void print() {
SaxionApp.printLine(age); // prints: 20
}
}
This works perfectly fine. You can print age, or change its value from all methods in the class.
public class ScopingDemo implements Runnable {
public void run() {
int age = 10;
printAndUpdateAge(age);
SaxionApp.printLine(age); // (still) prints 10
}
public void printAndUpdateAge(int age) {
age++; // Set local age to: 11
SaxionApp.printLine(age); // prints: 11
}
}
Note: that since age
is a primitive-type (type with small letter) a copy is passed to the method printAndUpdateAge()
. The copied value is changed in the method printAndUpdateAge()
, but not the original value.
For non-primitive types, like ArrayLists
this works completely different. When passing an ArrayList as an argument to a method, the reference is passed and not a copy of the value. This means that:
public class ScopingDemo implements Runnable {
public void run() {
ArrayList<String> names = new ArrayList<>();
names.add("Alpha");
addNameToList(names);
SaxionApp.printLine(names); // [ Alpha, Bravo] is printed.
}
public void addNameToList(ArrayList<String> names) {
names.add("Bravo");
}
}
Both methods can manipulate the same list.
If you need the information from the list in many methods, you might decide to declare it as an instance variable
again. See the sample below:
public class ScopingDemo implements Runnable {
ArrayList<String> names = new ArrayList<>();
public void run() {
names.add("Alpha");
}
public void addBravo() {
names.add("Bravo");
}
public void addCharlie() {
names.add("Charlie");
}
public void print() {
for (String name: names) {
SaxionApp.print(name);
}
}
}
All methods work on the same list, so this is perfectly possible and saves the trouble of passing the same list as method parameter each time.
Instance variable level scoping:
int
, char
, bool
, …) variables and reference typed (ArrayList
) variables can be set on instance variable level. Now all methods can print and update (read & write) the variable. (There is only 1 version if the variable)
public class ScopingDemo implements Runnable {
ArrayList<String> names = new ArrayList<>();
int age = 10;
public void run() {
}
}
Local variable scoping (on method level):
public class ScopingDemo implements Runnable {
public void run() {
int age = 10; // visible in whole method.
if (age < 18) {
boolean minor = true; // only visible in if block {}
}
}
}
Parameter level scoping:
int
, char
, bool
, … ) to a method makes a copy of the value. You are not able to change the original value in the method that gets called.ArrayList
) variable to a method does not make a copy. You can change the original list from the called method.public class ScopingDemo implements Runnable {
public void run() {
ArrayList<String> names = new ArrayList<>();
int age = 10;
update(names, age);
}
public void update(ArrayList<String> names, int age) {
names.add("Alpha"); // changes the list in run() also
age++; // only changes the local copy of age here
}
}