Introduction to Java 2 Programming Lecture 5 Quick Recap; Error-handling Overview • Quick Recap – We’re half way through! – Review some of the material we’ve already covered – Walk through some of the exercises • Java Error Handling – Handling and creating Exceptions The CLASSPATH • The CLASSPATH is – – – – How Java finds compiled classes A system property Contains directories and/or jar files Is a common source of frustration! • Classify Java tools into three groups: – File based – CLASSPATH based – And “mixed mode” (I.e. used both) The CLASSPATH • File based tools (e.g. javadoc, jar) – Accept parameters referring to files. – Read the directory structure to find related files javadoc c:\intro2java\src\intro2java\*.java – Result in file-based errors • CLASSPATH based tools (e.g. java, javap) – Refer to classes and not files – Ignore the file-system, except for those directories mentioned in the CLASSPATH java intro2java.Person – Result in exceptions or errors, e.g. ClassNotFoundException; NoClassDefFoundErrors The CLASSPATH • Mixed mode tools (e.g. javac) – Accept parameters referring to files – Read the CLASSPATH to find related classes javac c:\intro2java\src\intro2java\*.java – Results in file errors (relating to parameters), and “cannot resolve symbol” errors (relating to missing classes) CLASSPATH Tips • Always add “the current working directory” to the CLASSPATH SET CLASSPATH=%CLASSPATH%;. • Keep classes and source separate (e.g. bin and src directories) • Use a “global” classes directory, e.g. c:\classes – Add this to the CLASSPATH – Always compile into that directory SET CLASSPATH=%CLASSPATH%;c:\classes javac –d c:\classes *.java Constructors • Why do we use them? – Give us chance to ensure our objects are properly initialised – Can supply default values to member variables – Can accept parameters to allow an object to be customised – Can validate this data to ensure that the object is created correctly. • A class always has at least one constructor – …even if you don’t define it, the compiler will – This is the default constructor Constructors public class EmailAddress { public EmailAddress(String address) { if (address.indexOf(“@”) == -1) { //not a valid address, signal an error? } //must be valid… } //methods } Constructors • When do they get called? – When we use the new keyword – Cannot be called explicitly like other methods – But one constructor can refer to another, using the super keyword EmailAddress myAddress = new EmailAddress(“leigh@ldodds.com”); • Constructors and inheritance – An object must ensure that its parent is properly initialised, by calling one of its constructors – Example… Constructors public class Parent { private String msg; public Parent(String message) { msg = message; } } public class Child { public Child() { super("Parent message"); } } Inheritance • What happens when we call a method? – The JVM tries to find the implementation of that method and execute the code – Starts searching with the objects class, then works upward to its parent…its parent’s parent…etc, etc. • When do we override a method? – When we want to change the implementation, either completely or partially • To completely change the implementation, just define a new version • To partially change the implementation use the super keyword to refer to the parent implementation Inheritance – Using Super • In an E-Commerce system we might have a class responsible for calculating prices e.g: public class Pricer { public float calculatePrice(Product p) { //implementation details irrelevant for example } } • The Product parameter lets the Pricer calculate the price Inheritance – Using Super • Assume we want to extend this functionality so that the calculation also includes tax (i.e. adding on VAT). • US purchases don't include tax, but UK ones do, so we can't just rewrite the original method. • Instead we create a subclass, called UKPricer that does the extra work. public class UKPricer extends Pricer { public float calculatePrice(Product p) { //this implementation will also add on VAT… } } Inheritance – Using Super • Ideally we want to reuse the code in the base class, as all we need to do is add on the extra 17.5% to the final price. • We can do better than copy-and-paste using super… public class UKPricer extends Pricer { public float calculatePrice(Product p) { //call the superclass method float withoutTax = super.calculatePrice(p); float tax = withoutTax * 17.5 / 100; return withoutTax + tax; } } Controlling Inheritance • Inheritance can be restricted using the final keyword – Applies to both methods and classes – A final class cannot be extended – A final method cannot be overridden • Inheritance can be forced by using the abstract keyword – Again applies to both methods and classes – An abstract class must be extended, cannot be used to create objects – An abstract method must be overrided by a sub-class Encapsulation • Encapulation is information hiding, but what to hide? – Everything that isn’t part of the interface (contract) of an object – This means all member variables • Encapulation is enforced in Java by the visibility modifiers – Public, protected, private, and package access – Modifiers can be applied to variables, methods and classes Visibility Modifiers Modifier Class Subclass Package Private X Protected X X X Public X X X Package X X World X Passing Parameters • Java has two ways of passing parameters – Pass by Reference – Pass by Value • Pass by Value applies to primitive types (int, float, etc) • Pass by Reference applies to objects and arrays Passing Parameters public class PassByValueTest { public static void add(int x) { x++; } public static void main(String[] args) { int x = 0; System.out.println(x); add(x); System.out.println(x); } } Passing Parameters public class PassByReferenceTest { public static void reverse(StringBuffer buffer) { buffer.reverse(); } public static void main(String[] args) { StringBuffer buffer = new StringBuffer(“Hello”); System.out.println(buffer); reverse(buffer); System.out.println(buffer); } } Upcasting • Inheritance describes an isA relationship – E.g. A MotorVehicle isA type of Vehicle • Parent and child objects share a base type – So children can be treated as if they were an instance of the parent – This is known as upcasting Upcasting • The type of the object determines its possible behaviours – Because we define them in the class • The object reference limits the behaviours we can invoke to those defined by the type of the reference – If an child class is upcast we can only invoke the base class methods – We’ve “forgotten” the real type of the object Upcasting Example 1 • Parent and Child Upcasting Example 2 • PersonViewer, need to change references • Key to understanding this is that the compiler doesn’t determine the method to call at compile time, but at runtime – dynamic binding. • This is Polymorphism Method Overloading • Already introduced overriding • Overloading is defining methods with the same name, but different parameters • Enhanced Person Viewer example Error Handling in Java • Java uses Exceptions to handle errors – Events that happen whilst running a program that disrupts the normal flow of instructions • Exceptions can range in severity – Hardware or memory problems – Program errors; Bugs, etc. • Exceptions are objects – Carry message, and state about what the program was doing when the problem was encounter – Because Exceptions are objects, you can subclass them to create your own Exceptions • Exceptions are handled by separate blocks of code (exception handlers) – Separates error handling from normal code – Better than return codes • JVM is responsible for finding an error handler for each exception – Walks backwards through the call stack – If it can’t find one, then the JVM will exit Exceptions – Terminology • Throwing an exception – Creating an Exception object, and asking the JVM to deal with it • Catching an exception – Dealing with the Exception object. – Exception handlers catch exceptions • Stack Trace – Debug information about the application state (call stack) when Exception was generated. Exceptions – Syntax • Throwing an Exception • Create a new Exception object (actually one of its subclasses) • Use the throw keyword to ask Java to deal with it throw new Exception(“error message”); Exceptions – Syntax • Identifying methods that throw exceptions • Added a throws keyword to the method definition public void readFile throws IOException, FileNotFoundException { //..code... } • A method must list all exceptions that are thrown in the method body – Otherwise encounter compilation errors Exceptions – Syntax • Throwing an Exception • Create a new Exception object (actually one of its subclasses) • Use the throw keyword to ask Java to deal with it throw new Exception(“error message”); Exceptions – Syntax • Handling exceptions • Use a try..catch block try { readFile(); } catch (FileNotFoundException fe) { //handler for file not found } catch (IOException ioe) { //handler for general I/O exceptions } Exceptions – Syntax • Alternatively use a try..catch..finally block • The finally clause is always executed and is used for critical clean-up try { readFile(); } catch (IOException ioe) { //handler for general I/O exceptions } finally { //ALWAYS run closeFile(); } Exceptions – Syntax • Viewing the stack trace Exception.printStackTrace(); • Example Exceptions – Syntax java.lang.Exception: Error message at intro2java.GenerateStackTrace.methodThree(GenerateSta ckTrace.java:18) at intro2java.GenerateStackTrace.methodTwo(GenerateStack Trace.java:13) at intro2java.GenerateStackTrace.methodOne(GenerateStack Trace.java:8) at intro2java.GenerateStackTrace.main(GenerateStackTrace .java:27) Exceptions – Syntax • Defining new types of Exceptions is easy, just sub-class an existing one. public MyException extends Exception { public MyException() { … } public MyException(String msg) { super(msg); } }