4. Defining and Using Classes

About this Tutorial –

Objectives –

This course is aimed at object-oriented developers (e.g. C++ or C#) who need to transition into Java. It is also aimed at those learning to program for the first time; the course covers the Java programming constructs and APIs quickly, focussing on the differences between Java and other OO languages.

Audience

This training course is aimed at OO developers who need to transition into Java.

Prerequisites

No previous experience in Java programming is required. But any experience you do have in programming will help. Also no experience in eclipse is required. But again any experience you do have with programming development environments will be a valuable.

Contents

The Java course cover these topics and more:

  • Flow Control: Decision making: if and if-else; The switch statement; Looping: for loops; while loops; do-while loops; for-each style loops; Assertionsv
  • Concurrency: Overview of multithreading; Creating new threads; Object locking; Using wait, notify, and notifyAll
  • Collections: Overview of Java SE collection classes; Generics; Using List-based collection classes; Using Set-based collection classes; Using Map-based collection classes; Collection techniques

Exam Preparation

The Java course will help you prepare for these certifications:

  • Oracle Certified Java Associate – Exam 1Z0-803
  • Oracle Certified Java Professional – Exam 1Z0-804

Download Solutions

HTML tutorial


Overview

Estimated Time – 2 Hours

Not what you are looking? Try the next tutorial – Arrays

Lab 1: Essential concepts

Lab 1: Essential concepts
  1. What is a Class?
    • A class is a representation of a real-world entity
      • Defines data, plus methods to work on that data
      • Data is typically private, to enforce encapsulation
    • Domain classes
      • Specific to your business domain
      • E.g. BankAccount, Customer, Patient, MedicalRecord
    • Infrastructure classes
      • Implement technical infrastructure layer
      • E.g. NetworkConnection, AccountsDataAccess, IPAddress
    • Exception classes
      • Represent known types of error
      • E.g. Exception, BankException, CustomerException
    • Etc…
  2. What is a Object?
    • An object is an instance of a class
      • Created (or “instantiated”) via the new operator
      • Each object is uniquely referenced by its memory address (no need for primary keys, as in a database)
    • Object management
      • Objects are allocated on the garbage-collected heap
      • An object remains allocated until the last remaining object reference disappears
      • At this point, the object is available for garbage collection
      • The garbage collector will reclaim its memory sometime thereafter
  3. OO Modelling
    • During OO analysis and design, you map the real world into candidate classes in your application
      • Use-case diagrams
      • Class diagrams
      • Sequence diagrams
      • Object diagrams
      • State diagrams
    • UML is the standard OO notation
      • Widely used
      • Degree of ceremony varies from one organization to another

Lab 2: Defining a class

Lab 2: Defining a class
  1. General Syntax for Class Declarations
    • General syntax for declaring a class:
      [public] class ClassName {
       // Define members (data and methods) here.
      }
    • Example:
      public class BankAccount {
       // Define BankAccount data and implement BankAccount methods here.
      }
    • View code file.
    • Note:
      • There can only be one public class per file, and the filename must be classname.java
      • You can also define any number of non-public classes
  2. Member Modifiers
    • Java supports 4 access levels for members in a class:
      • public – Accessible by anyone, Methods and constants are often public
      • private – Accessible only by class itself, Data and helper methods are usually private
      • protected – Accessible by class itself, subclasses, and classes in same package, Allow access to members that are hidden from general client code
      • (No access modifier) – Accessible by class itself, and classes in same package
    • Additional common modifier keywords for methods:
      • static – Indicates a class-level method (rather than an instance-level method)
      • abstract – Indicates a method is not implemented in a class (subclasses must override),The containing class must also be declared abstract.
      • final – Indicates a method cannot be overridden in subclasses
      • synchronized – Indicates a thread-safe method
    • Additional common modifier keywords for variables:
      • static – Indicates a class-level variable (rather than an instance-level variable), Can only be used with class-scope variables.
      • final – Indicates a variable cannot be modified, Can be used with class-scope variables, arguments, and local variables.
  3. Defining Instance Variables
    • A class can define any number of instance variables
      • Each instance will have its own set of these variables
    • General syntax:
      • Optional access modifier (default is package-level visibility)
      • Optional initial value (default is 0-based)
        [public | private | protected] type variableName [= expression];
    • Example:
      import java.util.Date;
      public class BankAccount {
       private String accountHolder;           // Default initial value: null
       private int id;                  // Default initial value: 0
       private double balance = 0.0;
       private Date creationTimestamp = new Date();   
       ...
      }
    • View code file.
  4. Defining Getters and Setters
    • It’s common practice to define public getters and/or setters for private instance variables
      • Allows external code/tools to get/set values as “properties”
    • General syntax:
      [public | private | protected] type getVarName() { return varName; }
      [public | private | protected] void setVarName(type param) { varName = param; }
    • Example:
      public class BankAccount {
       ...
       public String getAccountHolder() {
        return accountHolder;
       }
       public void setAccountHolder(String ah) {
        accountHolder = ah;
       }
       ...
    • View code file.
  5. The this Keyword
    • The this keyword represents the “current object”
      • Allows instance methods to explicitly access instance variables and instance methods on the “current” object
      • For example, the following are semantically equivalent
        public void setAccountHolder(String ah) {
         accountHolder = ah;
        }
        public void setAccountHolder(String accountHolder) {
         this.accountHolder = accountHolder;
        }
      • View code file.
    • Uses of this:
      • Allows use of the same name for local vars and instance vars
      • Allows you to pass a “reference to self” into callback methods
      • Constructor chaining (see later)
      • Triggers IntelliSense
  6. Defining Instance Methods
    • A class can define any number of instance methods
      • So-called because each they operate on a particular instance
    • General syntax:
      [public | private | protected] type methodName(params) {
       methodBody
      }
    • Example:
      public class BankAccount {
       ...
       public double deposit(double amount) {
        balance += amount;
        return balance;
       }
       public double withdraw(double amount) {
        balance -= amount;
        return balance;
       }
       ...
      }
    • View code file.
  7. Overloading Methods
    • A class can contain several methods with the same name
      • As long as the number (or types) or parameters is different
      • This is known as “overloading methods”
      • Useful, because it gives client code several ways to invoke the same semantic behaviour
    • Example:
      public class BankAccount {
       ...
       public double deposit(double amount) {
        balance += amount;
        return balance;
       }
       public double deposit(int dollars, int cents) {
        double amount = dollars + cents/100.0;
        return this.deposit(amount);
       }
       ...
    • View code file.
    • Autoboxing and varargs complicate overloading (see later)
  8. Overriding Methods
    • A class can override a method defined in the base class
      • This is an inheritance-related concept (see later for details)
      • You must use the same method signature as in base class
      • You should also annotate with @Override (see later for details)
    • Example:
      public class BankAccount {
       ...
       @Override
       public String toString() {
        String str = String.format("[%d] %s, %.2f", id, accountHolder, balance);
        return str;
       }
       ...
      }
    • View code file.
Lab
  1. Defining a class and creating objects
    • Write an application that defines a simple Employee class and creates some instances.
    • Suggestions and requirements:
      • The Employee class needs to hold the name and salary of the employee, and the date he/she joined the company.
        import java.util.Date;
        public class Employee {
         // Instance data.
         private String name;
         private double salary;
         private Date joined = new Date();
      • View code file.
      • The class must honour the OO principle of encapsulation, so make sure the instance variables are private. Define public getter and setter methods if you need them.
      • The class needs to allow an employee to have a pay raise, so define a payRaise() method that takes the amount of the pay raise and adds it to the employee’s current salary.
         // Business methods.
         public void payRaise(double amount) {
          salary += amount;
         }
        public void setSalary(double salary) {
         this.salary = salary;
        }
      • View code file.
      • The class should also have a toString() method that returns a textual representation of the employee’s info.
         // toString() method.
         @Override
         public String toString() {
          String str = String.format("[%d] %s earns %.2f, joined %s", id, name, salary, joined);
          return str;
         }
      • View code file.
      • Define a separate test class, where you can create some Employee objects and invoke methods upon them.
         private static void doTest1() {
         
          System.out.println("In doTest1()...");
          /*For this to work, you must define a default constructor in the Employee class.
          Employee emp = new Employee(); */
          
          emp.setName("Chris Smith");
          emp.setSalary(20000);
          emp.setJoined(new Date());
          emp.payRaise(500);
          emp.setName("Chris Jones");
          System.out.println("Employee details: " + emp1);
          
         }
      • View code file.

Lab 3: Creating and using objects

Lab 3: Creating and using objects
  1. Creating an Object
    • To create an instance (object) of the class:
      • Use the new operator
      • Pass initialization parameters if necessary
      • Get back an object reference, which points to the object on the heap
        classType objectRef = new ClassType(initializationParams);
  2. Invoking Methods on an Object
    • To invoke methods on an object:
      • Use the object.method() syntax
      • Pass parameters if necessary
        returnValue = objectRef.methodName(params);
    • The compiler automatically widens parameter values if needed
      • E.g. int value ->long parameter
      • E.g. subclass object -> superclass parameter
    • But the compiler doesn’t widen wrapper types
      • E.g. it doesn’t widen Integer ->Long
  3. Letting Go of an Object
    • Optionally, when you’ve finished using an object, set the object reference to null
      • If this is the last remaining reference to the object (on any live thread), the object is eligible for garbage collection
        objectRef = null;
    • Other ways an object can become unreferenced:
      • Reassigning an object reference to a different object
      • Isolated references (e.g. two objects that refer to each other, but no-one else refers to them)
  4. Garbage Collection
    • The JVM decides when to run the garbage collector
      • Typically when it senses memory is getting low
      • The GC looks for objects that are eligible for garbage collection, and reclaims their memory
    • You can request the JVM to do a garbage collection
      • But Java is so good, you’re advised not to do this nowadays
        System.gc();
    • If you want to find out how much free memory you’ve got:
      Runtime rt = Runtime.getRuntime();
      ...
      rt.gc(); // Alternate to System.gc()
      ...
      System.out.println("After garbage collection, free memory = " + rt.freeMemory());
  5. Object Finalization
    • When an object is garbage collected:
      • It’s finalize() method is called
      • Defined in Object, you can override it in your class to clean up
    • But note:
      • When exactly will the object be garbage collected (if ever?)

Lab 4: Initialization

Lab 4: Initialization
  1. Default Initialization
    • When you create an object, its instance variables are initialized as follows:
      • If an instance variable doesn’t specify an initial value – The variable is initialized to the appropriate default value, i.e. zero-based for primitives, and null for object references
      • If an instance variable does specify an initial value – The variable is initialized to that value, obviously
  2. The Role of Constructors
    • In addition (or instead) of default initialization:
      • You can define constructors in your class to perform non-trivial initialization
    • Rules for defining constructors:
      • A constructor is a method with the same name as the class
      • Typically public, to allow client code to access
      • No return type, not even void
      • Can specify parameters
      • Cannot be static, abstract, or final
  3. Defining a No-Arg Constructor
    • A constructor that has no parameters is called the “no-arg” constructor
      public class BankAccount {
       private String accountHolder;
       private int id;
       private double balance = 0.0;
       private Date creationTimestamp = new Date();
       public BankAccount() {
        accountHolder = "Anonymous";
        ...// Plus any other initialization needed
       }
       ...
      }
    • View code file.
    • To create the object from the class:
      BankAccount acc1 = new BankAccount();
  4. Defining Parameterized Constructors
    • A class can have number of parameterized constructors
    • This is an example of overloading
      public class BankAccount {
       ...
       public BankAccount() {
        accountHolder = "Anonymous";
        // Plus any other initialization needed
       }
       public BankAccount(String accountHolder) {
        this.accountHolder = accountHolder;
        ...// Plus any other initialization needed
       }
       ...
      }
    • View code file.
    • And you can create the objects like so where it is dependent on the parameter given:
      BankAccount acc1 = new BankAccount();
      BankAccount acc2 = new BankAccount("John Smith");
  5. Constructor Chaining
    • If several constructors have to implement common initialization logic:
      • You can chain them together, using this(params) syntax
      • Typically, a basic constructor chains to a more specific constructor
        public class BankAccount {
         ...
         public BankAccount() {
          this("Anonymous");
         }
         public BankAccount(String accountHolder) {
          this.accountHolder = accountHolder;
          // Plus any other initialization needed
         }
         ...
        }
      • View code file.
    • The following code initialises the objects:
      BankAccount acc1 = new BankAccount();
      BankAccount acc2 = new BankAccount("John Smith");
  6. Initialization Blocks
    • You can use an initialization block to perform additional initialization
      • Handy if you have common initialization (regardless of which constructor is called)
    • You can have multiple initialization blocks in a class
      • Executed in the order they appear in the class, when an object is created (after all superclass constructors have been called)
        public class BankAccount {
         ...
         {
          System.out.println("Hello from the 1st initialization block.");
         }
         {
          System.out.println("Hello from the 2nd initialization block.");
         }
         ...
        }
      • View code file.
Lab
  1. Handling initialization
    • Add constructors to the Employee class.
    • Suggestions and requirements:
      • Add a constructor that initializes the employee’s name and salary from passed-in values.
         public Employee(String name, double salary) {
          this.name = name;
          if (salary < minimumSalary) {    this.salary = minimumSalary;   } else {    this.salary = salary;   }  }
      • View code file.
      • Add another constructor that initializes the employee's name, and sets the salary to the minimum statutory salary (e.g. 7000 as a hard-coded figure, for now). Make use of constructor chaining here.
         // Constructors. Note, no default constructor.
         public Employee(String name) {
          this(name, 7000); // Use constructor chaining.
         }
      • Make sure you do NOT have a default constructor. Why not?
      • Ensure the date the employee joined the company is always set to the current date/time (regardless of which constructor was called).
         private Date joined = new Date();
      • Modify your test code so that it exercises each of the constructors
         private static void doTest3() {
          
          System.out.println("\nIn doTest3()...");
          // Increase minimum salary (for all new employees) by 1000, to 8000 now.
          Employee.setMinimumSalary(Employee.getMinimumSalary() + 1000);
          
          // Create an employee with a salary below the minimum (should set salary to the minimum, 8000).
          Employee emp1 = new Employee("John", 5000);  
          System.out.println("emp1 details: " + emp1);
          // Create an employee with a salary above the minimum (should honour the specified salary).
          Employee emp2 = new Employee("Jane", 10000);
          System.out.println("emp2 details: " + emp2);
         }
      • View code file.

Lab 5: Using the static keyword

Lab 5: Using the static keyword
  1. static Variables
    • static variables belong to the class as a whole
      • Allocated once, before first usage of class
      • Remain allocated regardless of number of instances
        public class BankAccount {
         ...
         private static int nextId = 1;
         public static final double OVERDRAFT_LIMIT = -1000;
         ...
        }
      • View code file.
    • Client code can access public static members via the class name
      System.out.println("Overdraft limit is " + BankAccount.OVERDRAFT_LIMIT);
    • View code file.
  2. static Methods
    • static methods implement class-wide behaviour
      • E.g. getters/setters for static variables
      • E.g. factory methods, responsible for creating instances
      • E.g. instance management, keeping track of all instances
    • Note:
      • A static method can only directly access static members of the class (i.e. not instance variables/methods)
      • This is because static methods don't receive a this reference
        public class BankAccount {
         ...
         public static int getNextId() {
          return nextId;
         }
         ...
        }
      • View code file.
      • In another Java file that uses this -
        System.out.println("Next account will have ID " + BankAccount.getNextId());
      • View code file.
  3. static Initialization Blocks
    • You can use a static initialization block to initialize static variables
      • Handy if you have non-trivial one-off initialization to perform
    • You can have multiple static initialization blocks in a class
      • Executed in the order they appear in the class, when the class is first loaded
        public class BankAccount {
         ...
         static {
          System.out.println("Hello from the 1st static initialization block.");
         }
         static {
          System.out.println("Hello from the 2nd static initialization block.");
         }
         ...
        }
      • View code file.
Lab
  1. Using statics
    • Refactor your Employee class to make appropriate use of static data and static methods.
    • Suggestions and requirements:
      • In the Employee class, define a static field to hold the statutory minimum salary. Set it to 7000. Use this static field in the constructor that sets the employee's salary to the statutory minimum salary. Also provide a static int to give each new employee a unique id when they are initialized.
         // Static data.
         private static double minimumSalary = 7000;
         private static int nextEmployeeID;
         
      • View code file.
      • Define static getter/setter methods to get/set the statutory minimum salary. Call these methods from your test code.
         // Getters and setters for static data.
         public static double getMinimumSalary() {
          return minimumSalary;
         }
         public static void setMinimumSalary(double min) {
          minimumSalary = min;
         }
      • View code file.
      • Define an initialization block to increase the id of the employee
        // Initialization block, for common instance initialization.
        {
         id = nextEmployeeID++;
        }
      • View code file.

 

Well done. You have completed the tutorial in the Java course. The next tutorial is

5. Arrays


Back to beginning
Copyright © 2016 TalkIT®






If you liked this post, please comment with your suggestions to help others.
If you would like to see more content like this in the future, please fill-in our quick survey.
Scroll to Top