6. Additional Language Features

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 – 1.5 Hour

Not what you are looking? Try the next tutorial – Additional Java SE Classes

Lab 1: Autoboxing / unboxing

Lab 1: Autoboxing / unboxing
  1. Java has reference types and primitive types:
    • Reference types:
    • Primitive types:
      • boolean
      • /short/int/long
      • float/double
      • char
    • Many methods expect object references, such as the methods in collection classes
      • You can’t pass primitive types!
      • You must “box” primitive types into class-type wrappers:
        • java.lang.Boolean
        • java.lang.Byte/Short/Integer/Long
        • java.lang.Float/Double
        • java.lang.Character
  2. Boxing
    • Boxing:
      • Wrapping a primitive in a class-type wrapper
    • Manual boxing:
      ArrayList list = new ArrayList();
      list.add(new Integer(12345));
    • Autoboxing (Java 1.5 onwards)
      ArrayList list = new ArrayList();
      list.add(12345);
    • Note: Also see the “Collections and Generics” chapter
  3. Autoboxing and Overloading
    • Autoboxing complicates overloading
      • Because it makes more methods reachable
    • The rule is this:
      • The compiler always favours widening over autoboxing
      • Ensures backward compatibility with existing code
    • Example:
      // Overloaded methods:
      void myMethod(Integer x) { } // Version 1, has a wrapper parameter.
      void myMethod(long x) { } // Version 2, has a primitive long parameter.
      // Call myMethod() with an int. Will invoke version 2 of the method.
      myMethod(42);
    • View code file.
  4. Unboxing
    • Unboxing:
      • Unwrapping a primitive from a class-type wrapper
    • Manual unboxing:
      Integer wrappedValue = (Integer) list.get(0);
      int primitiveValue = wrappedValue.intValue();
    • Auto unboxing (Java 1.5 onwards)
      int primitiveValue = (Integer) list.get(0);
    • Note: Also see the “Collections and Generics” chapter
  5. Best Practice
    • Autoboxing/unboxing hide boxing and unboxing operations
      • They do not eliminate these operations
    • Boxing and unboxing are slow operations
      • Only use them when absolutely necessary
        • E.g. when using raw collection classes
      • Do not use for compute-intensive operations
        • E.g. complex financial calculations
        • Much better to use primitive types everywhere!

Autoboxing

Lab
  1. Using autoboxing and unboxing
    • Open AutoBoxingUnboxing.java, and write an application that explores autoboxing and unboxing in Java
    • Suggestions and requirements:
      • Write a simple main() method that declares an Integer variable. Try to assign it an integer constant (e.g. 42). Does this work? Now try to assign it a (previously declared) int variable. Does this work?
        // Declare an Integer variable.
        Integer anInteger = new Integer(42);
        System.out.println("Integer: " + anInteger);
        // Automatically unbox Integer to int.
        int anInt = anInteger + 10; // Implicit unboxing.
        System.out.println("int: " + anInt);
      • View code file.
      • Try to assign your Integer variable to an int variable. What happens?
      • Create an ArrayList object (you’ll need an import statement to import the java.util.ArrayList class). Try to add a mixture of Integer objects and int variables to the ArrayList. Does it work?
        // Create an ArrayList containing an Integer and a (boxed) int.
        ArrayList list = new ArrayList();
        list.add(anInteger);
        list.add(anInt); // Implicit boxing.
      • View code file.
      • Write a loop to iterate through your ArrayList. Each time round the loop, try to assign the current element to an Integer variable, and also to an int variable. What works? Explain to yourself what’s happening under the covers.
        System.out.println("Here are the items in the ArrayList...");
        for (int i = 0; i < list.size(); i++) {  // Try to access item as an Integer. This gives us a direct reference to heap-based object.  Integer theInteger = (Integer)list.get(i);  // Try to access item as an int. This gives us an unboxed copy of heap-based object.  int theInt = (Integer)list.get(i); // Implicit unboxing.  System.out.printf(" Item %d as Integer: %d, as int: %d\n", i, theInteger, theInt); }
      • View code file.

Lab 2: Varargs

Lab 2: Varargs
  1. Overview
    • Some methods require an arbitrary number of values
    • Prior to Java 1.5:
      • The method would have to declare an array argument
      • The client code would have to create an array containing the values, and pass the array to the method
        Object[] array = { "Andy", 45, 1.68 };
        System.out.printf("Hi %s, you are %d and your height is %fm.\n", array);
      • View code file.
    • Java 1.5 introduces the "vararg" language feature
      • Enables you to pass arbitrary vales as a sequence of arguments
      • No need to parcel-up values into an array beforehand
        System.out.printf("Hi %s, you are %d and your height is %fm.\n", "Andy", 45, 1.68);
      • View code file.
  2. Defining Vararg Methods
    • To define a varargs method, use the following syntax for the last argument in the method signature:
      baseType... paramName
    • The ... (ellipsis) denotes an arbitrary number of arguments of the specified base type
      • The client can pass a sequence of zero-or-more arguments
      • Alternatively the client can pass an array, in ye olde worlde fashion
  3. Example
    • Here's a varargs method
      • Takes two mandatory String arguments, plus zero-or-more subsequent arguments of any type
        private static void myVarargsMethod(String firstName,
                          String lastName,
                          Object... specialThings) {
          System.out.printf("\nHi %s %s, here are your special things:\n", firstName,
                                           lastName);
          for (Object obj: specialThings) {
            System.out.println(" -- " + obj.toString());
          }
        }
      • View code file.
    • Client code:
      // Calling my varargs method using a series of separate arguments.
      myVarargsMethod("Andy", "Olsen", "Jayne", "Emily", "Thomas", 3, Color.RED);
      // Calling my varargs method using an array. Just to show you can still do this!
      Object[] array = { "Jayne", "Emily", "Thomas", 3, Color.RED };
      myVarargsMethod("Andy", "Olsen", array);
    • View code file.
  4. Varargs and Overloading
    • Varags complicates overloading
      • Because it makes more methods reachable
    • The rule is this:
      • The compiler always favours widening over varargs
      • (Incidentally, the compiler also favours autoboxing over varargs)
      • Ensures backward compatibility with existing code
    • Example:
      // Overloaded methods:
      void myMethod(int a, int b) { } // Version 1, takes two ints.
      void myMethod(short... va) { } // Version 2, takes vararg list of shorts.
      // Call myMethod() with an two shorts. Will invoke version 1 of the method.
      short s1=10, s2=20;
      myMethod(s1, s2);
Lab
  1. Defining and calling variable-argument-list methods
    • Open Varargs.java, and write a method named sum(). The method should take at least 2 double parameters, plus any number of additional double values, and return the sum
    • Suggestions and requirements:
      • Implement sum() as a varargs method. Inside the method, use a loop to add up all the incoming values.
        private static double sum(double num1, double num2, double... additionalNums) {
         double total = num1 + num2;
         for(double n: additionalNums) {
          total += n;
         }
         return total;
        }
      • View code file.
      • Call sum() from main(), passing in a variety of different values.
        // Call sum() with exactly 2 parameters.
        double result1 = sum(100, 200);
        System.out.println("result1 is " + result1);
        // Call sum() with more than 2 parameters.
        double result2 = sum(100, 200, 300, 400);
        System.out.println("result2 is " + result2);
        // Call sum() with fewer than 2 parameters. This won't compile.
        // double result3 = sum(100);
        // System.out.println("result3 is " + result3);
        // Call sum() with 2 double parameters, plus some illegal parameter types. This won't compile.
        // double result4 = sum(100, 200, "Hello", "world");
        // System.out.println("result1 is " + result1);
      • View code file.
      • What happens if you pass in exactly 2 parameters?
      • What happens if you pass in more than 2 parameters?
      • What happens if you pass in fewer than 2 parameters?
      • What happens if you pass in 2 double parameters, plus some illegal parameter types?

Lab 3: Type-safe enumerations

Lab 3: Type-safe enumerations
  1. Overview
    • A type-safe enumeration (or simply "enum") is a set of related constants
      • Typically integers or strings
      • E.g. days of the week, months of the year, chemical symbols, etc.
    • Enums were introduced in Java 1.5
      • Prior to this, you had to define a regular class with a series of public final static fields
        class DirectionAsClass {
          public static final int NORTH = 0;
          public static final int SOUTH = 1;
          public static final int EAST = 2;
          public static final int WEST = 3;
        }
      • View code file.
  2. Defining a Simple Enum
    • To define a simple enum:
      • Similar to a class, except specify enum rather than class
      • Note: enums are implicitly final subclasses of java.lang.Enum
    • Specify a series of comma-separated enum constants
      • Enum constants are implicitly public static final
    • Example:
      enum Direction {
        NORTH,
        SOUTH,
        EAST,
        WEST
      };     // Note, the semicolon is optional
    • View code file.
    • Note:
      • You can define enums globally (similar to class definitions)
      • Or you can define enums within a class
      • But you can't define enums within a method
  3. Using a Simple Enum
    • To use a simple enum:
      • Similar to using primitive types
      • Access enum constants via EnumTypeName.EnumConstantName
      • Note: You can't use new on enums
    • Useful enum methods:
      • equals() - compare for equality (or just use ==)
      • toString() - get name of enum constant (or name())
      • ordinal() - get the ordinal position of an enum constant
    • Example:
      Direction southPole = Direction.SOUTH;
      System.out.println("southPole string: " + southPole.toString());
      System.out.println("southPole ordinal: " + southPole.ordinal());
    • View code file.
  4. Going Further with Enums
    • An enum type can also contain:
      • Instance variables - For each enum constant
      • Constructors - To initialize the instance variables for an enum constant
      • Getters/setters - To get/set instance variables for an enum constant
      • Overrides for superclass methods - E.g. toString()
      • Define instance-specific methods - If appropriate
  5. Defining a Complex Enum - See Enumerations.java for full implementation
    enum USstate {
      AL("Alabama", "Montgomery"),
      ...
      WY("Wyoming", "Cheyenne");  // The semi-colon is required if more code follows.
      private String stateName;
      private String capitalCity;
      USstate(String s, String c) {
        stateName  = s;
        capitalCity = c;
      }
      final public String getStateName() {
        return stateName;
      }
      ...
      @Override
      public String toString() {
        return ...
      }
    ...
    }
  6. View code file.
  7. Defining Instance-Specific Methods
    • If you really want to, you can define methods on specific instances in an enum definition
      enum FootballTeam {
        LFC("Liverpool"),
        ...
        SCFC("Swansea City") {
          String getFullName() {
            return this.teamName + ", the best team in the land";
          }
        },
        String teamName;
        FootballTeam(String n) {
          teamName = n;
        }
        String getFullName() {
          return teamName + " Football Club";
        }
      }
    • View code file.
  8. T6P1

Lab
  1. Defining and using enums
    • Open Employee.java, and take a look at the existing code. This is the solution code from earlier in the course.
    • Enhance the Employee class so that it holds the employee's contract type (full-time, part-time, or casual)
      • Define an enum type named ContractType to represent the allowable contract types
        enum ContractType {
         FULL_TIME("full-time", 25),
         PART_TIME("part-time", 10),
         CASUAL("casual", 0);
        }
      • View code file.
      • Modify the constructor/display capabilities of the Employee class, to initialize and to output the employee's contract type
        // Data in each enum instance.
        private String textualRepresentation;
        private int daysLeave;
        // Constructor to initialize enum instance. Can't be used by client.
        ContractType(String textualRepresentation, int daysLeave) {
         this.textualRepresentation = textualRepresentation;
         this.daysLeave = daysLeave;
        }
        // Override some methods.
        @Override
        public String toString() {
         return String.format("%s [%d days leave]", this.textualRepresentation, this.daysLeave);
        }
      • View code file.
      • Test the Employee class in UseEmployee.java
        public static void main(String[] args) {
         Employee emp = new Employee("Claire", 25000, ContractType.FULL_TIME);
         System.out.println(emp);
        // emp.displayJoiningDateInfo();
        }
      • View code file.

Lab 4: Static imports

Lab 4: Static imports
  1. Overview
    • Some classes contain a lot of static members
      • "Kitchen sink" classes
    • The java.lang.Math class is a common example:
      public class Math {
        public static final double PI = 3.141592653589793;
        public static final double E = 2.718281828459045;
        public static double sin(double a) { ...}
        public static double cos(double a) { ...}
        public static double tan(double a) { ...}
        ...
      }
    • View code file.
    • You access static members in client code as follows:
      double angle = 2 * Math.PI;
      System.out.println("Sin of angle: " + Math.sin(angle));
      System.out.println("Cos of angle: " + Math.cos(angle));
      System.out.println("Tan of angle: " + Math.tan(angle));
    • View code file.
  2. Using Static Imports
    • Java 1.5 supports "static imports"
      • Imports the specified static members from a class
        import static className.staticMember; // Or className.* to import all statics.
    • Enables client code to use static members without class qualification
      • Makes the client code marginally(!) cleaner
  3. Example
    • Importing specific statics from a class:
      import static java.lang.Math.PI;
      import static java.lang.Math.sin;
      import static java.lang.Math.cos;
      import static java.lang.Math.tan;
      // Usage:
      double angle = 2 * PI;
      System.out.println("Sin of angle: " + sin(angle));
      System.out.println("Cos of angle: " + cos(angle));
      System.out.println("Tan of angle: " + tan(angle));
    • View code file.
    • Importing all statics from a class:
      import static java.awt.Color.*;
      // Usage:
      System.out.println("My favourite colour is " + RED);
      System.out.println("I also quite like " + GREEN);
    • View code file.
  4. Best Practice
    • Use static imports sparingly!
      • Only use them when you make very frequent use of static members from a class
    • If you overuse static imports:
      • Your program can become unreadable and hard-to-maintain
    • In particular, try to avoid importing all the static members from a type
      • Increases likelihood of name clashes
      • Also, code maintenance staff won't know which class the static members are defined in
Lab
  1. Using static imports
    • Still in the Employee class, add another method named displayJoiningDateInfo(). The method should make use of various static members of the Calendar class, to display detailed information about the employee's joining date
    • Suggestions and requirements:
      • The Calendar class provides extensive date/time capabilities for modern Java code. Calendar is an abstract class, so you can't create a Calendar object itself; instead, you create a GregorianCalendar object as follows (GregorianCalendar is a concrete subclass of Calendar):
        Calendar cal = new GregorianCalendar();
      • Once you've created your GregorianCalendar object, you can set its date/time based on an existing Date object as follows (the following code snippet assumes you have a Date object named joined):
        cal.setTime(joined);
      • You can invoke the get() method on your (Gregorian)Calendar object, to get various pieces of information about the date/time. The get() method can take a static value from the Calendar class, to indicate which piece of information you require. For example, the following code snippet gets the year value:
        int year = cal.get(Calendar.YEAR);
      • Write code to get various pieces of date/time info from your (Gregorian)Calendar object. You'll need to make use of several static values from the Calendar class; use static imports to simplify your code.
        public void displayJoiningDateInfo() {
         // Create a Calendar based on the employee's joining date.
         Calendar cal = new GregorianCalendar();
         cal.setTime(joined);
         // Get various pieces of date info.
         int dayOfMonth = cal.get(DAY_OF_MONTH);
         int month = cal.get(MONTH);
         int year = cal.get(YEAR);
         // Display dd mm yyyy
         System.out.printf("Date joined: %d %d %d\n", dayOfMonth, month+1, year);
        }
      • View code file.

 

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

7. Additional Java SE Classes


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