530 likes | 541 Views
Learn how to use packages and handle exceptions when using others' code in geographical information analysis. Understand the concept of classes, objects, inheritance, and interfaces. Explore the benefits of packages and how they allow you to organize and import other people's code efficiently. Get familiar with exceptions and documentation in Java programming.
E N D
Programming for Geographical Information Analysis:Core Skills Lecture 6:Using others’ code II: Packages and Exceptions
Review Classes contain variables and methods. We can turn these into objects containing data and methods. We can limit who sees these using: public :everyone can use it. private :only the code in the class can use it. protected : only inheriting code can use it. We can also set them as static – meaning we can use the methods without making an object.
Review We can turn (super)classes into subclasses. E.g. a Point class can be used to make a Land class. Subclasses invisibly pick up all the superclass code and can use the public bits. Alternatively we can use Interfaces, which are a set of promises. extends : you get everything. implements : you promise everything. If a method expects a parent type, it can take a subclass in, but can only use parent methods and variables.
This lecture Packages Exceptions Documentation
Packages Packages are groups of classes. Often you put an application in its own package. Also ‘libraries’ of useful classes. Packages allow us to use other people’s code. Saves name clashes with other people.
Namespace Packages are named after the directory they are in. Directory structures should reflect your internet address. This means we know where classes are on our machine, and who wrote them. You should build up package hierarchies. E.g… /uk/ac/leeds/mass/ /uk/ac/leeds/mass/aevans/ One package for everyone, one specifically for aevans’ use. Note that directories can’t just start with numbers. All package names and directories should be lowercase.
Naming packages The name is each directory name separated by dots: /uk/ac/leeds/mass/ uk.ac.leeds.mass A class is declared as being in a package before its class declaration: package uk.ac.leeds.mass; public class MyClass { }
Using packages If we want to use a class we haven’t written, we need to import it: package uk.ac.leeds.mass; import java.awt.Point; class MyClass { public static void main (String args[]) { Point p = new Point(); } }
Equally we can import a whole package if we want to use several Classes in it… import java.awt.*; No major overhead – just directs compiler to find the files, doesn’t put them all in your program. Alternative is to give the full classname: java.awt.Pointa = new java.awt.Point(); But this only really worthwhile if two imported packages (or your own package) have the same class name in them. Note, though, not hierarchical: import java.awt.*; Doesn’t import: import java.awt.events.*;
Compiling and running with packages How do the compiler and interpreter know where different packages are? java.lang invisibly available (e.g. java.lang.System). Other core java packages need importing, but found automatically. For others, they look in the CLASSPATH environment variable for the directories where they should start looking for the tree. This path usually contains “.”, which directs them to the current directory.
Directory trees If we want to compile a class in presidents we have to run the compiler from the src directory, with the command… javac us\gov\presidents\Obama.java or javac us\gov\presidents\*.java to compile everything. If we use a uk.ac.leeds.geog class in Obama, that will also be found because the directory tree starts the same place. To run we use the full name of the main class: java us.gov.presidents.Obama
CLASSPATH But what if the trees don’t start in the same place? We set the environmental variable ‘CLASSPATH’. Environmental variables are just variables all computers keep which store user preferences. You can tell the ‘javac’ and ‘java’ programs the classpath using… javac –classpathpath;path; File.java (in UNIX: path:path) The programs will look in any directory listed in the CLASSPATH for the start of directory trees. One path should be “.” if you want to include the present directory.
Note that if your code is unpackaged this can become quite complicated, as the classpath must include the directory your code is running from, and the root of the hierarchy. Assuming you are in the latter, you'll need this kind of thing: javac unpackaged/lazyCode/*.java java -classpath unpackaged/lazyCode/;. MyClass What you CAN'T do is this: java unpackaged/lazyCode/MyClass The JVM will just assume you're trying to run from a package.
IDEs/jar Most IDEs will put files in their own structure. They will construct the –classpath option suitably when they run. They generally also allow you to add extra libraries, and sort out the classpath for you. These are often in the form of jar files. Jar files are zip files with an extra text file. IDEs sometimes generate these from your code, as you can set them to run when double clicked in Windows etc. You can make them yourself using the jar tool: http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/jar.html
Example: Array alternatives ‘Collection’ classes in java.util that allow you to store stuff. Pros: these are like arrays, but store anything, and expand automatically. Cons: tend to be less efficient than arrays and can take up a lot of space if you’re not careful. java.util.Vector java.util.ArrayList java.util.Stack java.util.Hashtable java.util.Properties java.util.Bitset java.util.Enumeration
Objects How do they store anything? Most objects we create automatically inherit from a built in class called “java.lang.Object”. This is useful, because it allows us to make storage classes that can store anything. Their storage methods take in generic objects. This means we have to cast anything in them back to the proper class.
Vector Like an array, however, of variable size. Vector() Vector(intsize) Vector(intsize, intincrement) When full, the Vector doubles in size, or increases by the increment given.
Vector methods addElement(Object ob) insertElementAt(Object ob, intindex) Add elements in at the top or indexposition. elementAt(intindex) Gets an element at the indexposition. contains(Object ob) Checks the object is in the Vector.
Example import java.util.*; public class GIS { Vector store = new Vector(5,5); public GIS () { Point p = new Point(); store.add(p, 10); // some time later for (int i = 0; i < store.size(); i++) { Point p1 = (Point) store.elementAt(10); } } }
Review To use others’ code: Import the package/classes. Make sure you are compiling from the right location, or set the classpath.
This lecture Packages Exceptions Documentation
Problems Encapsulation demands that we don’t need to know what goes on in other’s classes. Fine and dandy, but what if our code causes their code to break horribly? FileReader f = new FileReader(someFileThatDoesn’tExist); To understand the framework for dealing with this, we need to understand Exceptions.
Exceptions When something goes wrong we don’t want the program to crash. We want some way of doing something about it. When the JVM detects an problem, it generates an Exception object at that point in the running code which represents that problem. We can catch these and do something with them. For example, if you try and add something to an array outside its size the JVM makes an object of type… ArrayIndexOutOfBoundsException
Exceptions Different problems generate different exceptions. If we build classes other people will use, we can define our own exceptions that are generated when the classes are misused. We call this ‘throwing’ an exception. If code potentially throws an exception, we must deal with the potentially thrown exception.
Catching exceptions try { Operations that throw an exception. } catch (ExceptionTypeanyName) { Operations that deal with the anyName exception. } The catch statement is the ‘Exception Handler’. The code stops acting at the problem point and jumps to the handler.
Example try { FileWriter f = new FileWriter(someFile); } catch (Exception e) { return “File not found”; } f.write(“Hello World”); Though this looks fine, there’s a scope problem.
Example FileWriter f = null; try { f = new FileWriter(someFile); } catch (Exception e) { return “File not found”; } f.write(“Hello World”); Note the separation of the variable label creation from the object creation to avoid scoping issues.
Different problem objects Exceptions are subclasses of a broader class Throwable. Two main subclass branches… Errors Exceptions Error objects are used in catastrophic system problems. Exceptions are more frequent. One of the most common subclasses of Exception is the RuntimeException.
Propagating RuntimeExceptions can be left uncaught. In this case they ‘propagate’ through the code. The code stops at the problem point and jumps to where the method was called, and the exception object gets passed to that point. This continues until the main method is reached if it’s not handled. The default handler then handles the problem. Usually the program breaks and a ‘stacktrace’ is printed. This lists all the methods the problem has propagated through.
public class RubbishMaths { public RubbishMaths() { int answer = 12/0; } } Example public class MathsExample { public static void main (String args[]) { RubbishMaths r = new RubbishMaths(); } }
Nesting catches Note that the relationship between subclasses and their parent class means that we can nest catches… try { try { // Operation } catch (RuntimeException rte) { // Do something with rte. } } catch (Exception e) { // Do something with e if it’s not a RuntimeException. }
Laddered catches try { // Operation } catch (OurExceptionoe) { // Do something with oe } catch (Exception e) { // Do something with e if it’s not of type // OurException. }
What to do with Exceptions All exceptions except RuntimeExceptions, must be caught. The usual thing in debugging is to print the error and the stack trace. e.printStackTrace(); Can also write its name to a standard error log… System.err.println(e); …but this is usually the screen anyhow. In a real program we should do something about the error so the user doesn’t get a message.
Finally If there’s something you want to happen, even if there is an error, you should put it in a ‘finally’ block under your ‘try’. Finally blocks are always executed, even if written after returns. try { // Operation. } catch (Exception e) { // Do something with e. } finally { // Do something important. }
Making Exceptions By saying that a method or an object must catch an exception, we can force programmers using our objects to prepare for problems. We can use the keyword throws to do this. If someone uses our object they must catch the thrown object or throw it again. Eventually something must deal with it, or the program won’t compile.
Creating our own Exceptions Subclass the class ‘Exception’ to make a new exception class, eg. public class OurExceptionextends Exception { In our main class, declare that a method will be throwing an object if everything goes wrong… public void name () throws OurException { At some point in the code, throw the exception… throw new OurException();
Summary Exceptions and Errors give us a chance to manage problems without the user knowing. The also allows us to force people who use our classes to deal with problems we know may arise. Exceptions can be caught and handled, or thrown out of the method for someone else to deal with. Exceptions propagate back through all the method calls and objects inside one another until they reach a suitable handler.
Review try { // whatever } catch (ExceptionType label) { // fix stuff }
This lecture Packages Exceptions Documentation
The Java Packages We’ve now seen most of the core language. Some of this is actually in the package java.lang, for example, the System and Math Classes. These you don’t have to import - java.lang is always there for you. The rest of Java is in packages that do specific stuff. We’ll spend the rest of the course looking at packages you can use.
Example import java.io.*; public class Write { public Write() { FileWriter f = null; try { f = new FileWriter (someFile); } catch (IOExceptionioe) { ioe.printStackTrace(); } f.write(“Hello World”); f.close(); } public static void main (String args[]) { new Write(); } }
Some of the main packages java.io (file reading/writing) java.awt and javax.swing (windows applications) java.applet (web applications) java.net (network communication) java.util and java.lang (bits and pieces) But, how do we know how to use these packages and classes?
Documentation We’ve seen that we should comment our code for developers, using // comments. But that relies on seeing our code. Better to supply API (Application Programming Interface) documentation that says what each class and method does. One of the great things about Java is that comments can (and should) be written so that they can be automatically turned into documents about the programs. You do this with the ‘javadoc’ program.
The Docs Each class in the core language has a webpage that lists its variables and methods, along with examples of use.
The two comment types Comments you don’t want to put in the documentation start // After this you can’t write code on the same line, just comments E.g., // End of Class. } // This bit of code calculates horror // on a rating of one to ten. Comments you want in the documentation should be associated with a block or object and be laid out thus… /** * This is a class for working out * how long we’ve been sat here. */
The documentation The documentation comes out as webpages. This means that if you can write HTML you can format your documentation. The ‘docs’ (as we pros like to call them) list the methods, what you pass to them and get out of them, any important variables, other info. They're available for all the core classes and interfaces: http://docs.oracle.com/javase/8/docs/api/
Generics Only thing you won’t recognise in the docs is the use of angle brackets, thus: Class Vector<E> add(E e) Or containsAll(Collection<?> c) addAll(Collection<? extends E> c) These mean the class stores java.lang.Object type objects, but can be forced to be more specific to reduce potential casting errors.
Example These storage objects can be parameterized. i.e. they can be given a specific type other than Object. Vector<String> v = new Vector<String>(); You can also declare these in Method parameters… void myMethod(Vector<String> v) { You can build your own parameterizable types that take in Classes of a particular type… class ClassName<T extends OptionalClass>{ private Vector<T> items = new Vector<T>(); void add(T item) { items.add(item); }T get(int index){ return items.get(index); } }
Docs Find your class or package, and click on the link.
Practical Documentation Next lecture Reading and writing files