Java II

Classes

  • Classes are the primary organizational unit in Java
  • They contain both variables and functions
  • Each class is generally given its own file
  • No prototypes are needed

Class Syntax

  • The syntax for creating a class is
    < accessLevelModifier > class < className >{
     < code goes here >
    }
    
  • In general, each class is defined in a file that has the same name as the class
    • The class UMBCer would be in file named UMBCer.java

Class Syntax Example

public class UMBCer{

}

Class Members

  • The members of the class are the variables used to hold the state of the class
  • Each member must be declared with an access level modifier and a type.
public class UMBCer{
    private String firstName;
    private String lastName;
    private String email;
    private String id;
}

Methods

  • Similar to functions in procedural languages
  • Should be the primary way to interact with the state of an object
  • Just like members, methods are declared with an access level modifier
  • Methods have access to all the members of a class

Method Examples

public class UBMCer{
    private String firstName;
    private String lastName;
    private String email;
    private String id;

    ...

    public void printFullName(){
        System.out.println(firstName + " " + lastName);
    }

    ...
}

Method Examples

public class UBMCer{
    private String firstName;
    private String lastName;
    private String email;
    private String id;

    ...

    public String getFullName(){
        return firstName + " " + lastName;
    }

    ...
}

Method Examples

public class UBMCer{
    private String firstName;
    private String lastName;
    private String email;
    private String id;

    ...

    public boolean setEmail(String email){
        if(email.endsWith("@umbc.edu"))
        {
          this.email = email;
          return true;
        }

        return false;
    }

    ...
}

Constructors

  • Constructors are special methods used to initialize objects of a class
  • Constructors have no return type and have the same name as the class.
  • Each class can have multiple constructors
    • In this case the compilier differentiates them by their parameter types

Constructor Example

import java.util.Random;
public class UMBCer{
    private String firstName;
    private String lastName;
    private String email;
    private String id;

    public UMBCer(String firstName, String lastName)
    {

        this.firstName = firstName;
        this.lastName = lastName;
        this.email = firstName + "." + lastName + "@umbc.edu";

        String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        Random rnd = new Random();

        this.id = alphabet.charAt(rnd.nextInt(alphabet.length())) + "" +  
                  alphabet.charAt(rnd.nextInt(alphabet.length())) +
                  String.valueOf(rnd.nextInt(9) + 1) + String.valueOf(rnd.nextInt(9) + 1)  +
                  String.valueOf(rnd.nextInt(9) + 1) + String.valueOf(rnd.nextInt(9) + 1);
    }
    ...
}

Special Methods

  • Two common tasks don't behave the way we expect with objects by default
    • Remember that using = to compare objects will compare their reference
      • We need to implement .equals(Object obj) in order to test equality
    • If we print an object, by default it will print the type of the object and a hash value
      • .toString() allows us to control what happens when we print an object.

Equals

  • The equals method should always take one parameter of type Object
    • This is to make sure we are overriding the default method all of the time.
  • A value of null being passed to the method as well as an object of another class should be handled gracefully
  • When comparing member objects, be sure to use the equal methods of those classes.

Equals Example

public class UMBCer{
    private String firstName;
    private String lastName;
    private String email;
    private String id;

    public boolean equals(Object other)
    {
        if(!(other instanceof UMBCer) || other == null)
        {
            return false;
        }
        UMBCer otherUMBCer = (UMBCer)other;

        return this.firstName.equals(otherUMBCer.firstName) && 
               this.lastName.equals(otherUMBCer.lastName) && 
               this.email.equals(otherUMBCer.email) && 
               this.id.equals(otherUMBCer.id);
    }

}

toString Example

  • The toString method is called automatically when the object is passed to a function that produces a string, like System.out.println()
  • Remember this is the default method and should return something legible, but in many cases shouldn't be relied upon in code to produce formatted strings
public class UMBCer{
    private String firstName;
    private String lastName;
    private String email;
    private String id;

    public String toString(){
        return "UMBCer " + id + ": " + firstName + " " + lastName;
    }

}

Method Overloading

  • Due to Java's typing we can have many methods with the same name, even in the same object.
  • The compiler and the runtime system use the method signature along with the parameters being passed at runtime to deterimine which method to use
  • The return type is not part of the method signature
  • The following code does not work
public class UMBCer{
    private String firstName;
    private String lastName;
    private String email;
    private String id;

    public void setName(String firstName){
        this.firstName = firstName;
    }

    public boolean setName(String lastName){
        this.lastName = lastName;
    }

Method Overloading Example

import java.util.GregorianCalendar

public class UMBCer{
    private String firstName;
    private String lastName;
    private String email;
    private String id;
    private GregorianCalendar birthday;


    public void setBirthday(GegorianCalendar date){
        this.birthday = (GregorianCalendar)date.clone();
    }

    public boolean setBirthday(int month, int day, int year){
        this.birthday = new GegorianCalendar(year,month,day);
    }

Returning Objects

  • A method can return an object just like any other data type
  • We need to take special precautions when returing object
    • Always return a new object
import java.util.GregorianCalendar

public class UMBCer{
    private String firstName;
    private String lastName;
    private String email;
    private String id;
    private GregorianCalendar birthday;

    public GegorianCalendar getBirthday(){
        return  (GregorianCalendar)birthday.clone();
    }

Copy Constructors

  • In the previous example, we had to call clone to ensure we were returning a new object.
  • It is often easier to use new and pass the existing object as a parameter
public class UMBCer{
    private String firstName;
    private String lastName;
    private String email;
    private String id;
    private GregorianCalendar birthday;

    public UMBCer(UMBCer other){
        this.firstName = new String(other.firstName);
        this.lastName = other.lastName;
        this.email = other.email;
        this.id = other.id;
        this.birthday = (GregorianCalendar)other.birthday.clone();
    }

}

Private Methods

  • So far all methods have been public
  • When we declare a method as private, only other methods of that class can call it.
  • This is useful for helper methods that we don't want to make available to all users of the class.
public class UMBCer{
    private String firstName;
    private String lastName;
    private String email;
    private String id;
    private GregorianCalendar birthday;

    private boolean validEmail(String email){
        return email.endsWith("@umbc.edu");
    }

Static

  • Sometimes, we want a variable or a method to exist for the whole class rather than an instance of it.
  • Use the keyword static to accomplish this.
  • This goes against OOP principles
    • But it is really useful and can make implementation more efficent
import java.util.Random;
public class UMBCer{
    private String firstName;
    private String lastName;
    private String email;
    private String id;
    private static String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static Random rnd = new Random();

    public UMBCer(String firstName, String lastName)
    {

        this.firstName = firstName;
        this.lastName = lastName;
        this.email = firstName + "." + lastName + "@umbc.edu";

        this.id = alphabet.charAt(rnd.nextInt(alphabet.length())) + "" +  
                  alphabet.charAt(rnd.nextInt(alphabet.length())) +
                  String.valueOf(rnd.nextInt(9) + 1) + String.valueOf(rnd.nextInt(9) + 1)  +
                  String.valueOf(rnd.nextInt(9) + 1) + String.valueOf(rnd.nextInt(9) + 1);
    }
    ...
}

File IO

  • Working with files in Java requres two objects generally
    • Their instantiaions can be combined into one line
      • A stream represents the flow of text into or out of a file
      • The PrintWriter class implements functions used in printing
      • The Scanner class implements functions used in reading.

Reading from a File

  • To read from a file we create a FileInputStream that we then pass to a Scanner instance
  • Some of the methods are nextLine() , nextInt(), and nextFloat()
import java.util.Scanner;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class ScannerExample{

    public static void main(String[] args){

        Scanner input = new Scanner( new FileInputStream("words.txt"));

        while(input.hasNextLine())
        {
            line = input.nextLine();
        }
    }
}

Writing to a File

  • Writing is very similar, except we use a PrintWriter instance
  • The main methods to use in this class are print and println
import java.io.PrintWriter
import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class WriterExample{
    public static void main(String[] args){

        PrintWriter output = new PrintWriter( new FileOutputStream("out.txt"))

        output.println("Print this to the file");

        output.close();
    }
}

Exceptions Preview

  • Exceptions are them main way to indicate and handle errors in Java
  • When attempting to read a file, what happens if the file doesn't exist?
import java.util.Scanner;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class ScannerExample{

    public static void main(String[] args){

        try{
            input = new Scanner( new FileInputStream("words.txt"));

            while(input.hasNextLine())
            {
                line = input.nextLine();
            }
        }
        catch(FileNotFoundException)
        {
            System.err.println("Could not open file words.txt");
        }
    }
}