Method-local inner classes - Inscriere

advertisement
Course 3
Lesson 1. Exceptions
1.1 Catching exceptions
The term "exception" means "exceptional condition" and is an occurrence that alters
the normal program flow. A bunch of things can lead to exceptions, including hardware
failures, resource exhaustion, and good old bugs. When an exceptional event occurs
in Java, an exception is said to be "thrown." The code that's responsible for doing
something about the exception is called an "exception handler," and it "catches" the
thrown exception. Exception handling works by transferring the execution of a program
to an appropriate exception handler when an exception occurs. For example, if you call
a method that opens a file but the file cannot be opened, execution of that method will
stop, and code that you wrote to deal with this situation will be run. Therefore, we need
a way to tell the JVM what code to execute when a certain exception happens. To do
this, we use the try and catch keywords. The try is used to define a
block of code in which exceptions may occur. This block of code is called a guarded
region (which really means "risky code goes here"). One or more catch clauses
match a specific exception (or group of exceptions—more on that later) to a block
of code that handles it. Here's how it looks in pseudocode:
1.2 Using finally
A finally block encloses code that is always executed at some point after the try block,
whether an exception was thrown or not. Even if there is a return statement in the try
block, the finally block executes right after the return statement is encountered, and
before the return executes! This is the right place to close your files, release your
network sockets, and perform any other cleanup your code requires. If the try block
executes with no exceptions, the finally block is executed immediately after the try
block completes. If there was an exception thrown, the finally block executes
immediately after the proper catch block completes. Pseudocode example:
Note: It is illegal to use a try clause without either a catch clause or a finally clause. A
try clause by itself will result in a compiler error. Any catch clauses must immediately
follow the try block. Any finally clause must immediately follow the last catch clause (or
it must immediately follow the try block if there is no catch). It is legal to omit either the
catch clause or the finally clause, but not both.
2. Defining Exceptions
Every exception is an instance of a class that has class Exception in its inheritance
hierarchy. In other words, exceptions are always some subclass of java.lang.Exception
When an exception is thrown, an object of a particular Exception subtype is instantiated
and handed to the exception handler as an argument to the catch clause. An actual
catch clause looks like this:
In this example, e is an instance of the ArrayIndexOutOfBoundsException class. As
with any other object, you can call its methods („e.printStackTrace()”);
All exception classes are subtypes of class Exception. This class derives from the class
Throwable (which derives from the class Object):
There are two subclasses that derive from Throwable: Exception and Error. Classes
that derive from Error represent unusual situations that are not caused by program
errors, and indicate things that would not normally happen during program execution,
such as the JVM running out of memory. Generally, your application won't be able to
recover from an Error, so you're not required to handle them.
Java provides many exception classes, most of which have quite descriptive names.
There are two ways to get information about an exception. The first is from the type of
the exception itself. The next is from information that you can get from the exception
object. Class Throwable (at the top of the inheritance tree for exceptions) provides its
descendants with some methods that are useful in exception handlers. One of these
is printStackTrace(). As expected, if you call an exception object's printStackTrace()
method, as in the earlier example, a stack trace from where the exception occurred will
be printed.
3. Exceptions Matching
If you have an exception hierarchy composed of a superclass exception and a number
of subtypes, and you're interested in handling one of the subtypes in a special way but
want to handle all the rest together, you need write only two catch clauses. When an
exception is thrown, Java will try to find (by looking at the available catch clauses from
the top down) a catch clause for the exception type. If it doesn't find one, it will search
for a handler for a supertype of the exception. If it does not find a catch clause that
matches a supertype for the exception, then the exception is propagated down the call
stack. This process is called exception matching.
Example:
4. Custom Exception
When creating a custom exception, you should create a subclass of Exception class:
Lesson 2. Threads
In Java, “thread” means two things:


An instance of class java.lang.Thread
A thread of execution
An instance of Thread class is just like an object, it has variables and methods, and
lives and dies in the heap.
A thread of execution is an individual process which has its own call stack. In Java
there is one thread per call stack.
The main () method which start the execution of the program, runs in one thread
called main thread.
A thread in Java begins as an instance of java.lang.Thread. You'll find methods in the
Thread class for managing threads including creating, starting, and pausing them.
Main methods of Thread class are:




start()
yield()
sleep()
run()
The action happens in the run() method. Think of the code you want to execute in a
separate thread as the job to do. In other words, you have some work that needs to be
done, say, downloading stock prices in the background while other things are
happening in the program, so what you really want is that job to be executed in its own
thread. So if the work you want done is the job, the one doing the work (actually
executing the job code) is the thread. And the job always starts from a run() method as
follows:
You always write the code that needs to be run in a separate thread in a run() method.
The run() method will call other methods, of course, but the thread of execution—the
new call stack—always begins by invoking run().
2.1 Define Threads
To define a thread, you need a place to put your run() method. This can be aquired in
two ways: extending Thread class or implementing Runnable interface.
1. Extending java.lang.Thread
2. Implementing java.lang.Runnable
Instantiating threads:
or
2.2 Thread states
A thread can be in 5 states:
1. New this is the state the thread is in after the Thread instance has been created.
2. Runnable this is the state a thread is in when it's eligible to run. A thread first
enters the runnable state when the start() method is invoked, but a thread can
also return to the runnable state after either running or coming back from a
blocked, waiting, or sleeping state. When the thread is in the runnable state, it
is considered alive.
3. Running this is the state a thread is in when the thread scheduler selects it (from
the runnable pool) to be the currently executing process.
4. Waiting/blocked/sleeping this is the state a thread is in when it's not eligible to
run
5. Dead a thread is considered dead when its run() method completes
Lesson 3. Enums
Enumerations are a special data type in Java that allows for a variable to be set to
predefined constants.The variable must equal one of the values that have been
predefined for it. Enums have been added in Java 1.5. An enumeration is useful when
there is a limited set of options that a variable can equal and it is restricted to these
known values. It can be used for days of the week (SUNDAY, MONDAY, TUESDAY,
WEDNESDAY, THURSDAY, FRIDAY and SATURDAY) , directions (NORTH, SOUTH,
EAST and WEST) etc.
Using enums can help reduce the bugs in your code. For instance, in your coffee shop
application you might want to restrict your size selections to BIG, HUGE, and
OVERWHELMING. If you let an order for a LARGE or a GRANDE slip in, it might cause
an error. Enums to the rescue. With the following simple declaration, you can
guarantee that the compiler will stop you from assigning anything to a CoffeeSize
except BIG, HUGE, or OVERWHELMING:
From then on, the only way to get a CoffeeSize will be with a statement something like
this:
The Enum can be defined within or outside the class, it is similar to a class:
Or
!! The key point to remember is that an enum that isn't enclosed in a class can be
declared with only the public or default modifier.
Declaring Constructors, Methods, and Variables in an enum
Because an enum really is a special kind of class, you can do more than just list the
enumerated constant values. You can add constructors, instance variables, methods,
and something really strange known as a constant specific class body. To understand
why you might need more in your enum, think about this scenario: imagine you want
to know the actual size, in ounces, that map to each of the three CoffeeSize constants.
For example, you want to know that BIG is 8 ounces, HUGE is 10 ounces, and
OVERWHELMING is a whopping 16 ounces. You could make some kind of a lookup
table, using some other data structure, but that would be a poor design and hard to
maintain. The simplest way is to treat your enum values (BIG, HUGE, and
OVERWHELMING), as objects that can each have their own instance variables. Then
you can assign those values at the time the enums are initialized, by passing a value
to the enum constructor.
Example:
Output: ?
!!Note: Every enum has a static method, values(), that returns an array of the enum's
values in the order they're declared.
Lesson 4. Inner classes
OOP implies that classes should be kept specialzed. a class should have code only for
the things an object of that particular type needs to do; any other behavior should be
part of another class better suited for that job. Sometimes, though, you find yourself
designing a class where you discover you need behavior that belongs in a separate ,
specialized class, but also needs to be intimately tied to the class you're designing.
Types:
 Inner classes
• Method-local inner classes
• Anonymous inner classes
• Static nested classes
Coding a “regular” inner class
After compiling :
The inner class is still, in the end, a separate class, so a separate class file is generated
for it. But the inner class file isn't accessible to you in the usual way. The only way you
can access the inner class is through a live instance of the outer class! In other words,
only at runtime when there's already an instance of the outer class to tie the inner class
instance to.
To create an instance of an inner class, you must have an instance of the outer class
to tie to the inner class. There are no exceptions to this rule: an inner class instance
can never stand alone without a direct relationship to an instance of the outer class.
Instantiating an Inner Class from Within the Outer Class
Most often, it is the outer class that creates instances of the inner class, since it is
usually the outer class wanting to use the inner instance as a helper for its own
personal use. We'll modify the MyOuter class to create an instance of MyInner:
Creating an Inner Class Object from Outside the Outer Class Instance Code
If we want to create an instance of the inner class, we must have an instance of the
outer class.
Or
Using „this” keyword



this represents a reference of the object to itself
The keyword this can be used only from within instance code. In other words,
not within static code.
The this reference is the way an object can pass a reference to itself to some
other code, as a method argument.
Output: ?
Method-local inner classes
A regular inner class is scoped inside another class's curly braces, but outside any
method code (in other words, at the same level that an instance variable is declared).
But you can also define an inner class within a method:
The preceding code declares a class, MyOuter2, with one method, doStuff(). But inside
doStuff(), another class, MyInner, is declared, and it has a method of its own,
seeOuter(). The code above is completely useless, however, because it never
instantiates the inner class! Just because you declared the class doesn't mean you
created an instance of it. So to use the inner class you must make an instance of it
somewhere within the method but below the inner class definition (or the compiler won't
be able to find the inner class). The following legal code shows how to instantiate and
use a method-local inner class:
Download