Welcome to Lesson 10!


Learning Objectives for Today's Lesson

By the end of today's lesson, you should know...

  • What is the meaning of the keyword static?
  • How do you write static member variables and methods in a class?
  • How do you use static member variables and call static methods from other classes?
  • How automatic garbage collection works in Java


1. Static Methods and Variables

Static Methods

  • Java has both static methods and variables
  • Static members do not belong to objects, but to the class itself
  • So what does this mean?
  • First of all, it means that you can call a static method without creating an object

Writing Static Methods

  • You write static methods like regular methods, but with the keyword static added
  • For example:
    public static double area(double radius) {
        return radius * radius * PI;
    }
  • You also write an important static method each time you write a Java program:
public static void main(String[] args) { 
  • This method is called by the JVM without instantiating an object of the class.

Calling Static Methods

  • Although a static member does not require a calling object, it does belong to a class
  • To call static methods from another class, you must use the class name, a dot (period), the method name and a set of parenthesis with any required arguments if the method is defined in a different class.
    • Note that in 36A, we called static methods from inside the same class, and did not need to prepend the class name to the method name.
  • An example of static methods can be found in the Math class
  • The Math class contains many standard mathematical methods
  • In addition to methods, the Math class has final static variables defined for E and PI
System.out.println(Math.sqrt(9) + Math.PI);


When to Write Static Methods

  • Consider whether the action taken by the method is one that should "belong" to an object
    • Is it an action that an object itself would take?
    • Or is this an action that should be taken even outside the context of the class?
  • For example, you might have a Temperatures class with a method called convertToFahrenheit.
    • Because you might want to calculate a conversion between a Fahrenheit and Celsius without constructing an object of the Temperature class, you could make this method static.
    • In the below example, we don't want to construct an object of the Temperature class (with all of the "baggage" that goes along with it, such as a Patient object and hospital ID) just to convert between Celsius and Fahrenheit.
    • Thus, we define the conversion method to be static
class Temperature {
    private Patient p;
    private int hospitalId;

    public Temperature() {
        p = null;
        hospitalId = -1;
    }
   
    public static double convertToFahrenheit(double degreesCelsius) {
        return degreesCelsius * 1.8 + 32;
    }
          
           //rest of the class

}

public class TemperatureTest {
    public static void main(String[] args) {
        double tempInC = 48.0;
        double tempInF = Temperature.convertToFahrenheit(tempInC);
        System.out.println(tempInC + "C is " + tempInF + "F");
    }
}

  • Alternately:

class Temperature {
    private Patient p;
    private int hospitalId;

    public Temperature() {
        p = null;
        hospitalId = -1;
    }
   
    public double convertToFahrenheit(double degreesCelsius) {
        return degreesCelsius * 1.8 + 32;
    }
          
           //rest of the class

}

public class TemperatureTest {
    public static void main(String[] args) {
        double tempInC = 48.0;

           Temperature t = new Temperature(); //more overhead to simple conversion
        double tempInF = t.convertToFahrenheit(tempInC);
        System.out.println(tempInC + "C is " + tempInF + "F");
    }
}
  • The following shows static methods defined in a class and a test class that calls the static methods

Example Defining and calling static Methods

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

import java.util.Scanner;

public class BankAccount {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
double amount, interest;
String response;

System.out.println("Welcome to Wells Fraudster Bank!\n");
System.out.println("Ready to open an account?");
System.out.printf("We're offering an amazing annual interest rate of %.2f percent!\n\n",
+ (Account.interestRate * 100)); //accessing static variable of Account class
System.out.print("Enter the amount you are considering investing: $");
amount = input.nextDouble();

//calling static method of Account class
interest = Account.calcYearlyInterest(amount);
System.out.printf("In one year, you could earn: $%.2f\n\n", interest);
System.out.print("Would you like to create an account (yes/no): ");
response = input.next();
if (response.equalsIgnoreCase("yes")) {
input.nextLine();
System.out.print("Enter your name: ");
String name = input.nextLine();
Account newAccount = new Account(name, amount);
System.out.println("Your new account number is: " + newAccount.getAccountNum());
} else {
System.out.println("Goodbye!");
}
input.close();
}
}

class Account {
public static final double interestRate = 0.015;
private static int nextAccountNum = 10000;

private String name;
private int accountNum;
private double balance;

Account(String name, double balance) {
this.name = name;
this.accountNum = nextAccountNum++;;
this.balance = balance;

}

public static double calcYearlyInterest(double dollars) {
//I = Principle x rate x time
return dollars * interestRate * 1;
}

public void updateBalance(double newBalance) {
balance = newBalance;
}

public String getName() {
return name;
}

public int getAccountNum() {
return accountNum;
}

public double getBalance() {
return balance;
}

}

Static Variables

  • A class can have static variables as well as static methods
  • Like static methods, a static variable belongs to the class as a whole and not to objects individually
    • Another way to think of it: the static variable is shared among all objects of the class, rather than belonging to just one, individual object.
  • With instance variables, each object has its own copies
  • However, with static variables all objects share the variable
A static variable is shared amongst all the objects of the class

Writing Static Variables

  • You write static variables like instance variables, but with the keyword static added
  • For example:
    private static int numObjs;
    
  • If you do not initialize static variables, then Java initializes them just like instance variables
  • Numerical values are initialized to 0, boolean values to false and objects to null
  • Like instance variables, all static variables should be declared private except for constants
  • Oftentimes you declare constant variables static (and public)
  • For example:
    public static final double interestRate = 0.015;
    

Accessing Static Variables

  • Any method can access the value of a static variable
  • This includes static methods as well as instance methods

Example Using Static Methods and Variables

  • A classic example of using static fields and methods is to keep track of how many objects of a class are constructed
  • We first add an object count variable to the class:
    private static int numObjs = 0;
    
  • We need to increment the variable whenever a new object is instantiated
  • Thus we increment the static variable in the every constructors
    public ConstructionCounter() {
        numObjs++;
    }
    
  • Also need a method to retrieve the count
    public static int getNumObjs() {
        return numObjs;
    }
    
  • Since the getNumObjs() method is static, we can call it without instantiating an object:
    System.out.println("Initial count: " + getCount());
    
  • After instantiating several objects, we call the method again to retrieve the count of objects instantiated
  • We can experiment with the following example code

Example Using static Methods and Variables

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class ConstructionCounter {
    private static int numObjs = 0;

    public ConstructionCounter() {
        numObjs++;
    }

    public static int getCount() {
        return numObjs;
    }

    // For testing
    public static void main(String[] args) {
        System.out.println("Initial count: "
            + getCount());
        ConstructionCounter c1 =
            new ConstructionCounter();
        ConstructionCounter c2 =
            new ConstructionCounter();
        System.out.println("Number constructed: "
            + getCount());
    }
}

Static Dos and Don'ts:

  • Note that static methods canNOT call regular methods without creating instance of the class.
  • This is why you cannot call regular methods from the main() method
  • If you try to call a regular method from a static method (without creating an instance of the class), you get a message like:
    non-static method cannot be referenced from a static context
  • For example:
public class CoffeeBar {
   
    public static void main(String[] args) {
        CoffeeBar bar = new CoffeeBar();
        Coffee cup1 = new Coffee();
        
        System.out.println("Before making coffee: " + cup1.getFlavor() + "\n");
        
        //cannot call a non static method from a static method
        makeCoffee(cup1, "Mocha Latte"); //will cause error
   
    }
    
    public void makeCoffee(Coffee cup, String flavor) {
        cup.setFlavor(flavor);
        addTopping(cup, "cinnamon"); //okay to call static method from non-static method
        printOrder(cup); //okay to call a non-static method from a non-static method
    }
    
    public static void addTopping(Coffee cup, String topping) {
        cup.setFlavor(cup.getFlavor() + " with " + topping);
    }
   
    public void printOrder(Coffee cup) {
        System.out.println("Your ordered: " + cup.getFlavor());
    }
}

class Coffee {
    private String flavor;
    
    public Coffee() {
        setFlavor("flavor unknown"); //okay to call a non-static method from a non-static method
    }

    public Coffee(String flavor) {
        setFlavor(flavor); //okay to call a non-static method from a non-static method
    }
   
    public String getFlavor() {
        return flavor;
    }

    public void setFlavor(String newFlavor) {
        flavor = newFlavor;
    }
}


Don't: Write a static method to interact with a non-static variable

private int numObjs;

public static int getNumObjs() { //will not compile
    return numObjs;
}


Do: Write a static method to interact with a static variable


private static int numObjs;

public static int getNumObjs() { //will compile
    return numObjs;
}


Do: Write a non-static method to interact with a static variable


private static int numObjs;

public int getNumObjs() { //will compile
    return numObjs;
}

Activity 10.1: A Person Class with Static Variable and Method (10 pts)

  • Open up your Person.java class from the previous activity.
  • Add a static variable to the top of your Person class:
private static int numPersons = 0;
  • Next, add two static methods to access and update the value of the numPersons variable:
  • Write a static access method as follows:
    • This accessor method is named getNumPersons
    • It is a static method
    • It returns an int
    • The body of the method returns the value of the numPersons variable
  • Write a static mutator method as follows:
    • This mutator method is named updateNumPersons
    • It is a static method
    • It returns nothing
    • The body of the method increments the value of numPersons by 1
  • Copy and paste the new test file below into PersonTest.java (you can erase the old contents of the file):
/**
* PersonTest.java, Activity 10.1
* @author
* CIS 36B
*/

import java.util.Scanner;

public class PersonTest {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        String name, gender, street;
        int age, number;
        Person person1;
     
        System.out.print("Welcome!\n\nEnter your name: ");
        name = input.nextLine();
       
        System.out.print("Enter your age: ");
        age = input.nextInt();
       
        System.out.print("Enter your gender: ");
        gender = input.next();
        
        System.out.print("Enter the street number of your address: ");
        number = input.nextInt();
       
        System.out.print("Enter the name of your street: ");
        input.nextLine();
        street = input.nextLine();
        
        Address address = new Address(number, street);
       
        person1 = new Person(name, age, gender, address);
        Person.updateNumPersons();
        System.out.println("\nYour Summary:\n" + person1);
       
       
        Person person2 = new Person(person1);
        person2.setName("C.J. Nguyen");
        Address a = new Address(42, "South 3rd St");
        person2.setAddress(a);
        Person.updateNumPersons();
        
        System.out.println("\nAnother student with your "
            + "same age and gender: \n" + person2);
        
        System.out.println("\nTotal num persons: " + Person.getNumPersons());
        input.close();

    }
}
  • When you get the correct output (as shown below), upload Address.java and Person.java to Canvas

Sample Output (Note that user input may vary):


Welcome!

Enter your name: Xing Li
Enter your age: 39
Enter your gender: M
Enter the street number of your address: 555
Enter the name of your street: W. Harlem Ave

Your Summary:
Name: Xing Li
Age: 39
Gender: M
Address: 555 W. Harlem Ave

Another student with your same age and gender:
Name: C.J. Nguyen
Age: 39
Gender: M
Address: 42 South 3rd St

Total num persons: 2


2. Automatic Garbage Collection

  • What happens to an object that is no longer used?
  • Java performs what is known as "automatic garbage collection" to remove those currently unused objects.
  • In C and C++, special methods (free() and delete()) must be called by the programmer to deallocate memory -- return the memory for reuse by the program
Java heap - garbage collection


  • In Java, the garbage collection process happens automatically, and thus provides superior memory management (not prone to human error).
  • In Java, an object is marked for garbage collection if there are no references to the object in the program.
Student s1 = new Student("Wen", 3.9);
s1 = null; //s1 no longer references object
  • Additionally, as objects age, they are considered better and better candidates for garbage collection.
  • Different parts of memory are reserved for objects of different ages.
  • The Young Generation are newly created objects.
  • The Old Generation are all objects older than a predefined threshold. 
  • The Permanent Generation are objects required by the JVM that are never garbage collected
  • At certain intervals, the Garbage Collector moves through and marks objects that are currently unreferenced.
  • To read more about the Automatic Garbage Collection process, see the Oracle documentation below
  • You can manually choose to run the garbage collector as well, although it is considered bad practice, and does not necessarily speed up the garbage collection of an object.
    System.gc();
    

image source

Oracle Tutorial on Garbage Collection:


Wrap Up: 

  • Answer the practice exam questions for this lesson on Canvas


Upcoming Assignments:

  • Activity 10.1 due Thursday at 11:59pm
  • Lesson 10 Practice Exam Questions due Thursday at 11:59pm
  • Peer Reviews of Lesson 9 and 10 Practice Exam Questions due Saturday at 11:59pm
  • Lab 5 due Monday at 11:59pm


~ Have a Great Weekend! ~