Java Prerequisite Android Marakana
Java Prerequisite Android Marakana
1. Overview of Java
Introduction to Java Development
1991 Stealth Project for consumer electronics market (later Green Project)
Netscape incorporates support for Java – Internet Explorer add support for Java
1997 JDK 1.1 JavaBeans, RMI, AWT, JDBC, servlets, JNDI, JFC, EJB
1998 Java 1.2 Reflection, Swing, Java Collections Framework, plug-in, IDL
1999 Jini, PersonalJava, Java 2 Source Code, XML support, JavaServer Pages, Java Editions (J2ME,
J2SE, J2EE)
2001 Java Connector Architecture, patterns catalog, Java Web Start 1.0, J2EE 1.3
J2SE 1.4 assert, regular expressions, exception chaining, NIO, logging, image I/O,
2002
integrated XML/XSLT, integrated Web Start, integrated JCE, JSSE, JAAS, J2EE 1.4 beta (Web
Services)
2004 J2SE 1.5 (Java 5) Generics, auto-boxing, metadata (annotations), enums, “for-each”
2
Java platform consists of Java virtual machine (JVM) responsible for hardware abstraction,
and a set of libraries that gives Java a rich foundation.
Java tools include the Java compiler as well as various other helper applications that are used
for day-to-day development (e.g. debugger).
Due to its support for strong type checking, exception handling, and memory
management, Java is immune to buffer- overruns, leaked memory, illegal data access.
Additionally, Java comes with a Security Manager that provides a sand-box execution
model.
Scalable
Thanks to its overall design, Java is scalable both in terms of performance/throughput,
and as a development environment. A single user can play a Java game on a mobile
phone, or millions of users can shop though a Java-based e-commerce enterprise
application.
High-performance/Multi-threaded
With its HotSpot Just-in-Time compiler, Java can achieve (or exceed) performance of
native applications. Java supports multi-threaded development out-of-the-box.
Dynamic
Java can load application components at run-time even if it knows nothing about them.
Each class has a run-time representation.
Distributed
Java comes with support for networking, as well as for invoking methods on remote
(distributed) objects through RMI.
Source: http://www.java.com/en/about/
first letter of each word is capitalized, but the words are joined together (i.e. no dashes or
underscores).
Note
Java source files can be encoded in UTF-8 to support internationalized characters (even
for class, method, and variable names). In most situations however, Java sources are
stored in US-ASCII character set, and internationalized strings are loaded from external
resource files.
javap -c HelloWorld
This allows compiled Java applications to run on any platform that has a Java virtual machine
written for it:
AIX
BSD
HP-UX
Linux
Mac OS X
Solaris
Windows
/**
* Main method that runs when the program is started.
* @param args command-line arguments
*/
public static void main (String[] args) {
/*
This is how you can print to STDOUT
*/
7
/*
System.out.println("I was also going to say...");
System.out.println("but I changed my mind");
*/
}
}
2.7. The main() Method
A Java application is a public Java class with a main() method.
The main() method is the entry point into the application.
The signature of the method is always:
public static void main(String[] args)
Command-line arguments are passed through the args parameter, which is an array
of Strings
Applets and servlets do not have a main() method because they are run throughtemplate
methods in the context of a framework. For example, a web container is responsible for
instantiating a servlet object. It then invokes a standard set of methods defined by
the Servlet class at appropriate points in the servlet lifecycle; for example,init() to
initialize the servlet, doGet() to handle an HTTP GET message, destroy()when the web
container is about to destroy the object, and so on. The parent class provides default
implementations of these methods, but the derived servlet class can override any of the
template methods to provide servlet-specific functionality.
3. Data Types
Primitive Data Types in Java
In contrast to a language like C, in Java the local variables do not have to be declared at the
beginning of program blocks (defined by curly braces). They can be declared when they need
to be used.
public static void main(String[] args) {
System.out.print("Number of arguments: ");
int len = args.length;
System.out.println(len);
}
Multiple variables can be declared on a singe line: int i, j, k;
Multiple variables can be initialized at the same time: i = j = k = 5;
There is an generally accepted naming convention in the Java community to start variable
names with a lower-case letter and use a so-called CamelCase (or CamelHump) notation,
where the first letter of each subsequent word is capitalized, but the words are joined
together (i.e. no dashes or underscores).
0
byte 8 bits [-128, 127]
0
short 16 bits [-32,768, 32,767]
'\u0000'
char 16 bits ['\u0000', '\uffff'] or [0, 65535]
0
int 32 bits [-2,147,483,648 to 2,147,483,647]
0
long 64 bits [-263, 263-1]
0.0
float 32 bits 32-bit IEEE 754 floating-point
0.0
double 64 bits 64-bit IEEE 754 floating-point
* The default value for uninitialized class or instance variables of this type.
Even though Java is a fully object oriented language, for performance reasons it defines eight
primitive data types. All of these types also have their respective wrapper classes (for true
OO) in the default java.lang package (which we will see later).
In addition to the eight primitive types, there is also a concept of a void type, which is only
used for a method return type (i.e. to indicate that nothing is returned).
9
Examples:
boolean bln = true; // booleans can only be 'true' or 'false'
byte b = 0x20; // using hexadecimal notation
short s = 500; // small integer
char c = 'A'; // must use single quotes to denote characters
char tab = '\t'; // other specials: \n, \r, \f, \b, \\, \', \"
int i = 1000000; // decimal notation
int j = 0x3FA0B3; // hexadecimal notation
int k = 0777; // octal notation
float f = 1.5f; // trailing 'f' distinguishes from double
long l = 2000000L; // trailing 'L' distinguishes from int
double pi = 3.141592653589793; // doubles are higher precision
double large = 1.3e100; // using the exponent notation
Note
Java has a clear separation between numerical types and booleans. They are not
interchangeable. This means that an int cannot be used in place of
a boolean expression, for example in an if statement:
int someInteger = 0;
/*
* This will not compile, because someInteger is not
* a boolean type (or a boolean expression)
*/
if (someInteger) {
// Do something
}
3.7. Strings
double d = Double.parseDouble(s);
We will examine the String API later in class.
4. Operators
Operators in Java
In Java, you need to be aware of the type of the result of a binary (two-argument) arithmetic
operator.
If either operand is of type double, the other is converted to double.
Otherwise, if either operand is of type float, the other is converted to float.
Otherwise, if either operand is of type long, the other is converted to long.
Otherwise, both operands are converted to type int.
For unary (single-argument) arithmetic operators:
If the operand is of type byte, short, or char, the result is a value of type int.
Otherwise, a unary numeric operand remains as is and is not converted.
This can result in unexpected behavior for a newcomer to Java programming. For example,
the code below results in a compilation error:
short a = 1;
short b = 2;
short c = a + b; // Compilation error
13
The reason is that the result of the addition is an int value, which cannot be stored in a
variable typed short unless you explicitly cast it, as in:
short c = (short) (a + b);
The location of the shortcut operator is only important if the operator is used in an expression
where the operand value is assigned to another variable or returned from a method.
is equivalent to:
++x;
But in an assignment:
y = x++;
If the value being shifted is of type long, the result is of type long.
Otherwise, the result is of type int.
Operation Decimal Binary Result
Result
x 71 00000000000000000000000001000111
y 5 00000000000000000000000000000101
~x -72 11111111111111111111111110111000
x & y 5 00000000000000000000000000000101
x | y 71 00000000000000000000000001000111
x ^ y 66 00000000000000000000000001000010
x >> y 2 00000000000000000000000000000010
x >>> y 2 00000000000000000000000000000010
x << y 2272 00000000000000000000100011100000
The bitwise operators may also be used with boolean values to produce a booleanresult.
However, you cannot combine boolean and integral operands in a bitwise expression.
short x = 3;
x += 4.6;
and results in x having the value 7 because it is equivalent to:
short x = 3;
x = (short) (x + 4.6);
int x = (int)
(type) Cast from one type to another
1.2;
o instanceof
instanceof Check for object type, returning boolean
String
The short-cut conditional operator (?:) (also known as the “if-then-else operator” or the
“ternary operator”) is used very often to make Java code more compact, so it is worthwhile to
get accustomed to it.
For example:
int x = 0;
int y = 5;
// Long way
int z1;
if (x == 0) {
z1 = 0;
} else {
z1 = x / y;
}
// Short-cut way
int z2 = (x == 0) ? 0 : x / y;
We’ll explore the other operators listed on this slide in more depth throughout this class.
3. *, /, %
4. +, -
5. <<, >>, >>>
6. <, <=, >, >=, instanceof
7. ==, !=
8. &
9. ^
10. |
11. &&
12. ||
13. ? :
14. =, *=, /=, +=, -=, %=, <<=, >>=, >>>=, &=, ^=, |=
Use the () operator to change precedence of operators:
x << (((((x == 0 ? 0 : (x / y)) + 5) * z) > 4) ? 3 : 7)
Other than in the most trivial situations, It is always a good practice to use () to document
your intentions, regardless of precedence rules.
For example, change:
int x = 5 - y * 2 > 0 ? y : 2 * y;
to:
int x = ((5 - (y * 2)) > 0) ? y : (2 * y);
even though both lines will assign the same value to x
Prev Next
Home | ToC
5.1. Expressions
An expression is a code fragment consisting of variables, constants, method invocations,
and operators that evaluates to a single value.
Examples:
2 + 2
a = b + c
myMethod()
Java requires one or more whitespace characters between keywords and/or identifiers. Other
whitespace characters that do not occur within quoted string literals are not considered
significant and serve only to increase the readability of code.
All variables declared within a block are known as local variables, which are stored in a
memory location known as the stack. Examples of where blocks are used include:
Method definitions
Flow control statements
Other blocks contained within a sequence of statements
The stack grows and shrinks as the program runs.
Entering a block expands the stack, storing local variables in memory.
Leaving a block shrinks the stack, flushing local variables from memory.
The scope of a local variable — that is, the context in which is visible and accessible to
your program — is limited to the block in which it is declared, and all nested blocks.
Note
Java does not allow you to declare a local variable with the same name as a local
variable already in the same scope.
public static void main(String[] args) {
int x = 1;
// A local scope where args and x are visible
while (x <= 5) {
String msg = "x is now " + x;
// A local scope where args, x, and msg are visible
System.out.println(msg);
}
// msg is no longer in scope, and has been flushed from memory
}
As previously mentioned, local variables must be initialized before they are used.
20
A local variable is visible only in the block of code (or sub blocks) where it is declared. Along
with the variable’s value, its name is also flushed as the stack shrinks, allowing the same
variable to be re-declared in another block of code.
Note
Method parameters are also considered local variables, because they too are declared
(and initialized automatically by the calling code) on the stack.
Tip
It is a good practice to limit the scope of local variables as much as possible. This
promotes variable name reuse. In the case of objects, limiting local variable scope
allows the JVM to quickly reclaim the memory occupied by objects that are no longer
in use.
5.4. The return Statement
The return statement breaks out of the entire method.
It must return a value of the type specified in the method’s signature.
It must not return a value if the method’s return value is of type void.
The value can be an expression:
public static int max(int x, int y) {
return (x > y) ? x : y;
}
public class FindNumber {
public static void main(String[] args) {
if (args.length != 1) {
System.err.println("Usage: FindNumber <num>");
return;
}
int[] numbers = {1, 3, 4, 5, 7, 5, 2, 8, 9, 6};
int findNumber = Integer.parseInt(args[0]);
System.out.println(find(numbers, findNumber));
}
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
numDays = 31;
break;
case 4:
case 6:
case 9:
case 11:
numDays = 30;
break;
case 2:
numDays = ( ( (year % 4 == 0) && !(year % 100 == 0))
|| (year % 400 == 0) )? 29 : 28;
break;
default:
23
You can omit the initialization and/or update statements from the for loop, but you
must still include the ; separator characters:
// x has been declared and initialized elsewhere
for (; x < 5; x++) System.out.println(x);
5.10. Using for to Iterate over Arrays and Collections
Java 5 also introduced an advanced for syntax known as for-each.
It is designed specifically for iterating over collections of data, whether whose
collections are arrays, or some predefined collection classes (discussed in theJava
Collections Framework module).
The for-each statement has the following syntax:
for (Type element: collectionOfType) {
// Do something with element
}
For example:
public class ForEachArguments {
public static void main(String[] args) {
for (String arg: args) {
System.out.println(arg);
}
}
}
5.11. The break Statement
In addition to defining the exit points from cases in a switch statement,
the breakstatement stops the execution of a loop:
while (someCondition) {
// Do something
if (someOtherCondition) {
break;
}
// Do something else
}
public class SearchForNumber {
public static void main (String[] args) {
int[] nums = {1, 5, 4, 43, -2, 6, 4, 9 };
int search = 4;
for (int i = 0; i < nums.length; i++) {
if (nums[i] == search) {
System.out.println("Found " + search + " at position " + i);
break;
}
}
}
}
5.12. The continue Statement
Skips one execution of a loop’s body
With continue, this:
while (someCondition) {
if (someOtherCondition) {
continue;
}
// Do something
}
if (!someOtherCondition) {
// Do something
}
}
public class SkipOddNumbers {
public static void main(String[] args) {
int[] nums = { 0, 3, 4, 5, 7, 2, 6, 9, 8, 7, 1 };
for (int i = 0; i < nums.length; i++) {
if (nums[i] % 2 != 0) {
continue;
}
System.out.println(nums[i] + " is even");
}
}
}
When the physical cars roll off the assembly line, those cars are instances (concrete
objects) of that class.
Many people can have a 2007 BMW 335i, but there is typically only one design for that
particular class of cars.
As we will see later, classification of objects is a powerful idea, especially when it comes
to inheritance — or classification hierarchy.
class Employee {
String name;
String ssn;
String emailAddress;
int yearOfBirth;
new MyClass()
e1.name = "John";
e1.ssn = "555-12-345";
e1.emailAddress = "john@company.com";
e2.name = "Tom";
e2.ssn = "456-78-901";
e2.yearOfBirth = 1974;
Name: John
SSN: 555-12-345
Year Of Birth: 0
30
Name: Tom
SSN: 456-78-901
Java variables do not contain the actual objects, they contain references to the
objects.
o The actual objects are stored in an area of memory known as the heap.
o Local variables referencing those objects are stored on the stack.
o More than one variable can hold a reference to the same object.
Figure 4. Java Memory Model
As previously mentioned, the stack is the area of memory where local variables
(including method parameters) are stored. When it comes to object variables, these are
merelyreferences (pointers) to the actual objects on the heap.
Every time an object is instantiated, a chunk of heap memory is set aside to hold the
data (state) of that object. Since objects can contain other objects, some of this data can
in fact hold references to those nested objects.
In Java:
Object references can either point to an actual object of a compatible type, or be
set to null (0 is not the same as null).
31
Employee e3 = e1;
e3 = e2;
e1 = null;
Note
The statement Employee e3 = e2; sets e3 to point to the same physical object as e2. It
does not duplicate the object. Changes to e3 are reflected in e2 and vice-versa.
Unlike some OO languages, Java does not support an explicit destructor method to
delete an object from memory.
32
e1.name = "John";
e1.ssn = "555-12-345";
e1.emailAddress = "john@company.com";
e2.name = "Tom";
e2.ssn = "456-78-901";
e2.yearOfBirth = 1974;
printEmployee(e1);
printEmployee(e2);
Name: John
SSN: 555-12-345
Year Of Birth: 0
Name: Tom
SSN: 456-78-901
class Employee {
String name;
String ssn;
String emailAddress;
int yearOfBirth;
void print() {
e1.name = "John";
e1.ssn = "555-12-345";
35
e1.emailAddress = "john@company.com";
e2.name = "Tom";
e2.ssn = "456-78-901";
e2.yearOfBirth = 1974;
e1.print();
e2.print();
Name: John
SSN: 555-12-345
Year Of Birth: 0
Name: Tom
SSN: 456-78-901
modifiers
public, private, protected, static, final, abstract, native, synchronized
returnType
36
public native void write(byte[] buffer, int offset, int length) throws IOException { ... }
We’ll discuss examples of overloading constructors and other methods later in this
module.
yearOfBirth = year;
int y = 1974;
e2.setYearOfBirth(y);
System.out.println(e.yearOfBirth);
System.out.println(e2.yearOfBirth); // prints -1
Employee.vacationDays = 15;
Now, e1.print() and e2.print() will both show the vacation days set to 15. This is
because both e1 and e2 (and any other Employee object) share the
static vacationDaysinteger field.
The field vacationDays is part of the Employee class, and this is also stored on the heap,
where it is shared by all objects of that class.
Static fields that are not protected (which we will soon learn how to do) are almost like
global variables — accessible to anyone.
Note that it is possible to access static fields through instance variables
(e.g.,e1.vacationDays = 15; will have the same effect), however this is discouraged. You
39
should always access static fields by ClassName.staticFieldName, unless you are within
the same class, in which case you can just say staticFieldName.
Static methods can access only static data and invoke other static methods.
o Often serve as helper procedures/functions
o Use when the desire is to provide a utility or access to class data only
Instance methods can access both instance and static data and methods.
o Implement behavior for individual objects
o Use when access to instance data/methods is required
An example of static method use is Java’s Math class.
o All of its functionality is provided as static methods implementing
mathematical functions (e.g., Math.sin()).
o The Math class is designed so that you don’t (and can’t) create actual Math
instances.
Static methods also are used to implement factory methods for creating objects, a
technique discussed later in this class.
class Employee {
String name;
String ssn;
String emailAddress;
int yearOfBirth;
int extraVacationDays = 0;
this.name = name;
this.ssn = ssn;
}
40
return baseVacationDays;
int getExtraVacationDays() {
return extraVacationDays;
yearOfBirth = year;
int getVacationDays() {
void print() {
}
41
if (header != null) {
System.out.println(header);
if (footer != null) {
System.out.println(footer);
print(header, null);
print(null);
e1.print("COOL EMPLOYEE");
return max;
43
You can then invoke the max() method with any of the following:
max(1);
max();
max(myValues);
6.18. Constructors
Constructors are like special methods that are called implicitly as soon as an object
is instantiated (i.e. on new ClassName()).
o Constructors have no return type (not even void).
o The constructor name must match the class name.
If you don’t define an explicit constructor, Java assumes a default constructor
o The default constructor accepts no arguments.
o The default constructor automatically invokes its base class constructor with
no arguments, as discussed later in this module.
You can provide one or more explicit constructors to:
o Simplify object initialization (one line of code to create and initialize the
object)
o Enforce the state of objects (require parameters in the constructor)
o Invoke the base class constructor with arguments, as discussed later in this
module.
Adding any explicit constructor disables the implicit (no argument) constructor.
We can add a constructor to our Employee class to allow/require that it be constructed
with a name and a social security number:
class Employee {
String name;
String ssn;
e1.emailAddress = "john@company.com";
e2.setYearOfBirth(1974);
this.ssn = ssn;
}
45
this(ssn);
this.name = name;
this(name, ssn);
this.emailAddress = emailAddress;
this(ssn);
this.yearOfBirth = yearOfBirth;
e2.name = "Tom";
6.20. Constants
“Constant” fields are defined using the final keyword, indicating their values can
be assigned only once.
o Final instance fields must be initialized by the end of object construction.
o Final static fields must be initialized by the end of class initialization.
o Final local variables must be initialized only once before they are used.
o Final method parameters are initialized on the method call.
Important
Declaring a reference variable as final means only that once initialized to refer to an
object, it can’t be changed to refer to another object. It doesnot imply that the state of the
object referenced cannot be changed.
46
Final static field can be initialized through direct assignment or by using a static
initializer.
o A static initializer consists of the keyword static followed by a block, for
example:
o static {
o }
If we declare ssn as final, we then must either assign it right away or initialize it in all
constructors. This can also be done indirectly via constructor-to-constructor calls. Once
initialized, final instance fields (e.g. ssn) can no longer be changed.
class Employee {
Employee(String ssn) {
this.ssn = ssn;
Local variables can also be set as final, to indicate that they should not be changed once
set:
e3 = e2;
6.21. Encapsulation
The principle of encapsulation is that all of an object’s data is contained and hidden
in the object and access to it restricted to methods of that class.
o Code outside of the object cannot (or at least should not) directly access
object fields.
o All access to an object’s fields takes place through its methods.
Encapsulation allows you to:
o Change the way in which the data is actually stored without affecting the
code that interacts with the object
o Validate requested changes to data
o Ensure the consistency of data — for example preventing related fields from
being changed independently, which could leave the object in an inconsistent or
invalid state
o Protect the data from unauthorized access
o Perform actions such as notifications in response to data access and
modification
More generally, encapsulation is a technique for isolating change. By hiding internal data
structures and processes and publishing only well-defined methods for accessing your
objects,
There are two additional access levels that we’ll discuss in the next module.
this.name = name;
return this.name;
}
49
return this.ssn;
Now, to set the name on an employee in EmployeeDemo.main() (i.e., from the outside),
you must call:
e2.setName("Tom");
as opposed to:
6.24. Inheritance
Inheritance allows you to define a class based on the definition of another class.
o The class it inherits from is called a base class or a parent class.
o The derived class is called a subclass or child class.
Subject to any access modifiers, which we’ll discuss later, the subclass gets access
to the fields and methods defined by the base class.
o The subclass can add its own set of fields and methods to the set it inherits
from its parent.
Inheritance simplifies modeling of real-world hierarchies through generalization of
common features.
o Common features and functionality is implemented in the base classes,
facilitating code reuse.
o Subclasses can extended, specialize, and override base class functionality.
Inheritance provides a means to create specializations of existing classes. This is referred
to as sub-typing. Each subclass provides specialized state and/or behavior in addition to
the state and behavior inherited by the parent class.
objects to know how to calculate the elapsed time between two instances. The Customer
object could then delegate the age request to the Date object in an appropriate manner.
This makes the classes loosely coupled –- so that a change to Date is unlikely to require
a change to Customer.
o In Java, a class can extend at most one base class. That is, multiple
inheritance is not supported.
o If you don’t explicitly extend a base class, the class inherits from Java’s
Object class, discussed later in this module.
Java supports multiple levels of inheritance.
o For example, Child can extend Parent, which in turn extends GrandParent,
and so on.
class A {
String a = null;
void doA() {
class B extends A {
String b = null;
void doB() {
class C extends B {
String c = null;
void doA() {
void doB() {
void doC() {
A a = new A();
B b = new B();
C c = new C();
a.a = "AAA";
b.b = "BBB";
c.b = "Whatever";
c.c = "CCC";
a.doA();
b.doB();
c.doA();
c.doB();
c.doC();
}
53
A says AAA
super(name);
}
The subclass can override its parent class definition of fields and methods,
replacing them with its own definitions and implementations.
o To successfully override the base class method definition, the subclass
method must have the same signature.
54
o If the subclass defines a method with the same name as one in the base
class but a different signature, the method is overloaded not overridden.
A subclass can explicitly invoked an ancestor class’s implementation of a method
by prefixing super. to the method call. For example:
}
super(name, ssn);
this.responsibility = responsibility;
this.responsibility = responsibility;
return this.responsibility;
}
55
super.print(header, null);
if (footer != null) {
System.out.println(footer);
Employee.setBaseVacationDays(15);
m1.setExtraVacationDays(10);
m1.print("BIG BOSS");
BIG BOSS
Name: Bob
SSN: 345-11-987
Year Of Birth: 0
Vacation Days: 25
56
Responsibility: Development
Note that the Manager class must invoke one of super’s constructors in order to be a
valid Employee. Also observe that we can invoke a method
like setExtraVacationDays() that is defined in Employee on our Manager instance m1.
6.29. Polymorphism
Polymorphism is the ability for an object of one type to be treated as though it
were another type.
In Java, inheritance provides us one kind of polymorphism.
o An object of a subclass can be treated as though it were an object of its
parent class, or any of its ancestor classes. This is also known as upcasting.
o For example, if Manager is a subclass of Employee:
o // ...
giveRaise(m);
Why is polymorphism useful? It allows us to create more generalized programs that can
be extended more easily.
Consider an online shopping application. You might need to accept multiple payment
methods, such as credit cards, debit card, direct bank debit through ACH, etc. Each
payment method might be implemented as a separate class because of differences in the
way you need to process credits, debits, etc.
If you were to handle each object type explicitly, the application would be very complex
to write. It would require if-else statements everywhere to test for the different types of
payment methods, and overloaded methods to pass different payment type objects as
arguments.
On the other hand, if you define a base class like PaymentMethod and then derive
subclasses for each type, then it doesn’t matter if you’ve instantiated a CreditCard object
or a DebitCard object, you can treat it as a PaymentMethod object.
57
Once you have upcast an object reference, you can access only the fields and
methods declared by the base class.
o Now using e you can access only the fields and methods declared by the
Employee class.
However, if you invoke a method on e that is defined in Employee but overridden
in Manager, the Manager version is executed.
o For example:
o public class A {
o }
o }
o }
o }
o // ...
obj.print();
6.31. Downcasting
// ...
Manager m = (Manager) e;
e2.setName("Tom");
Employee.setBaseVacationDays(15);
e2.setExtraVacationDays(5);
em.setExtraVacationDays(10);
m.setResponsibility("Operations");
}
59
e1.print("COOL EMPLOYEE");
em.print("BIG BOSS");
BIG BOSS
Name: Bob
SSN: 345-11-987
Year Of Birth: 0
Vacation Days: 25
Responsibility: Operations
o If a class has any abstract methods declared, the class itself must also be
declared as abstract.
For example, we could create a basic triangle class:
Now we can create concrete triangle classes based on their geometric properties. For
example:
private double a, b, c;
this.a = a;
this.b = b;
}
61
6.33. Interfaces
For example, one must have a driver’s license to drive a car, regardless for what kind of
a car that is (i.e., make, model, year, engine size, color, style, features etc.).
o double getArea();
o double getPerimeter();
62
A concrete class must then provide implementations for all methods declared by
the interface.
o Omitting any method declared by the interface, or not following the same
method signatures and return types, results in a compilation error.
An abstract class can omit implementing some or all of the methods required by
an interface.
o In that case concrete subclasses of that base class must implement the
methods.
A Java class can implement as many interfaces as needed.
o Simply provide a comma-separated list of interface names following
theimplements keyword. For example:
A Java class can extend a base class and implement one or more interfaces.
o In the declaration, provide the extends keyword and the base class name,
followed by the implements keywords and the interface name(s). For example:
this.radius = radius;
return radius;
/**
* @author sasa
* @version 1.0
*/
/**
* Constructor.
*/
this.width = width;
this.height = height;
/**
*/
return width;
/**
*/
return height;
}
65
super(side, side);
o }
}
66
When an object reference is upcast to an interface, you can invoke only those
methods declared by the interface.
The following illustrates our shapes and ShapePrinter classes:
printer.print(c);
printer.print(r);
printer.print(s);
AREA: 78.53981633974483
CIRCUMFERENCE: 31.41592653589793
AREA: 12.0
CIRCUMFERENCE: 14.0
AREA: 36.0
CIRCUMFERENCE: 24.0
// ...
Circle c = a;
if { a == b } { // false }
if { a == c } { // true }
68
One exception to this equality principle is that Java supports string interning to save
memory (and speed up testing for equality). When the intern() method is invoked on a
String, a lookup is performed on a table of interned Strings. If a String object with the
same content is already in the table, a reference to the String in the table is returned.
Otherwise, the String is added to the table and a reference to it is returned. The result is
that after interning, all Strings with the same content will point to the same object.
String interning is performed on String literals automatically during compilation. At run-
time you can invoke intern() on any String object that you want to add to the intern
pool.
o if (obj == this) {
o return true;
o }
o return false;
o }
o else {
o }
this.name = name;
this.yearOfBirth = yearOfBirth;
return this.name;
this.name = name;
return this.yearOfBirth;
return this.emailAddress;
this.emailAddress = emailAddress;
}
70
if (o == this) {
return true;
return false;
} else {
p.yearOfBirth == this.yearOfBirth;
The hashcode() method is used by many Java Collections Framework classes like
HashMap to identify objects in the collection. If you override the equals() method in
your class, you must override hashcode() as well.
Tip
7. Packaging
Packaging Java Code
Using Packaged Java Libraries
of enumerations and annotations. These Java constructs are discussed later in this class.
Tip
The package name corresponds to a directory structure on disk where the classes
are stored.
o For example, the class and interface files for org.xml.sax are located in the
directory org/xml/sax, relative to the directory where Java looks for classes (we’ll
discuss this later in this module).
To add a class or interface to a package:
o Add package myPackageName; as the first Java statement of the source file
o In your development directory, store the source file in a directory structure
corresponding to your package name.
Tip
Java does not require you to store your .java source files in in package-based
directories, but it is a common convention. However, once the source files are compiled,
the generated .class files are (and must be) stored in the package-based directories.
It’s also common to have separate, parallel directory hierarchies for
your.java and .class files reflecting the package structure. Having your source files
separate from your class files is convenient for maintaining the source code in a source
code control system without having to explicitly filter out the generated class files.
Having the class files in their own independent directory hierarchy is also useful for
generating JAR files, as discussed later in this module.
Most modern IDEs can create and manage your source and class file directory hierarchies
automatically for you.
Caution
If you don’t explicitly specify a package, your classes and interfaces end up in an
unnamed packaged, also known as the default package. Best practice is not to use the
default package for any production code.
73
java shape.ShapeDemo
74
import com.marakana.utils.MyClass;
You can then use the simple (unqualified) name of the member throughout the
rest of the source file.
o You can import all of the members of a package by importing the package
with an asterisk (*) wildcard. For example:
import com.marakana.utils.*;
You can then use the simple (unqualified) name of all the package members
throughout the rest of the source file.
Important
Using the wildcard import does not import any sub-packages or their members.
The import statements must appear after any package statement and before all
class/interface definitions in your file.
Note
The java.lang package is imported automatically into all source files.
In case there are two or more classes with the same name but defined in different
imported (or assumed) packages, then those classes must be referenced by their fully-
qualified-class-name (FQCN).
com.mycompany.calc.AdditionOperation,
com.othercompany.calculator.AdditionOperation.
import com.othercompany.calculator.AdditionOperation;
would make AdditionOperation ambiguous. Instead of importing it, you would reference it
by its FQCN.
Caution
Even though importing an entire package using the asterisk (*) notation is convenient, it
is not generally recommended — especially when multiple packages are imported. It
makes it harder to track down the classes if you do not know exactly which package they
come from. Modern IDEs help with resolving classes (as well as with organizing
imports), but you should not assume that everyone will always have an IDE handy.
Prior to Java 5, you always had to access static fields and methods qualified by
their class name.
o For example:
o Once imported, you can use them as if they were defined locally:
public
Accessible from any class
protected
Accessible from all classes in the same package or any child
classesregardless of the package
default (no Accessible only from the classes in the same package (also known
modifier) asfriendly)
private
Accessible only from within the same class (or any nested classes)
The class path should include only the root directory of a package directory hierarchy,
not the individual package directories.
cd /home/me/classes
java calc.CalculatorDemo
export CLASSPATH=/home/me/classes
77
java calc.CalculatorDemo
cp -r /home/me/classes/calc $JAVA_HOME/lib/ext/.
java calc.CalculatorDemo
It is important to notice the distinction between class path locations and package
directories. Package-based directories should never be included within the class path and
vice-versa.
A Java Archive (JAR) file packages multiple classes in a single compressed file.
o Based on the ZIP file format
o Easier and more efficient management of binaries
o Also known as Java library (.jar extension)
o Must preserve package directory structure
A JAR file can include additional meta-data in a manifest file at the
pathname META-INF/MANIFEST.MF.
o The manifest is a text file containing name: value formatted entries.
o For example, you can make an executable JAR by including a Main-
Class entry whose value is the fully-qualified name of a class containing
a main() method. You could then execute the JAR as:
JAR files internally must look like package directories. For example, a
classcom.myco.calc.CalculatorDemo would be stored within calculator.jar file just like it
would be stored on disk: com/myco/calc/CalculatorDemo.class.
78
JAR files are referenced in the CLASSPATH by their actual name, not by the name of the
directory in which they are contained.
To run com.myco.calc.CalculatorDemo you would do:
Main-Class: com.myco.calc.CalculatorDemo
You will find that the jar command has a usage similar to the Unix tar command:
Usage: jar {ctxui}[vfm0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ...
Options:
The manifest file name, the archive file name and the entry point name are
specified in the same order as the 'm', 'f' and 'e' flags.
Example 2: use an existing manifest file 'mymanifest' and archive all the
Note
80
You can use any utility with support for ZIP files (e.g. WinZip) to create, view, extract,
and manage your JAR files.
Prev Next
Home | ToC
8. JavaDoc
Documenting Java Code
It makes using third-party classes (including the Java Library itself) much easier because everything is
documented the same way.
/**
* @version 1.0
*/
/**
*/
83
/**
*/
For the full doc comments HOWTO (including a complete list of doc comment tags), please
see: http://www.oracle.com/technetwork/java/javase/documentation/index-137868.html
You can also specify one or more package names as arguments, in which
casejavadoc generates output for all classes and interfaces in those packages.
o Open the generated /path/to/output/index.html file in your browser.
Figure 6. Doc Comment Generation Example
84
Prev Next
Home | ToC
9. Exceptions
Exception Handling in Java
JVM Errors:
o OutOfMemoryError
o StackOverflowError
o LinkageError
System errors:
FileNotFoundException
IOException
SocketTimeoutException
o Programming errors:
NullPointerException
ArrayIndexOutOfBoundsException
ArithmeticException
System.out.println(divideArray(args));
String s1 = array[0];
String s2 = array[1];
int i1 = Integer.parseInt(s1);
int i2 = Integer.parseInt(s2);
return i1 / i2;
87
Note that we could have overloaded all divide*() methods (since they have different
parameters), but this way the generated stack traces are easier to follow.
All exceptions and errors extend from a common java.lang.Throwable parent class. Only
Throwable objects can be thrown and caught.
Other classes that have special meaning in Java are java.lang.Error (JVM
Error),java.lang.Exception (System Error),
and java.lang.RuntimeException(Programming Error).
implements java.io.Serializable {
public Throwable();
88
Checked exceptions give API designers the power to force programmers to deal with the
exceptions. API designers expect programmers to be able to reasonably recover from
those exceptions, even if that just means logging the exceptions and/or returning error
messages to the users.
89
Unchecked exceptions give programmers the power to ignore exceptions that they
cannot recover from, and only handle the ones they can. This leads to less clutter.
However, many programmers simply ignore unchecked exceptions, because they are by
default un-recoverable. Turning all exceptions into the unchecked type would likely lead
to poor overall error handling.
at ExceptionDemo.divideInts(ExceptionDemo.java:21)
at ExceptionDemo.divideStrings(ExceptionDemo.java:17)
at ExceptionDemo.divideArray(ExceptionDemo.java:10)
at ExceptionDemo.main(ExceptionDemo.java:4)
Looking at the list bottom-up, we see the methods that are being called from main() all
the way up to the one that resulted in the exception condition. Next to each method is
the line number where that method calls into the next method, or in the case of the last
one, throws the exception.
divideSafely(args);
try {
System.out.println(divideArray(array));
} catch (ArrayIndexOutOfBoundsException e) {
} catch (NumberFormatException e) {
} catch (ArithmeticException e) {
}
91
String s1 = array[0];
String s2 = array[1];
int i1 = Integer.parseInt(s1);
int i2 = Integer.parseInt(s2);
return i1 / i2;
try {
// Code bock
}
}
}
92
// ...
finally {
o Both catch and finally blocks are optional, but at least one must follow
a try.
o The try-catch-finally structure can be nested in try, catch,
or finallyblocks.
o The finally block is used to clean up resources, particularly in the context
of I/O.
o If you omit the catch block, the finally block is executed before the
exception is propagated.
Exceptions can be caught at any level.
If they are not caught, they are said to propagate to the next method.
divideSafely(args);
try {
System.out.println(divideArray(array));
} catch (ArrayIndexOutOfBoundsException e) {
String s1 = array[0];
String s2 = array[1];
try {
int i1 = Integer.parseInt(s1);
int i2 = Integer.parseInt(s2);
} catch (NumberFormatException e) {
return 0;
try {
return i1 / i2;
} catch (ArithmeticException e) {
return 0;
catch (RuntimeException e) {
94
Caution
Be careful about being too generic in the types of exceptions you catch. You might end
up catching an exception you didn’t know would be thrown and end up “hiding”
programming errors you weren’t aware of.
divideSafely(args);
try {
System.out.println(divideArray(array));
} catch (ArrayIndexOutOfBoundsException e) {
} catch (RuntimeException e) {
String s1 = array[0];
String s2 = array[1];
95
int i1 = Integer.parseInt(s1);
int i2 = Integer.parseInt(s2);
return i1 / i2;
IndexOutOfBoundsException
Index parameter is out of range
UnsupportedOperationException
Object does not support the method
For example:
/**
* Circle shape
*/
/**
* Constructor.
*/
this.radius = radius;
extends Exception
Unchecked
extends RuntimeException
o Define constructor(s) that call into super’s constructor(s), taking message
and/or cause parameters.
o Consider adding custom fields, accessors, and mutators to allow
programmatic introspection of a thrown exception, rather than requiring code to
parse an error message.
/**
* @author me
* @version 1.0
*/
/**
* Constructor.
*/
this.available = available;
this.required = required;
/**
*/
return available;
/**
*/
return required;
/**
*/
try {
try {
String sql
+ id + "'";
try {
try {
} finally {
result.close();
} finally {
stmt.close();
} finally {
con.close();
} catch (SQLException e) {
Observe that the getCustomer() method signature does not say anything about
customers being retrieved from a SQL-based RDBMS. This allows us to provide an
alternative implementation, say based on a LDAP directory server or XML files.
100
int i = 5;
list.add(new Integer(i));
int j = intObj.intValue();
Note
Integer j = 5 + 10;
101
listOfLongs.add(123123123L);
Warning
This auto-boxing feature can lead to legal but very inefficient code. For example, in the
following loop, the index variable is accidentally declared as a Long rather than a long,
leading to the creation of a billion extraneous objects compared to using the primitive
type:
String
o Automatically created with double quotes
o Pooled (interned) to save memory
o Immutable — once created cannot change
o Concatenated using the expensive + operator
o Many methods for string manipulation/searching
StringBuilder and StringBuffer
o Mutable — can quickly grow and shrink as needed
o Few methods modifying the buffer: append(), insert(), delete(), replace()
o Use toString() if you need to get a String representation of the object’s
content
o StringBuffer is synchronized for thread-safe access in multithreaded
applications
o Use StringBuilder for better performance unless you plan to access the
object from multiple threads
In a single-threaded context (as is generally the case), StringBuilder is faster than
StringBuffer. But both are 1000+ times faster than repeated String concatenation.
String s = "";
s += ".";
System.out.println(time);
sb.append(".");
sb.trimToSize();
System.out.println(time);
The Math class contains static methods implementing math functions, such as:
o Trigonometry: sin(), cos(), tan(), etc.
o Rounding: round(), floor(), ceil(), rint()
103
The System class provides access to your system and the JVM, including:
o A context for stdin, stdout, stderr streams
o Environmental variables and JVM properties
o System time in milliseconds or nanoseconds
o Loading external [native] libraries
o Terminating the JVM
o Efficient array copying
The java.lang.System class gives access to the JVM system, although it is used most
often for printing to stdout:
System.out.println("Hello World");
Environmental variables are system dependent (configured by the shell), so they are
generally not portable across platforms.
104
Prev Next
Home | ToC
11. Input/Output
Exploring the Java I/O Library
A File object provides methods for querying and manipulating the file system.
o Methods that query the file system
include: canRead(), canWrite(), exists(),isDirectory(), isFile(), isHidden(), ge
tAbsolutePath(), lastModified(),length(), listFiles(), listRoots()
o Methods that modify the file system
include: createNewFile(), mkdir(),renameTo(), delete(), deleteOnExit(), setRead
Only(), setLastModified()
105
package io;
import java.io.File;
if (args.length == 0) {
remove(new File(args[i]));
if (!file.exists()) {
+ file.getAbsolutePath());
+ file.getAbsolutePath());
else if (!file.delete()) {
A set of four abstract base classes provide the core functionality for most of these
classes:
o Byte-oriented (binary) data: InputStream and OutputStream
o Character-oriented data: Reader and Writer
The methods for reading data from an InputStream and a Reader are very similar,
as are the methods for writing data to an OutputStream or Writer.
Many of the other I/O classes follow the Decorator Pattern, attaching additional
responsibilities to an object dynamically.
o Most of these classes have constructors that take a Reader (or Writer, or
InputStream, or OutputSteam) object as an argument, and return an object
that’s another Reader (or Writer, or InputStream, or OutputSteam).
o Each class just provides some additional functionality (such as buffering,
compression, etc.) on top of the basic I/O functionality as defined by the abstract
base class.
The key to the Decorator Pattern (and the I/O class hierarchy) is polymorphism. A
FileReader “is-a” Reader, a BufferedReader “is-a” Reader, a LineNumberReader “is-a”
Reader, etc.
int b = 0;
System.out.write(b);
107
try {
try {
int len = 0;
System.out.write(buffer, 0, len);
} finally {
fis.close();
} catch (FileNotFoundException e) {
} catch (IOException e) {
try {
try {
int ch;
System.out.print((char) ch);
System.out.flush();
} finally {
reader.close();
} catch (FileNotFoundException e) {
} catch (IOException e) {
try {
try {
int ch;
writer.write(ch);
writer.flush();
} finally {
reader.close();
} catch (FileNotFoundException e) {
} catch (IOException e) {
The PrintWriter and PrintStream classes are designed to simplify common text
output tasks.
o The print() method is overloaded to print a String representation of all Java
primitive types, and to automatically print the toString() representation of all
Objects.
o The println() method works in the same way as print(), but add a
platform-specific line terminator.
o The format() method and its alias the printf() method print a formatted
representation of one or more Objects as specified by a format String. The
operation is based on the C language printf() function.
o The class methods never throw an IOException. Instead, exceptional
situations merely set an internal flag that can be tested via
the checkError() method.
Note
The System.out and System.err objects are instances of PrintStream.
The PrintWriter and PrintStream constructors are overloaded. In addition to
versions that accept an existing InputStream or Writer to “wrap”, there are versions
that accept a File object or a String representing a file path to specify an output file.
111
new InputStreamReader(System.in) );
The following shows a simple example of line-oriented input from the terminal:
package com.marakana.demo;
import java.io.*;
/*
112
*/
new InputStreamReader(System.in) );
try {
} catch (IOException e) {
e.printStackTrace();
Many other pre-defined I/O “filter” classes are available in Java, including:
o Buffering (BufferedReader/Writer/InputStream/OutputStream)
o Checksum handling (java.util.zip.CheckedInputStream/OutputStream)
o Compression (java.util.zip.GZIPInputStream/OutputStream and
java.util.zip.ZipInputStream/OutputStream)
You can define your own custom I/O filters by subclassing
FilterReader/Writer/InputStream/OutputStream.
package io;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
113
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.GZIPOutputStream;
/**
* This program compresses one or more input files using gzip compression
* algorithm. Source files are deleted and compressed files get .gz extension.
*/
if (args.length == 0) {
gzip(new File(args[i]));
if (!file.exists()) {
} else if (file.isDirectory()) {
+ file.getAbsolutePath());
} else {
try {
114
try {
try {
int len = 0;
out.write(buffer, 0, len);
} finally {
out.close();
} finally {
in.close();
} catch (IOException e) {
if (outFile.exists()) {
outFile.delete();
}
115
Java supports the automatic conversion of objects to and from byte streams.
o Including complete object graphs.
For an object (class) to be serializable, the class must:
o Implement the java.io.Serializable interface, a marker interface with no
required methods
o Contain instance fields that are serializable — primitives or other Serializable
types — except for any fields marked as transient
o Have a no-argument constructor
o (Optional but recommended) Implement a static final long field
namedserialVersionUID as a “version number” to identify changes to the class
implementation that are incompatible with serialized objects of previous versions
of the class.
You can then serialize and deserialize objects with the following filter classes:
o ObjectOutputStream — Serialize an object to an underlying OutputStream
with thewriteObject() method.
o ObjectInputStream — Deserialize an object from an underlying InputStream
with the readObject() method.
A simple example, assuming that Employee implements java.io.Serializable:
import java.io.ObjectOutputStream;
import java.io.IOException;
import java.io.FileOutputStream;
if (args.length != 6) {
return;
e.setYearOfBirth(Integer.parseInt(args[3]));
e.setExtraVacationDays(Integer.parseInt(args[4]));
116
new FileOutputStream(args[5]));
try {
oos.writeObject(e);
} finally {
oos.close();
import java.io.FileInputStream;
import java.io.ObjectInputStream;
if (args.length != 1) {
return;
new FileInputStream(args[0]));
try {
e.print();
} finally {
ois.close();
}
117
Note
Object serialization support can become quite complex, especially if a class supports
internal references to I/O streams, databases, etc. A full discussion is beyond the scope of
this class.
12. java.net
Exploring Java Networking Library
12.1. java.net.InetAddress
Represents an IP address
o Supports IPv4 and IPv6
o Supports unicast and multicast
Hostname resolution (DNS lookup)
o Supports caching (positive and negative)
java.net.NetworkInterface
o Represents system network interface
o Lookup local listening InetAddresses
import java.net.*;
import java.util.*;
nis.hasMoreElements();) {
System.out.println(ni.getDisplayName());
ias.hasMoreElements();) {
System.out.println("\t" + ia.getHostAddress());
118
try {
InetAddress ia = InetAddress.getByName(args[0]);
System.out.print(ia.getHostName());
} catch (UnknownHostException e) {
12.2. URL/Connections
java.net.URL
o Uniform Resource Locator
o Elements: scheme/protocol, host, port, authority, userInfo, path, query,
fragment/ref
o Factory for URLConnections
java.net.URLConnection
o Communication link between the app and the URL
o Built-in support for HTTP and JAR connections
o Read/write from/to connection using I/O streams
import java.io.*;
import java.net.*;
if (args.length != 1) {
return;
connection.connect();
InputStream in = connection.getInputStream();
try {
int nread = 0;
System.out.write(buf, 0, nread);
System.out.flush();
} finally {
in.close();
import java.io.InputStream;
120
import java.io.OutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.ServerSocket;
System.out.println("(Control-C to terminate)");
while(true) {
try {
InputStream in = clientSocket.getInputStream();
int b;
out.write(b);
out.flush();
} finally {
clientSocket.close();
Note
UDP sockets are supported through java.net.DatagramSocket.
121
Iterator i = c.iterator();
while (i.hasNext()) {
123
Object o = i.next();
System.out.println(o);
System.out.println(i.next());
for (Object o : c) {
System.out.println(o);
Especially if you’re dynamically resizing a collection of object, favor using a List over a
Java array.
package util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* or the lines from STDIN, sorts them, and writes the result to STDOUT.
*/
125
if (args.length > 0) {
Arrays.sort(args);
System.out.println(args[i]);
} else {
System.in));
lines.add(line);
Collections.sort(lines);
System.out.println(i.next());
The Set interface adds no methods beyond those of the Collection interface.
o The Set interface simply enforces behavior of the collection.
The java.util.SortedSet interface extends Set so that elements are automatically
ordered.
o A SortedSet Iterator traverses the Set in order.
o A SortedSet also adds the methods first(), last(), headSet(), tailSet(),
and subSet()
package util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
*/
Set unique = new HashSet(); // replace with TreeSet to get them sorted
if (args.length > 0) {
unique.addAll(Arrays.asList(args));
} else {
System.in));
unique.add(line);
System.out.println(i.next());
package util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
130
*/
if (args.length > 0) {
countWord(wordMap, args[i]);
} else {
getWordFrequency(System.in, wordMap);
throws IOException {
int ch = -1;
if (Character.isWhitespace(ch)) {
if (word.length() > 0) {
countWord(wordMap, word.toString());
} else {
word.append((char) ch);
if (word.length() > 0) {
countWord(wordMap, word.toString());
if (count == null) {
} else {
wordMap.put(word, count);
The Java Collections Framework was designed to handle objects of any type.
o In Java 1.4 and earlier they used Object as the type for any object added to
the collection.
o You had to explicitly cast the objects to the desired type when you used
them or else you would get compile-time errors.
o Worse yet, if you were dealing with a collection of objects, say of type Dog,
and then accidentally added an object of an incompatible type, say a Cat, your
code could eventually try to cast the object to the incompatible type, resulting in
a runtime exception.
Java arrays actually have a similar polymorphism problem that can result in runtime
exceptions:
package com.markana.demo;
System.out.println("I'm an animal.");
@Override
System.out.println("woof");
@Override
System.out.println("I'm a Dog.");
@Override
System.out.println("meow");
@Override
System.out.println("I'm a Cat.");
package com.markana.demo;
134
*/
* ArrayStoreException.
*/
Employee e = emps.get(0);
o Object type errors are now detected at compile time, rather than throwing
casting exceptions at runtime.
What can be confusing about generics when you start to use them is that
collections of a type are not polymorphic on the type.
o That is, you can not assign a List<String> to a reference variable of
typeList<Object> (and by extension, pass a List<String> as an argument to a
method whose parameter is type List<Object>); it results in a compiler error.
o Why? If allowed, we could then add objects of an incompatible type to the
collection through the more “generic” typed reference variable.
So if you define a printCollection() to accept a parameter typed List<Person>,
you can pass only List<Person> collections as arguments.
o Even if Employee is a subclass of Person, a List<Employee> can’t be assigned
to a List<Person>.
Here’s an illustration of how type parameters are not polymorphic for collections:
package com.markana.demo;
import java.util.*;
package com.markana.demo;
import java.util.*;
/*
*/
o The list might contain all Person objects… or Employee objects, or Customer
objects, or objects of some other subclass of Person. You’d be in trouble if you
could add a Customer to a list of Employees.
Another type wildcard qualifier is super.
o List<? super Employee> means a List of objects of type Employee or some
supertype of Employee.
o So the type is “unknown,” but in this case it could be Employee, Person, or
Object.
o Because you don’t know which, for “read” access the best you can do is use
only Object methods.
o But you can add new Employee objects to the list, because polymorphism
allows the Employee to be treated as a Person or Object as well.
Both extends and super can be combined with the wildcard type.
package com.markana.demo;
import java.util.*;
/*
* of Animal.
*/
/*
*/
o.identify();
/*
*/
c.add(p);
o In this example, the object p and the objects in the collection c must all be
the same type.
You can use type wildcards, extends, and super in generic method definitions as
well.
package com.markana.demo;
import java.util.*;
c.add(obj);
c.add(obj);
// And now let's try using our generic methods to add objects
o.identify();
14. Threading
14.1. Runnable And Thread
System.out.println("Creating threads");
}
142
System.out.println("Starting threads");
System.out.println("Done");
Thread.yield();
int currentCount;
synchronized(this.counter) {
currentCount = this.counter.getCount();
currentCount++;
this.counter.setCount(currentCount);
System.out.println(Thread.currentThread().getName()
A better approach would be to add a synchronized count method on the Counter class so
that Runners would not have to worry about synchronization.
return ++this.count;
144
Element next;
if (this.first == null) {
} else {
this.curSize++;
this.notifyAll();
145
Object o = this.first.value;
this.first = this.first.next;
this.curSize--;
this.notifyAll();
return o;
while(true) {
//
Note
With no access to a standard thread-pool library, we end up creating Threads on demand. Works
well for very simple cases, but does not scale and it is not resource-efficient.
while(true) {
pool.execute(new Handler(ss.accept())); //
//
r.run();
}
148
}
new Thread(r).start();
}
...
...
long t = System.currentTimeMillis();
try {
// handle request
this.result = System.currentTimeMillis() - t;
} catch (Exception e) {
this.e = e;
} finally {
this.notifyAll();
this.wait();
}
150
if (e != null) {
throw e;
} else {
return result;
Java 5 provides a new interface to define a runnable task that returns a result and
may throw an exception:
long t = System.currentTimeMillis(); //
return System.currentTimeMillis() - t;
return map.get(key);
V value = null;
try {
this.wait();
catch (InterruptedException e) {
152
break;
return value;
map.put(key, value);
this.notifyAll();
lock.readLock().lock();
try {
return map.get(key);
} finally {
lock.readLock().unlock();
}
153
if (value == null) {
lock.writeLock().lock();
try {
vAdded.await();
...
} finally {
lock.writeLock().unlock();
return value;
lock.writeLock().lock();
try {
map.put(key, value);
vAdded.signalAll();
} finally {
lock.writeLock().unlock();
}
154
if (lock.tryLock()) {
try {
} finally {
lock.unlock();
} else {
try {
lock.lockInterruptibly();
try {
} finally {
lock.unlock();
} catch (InterruptedException e) {
try {
if (lock.tryLock(10, TimeUnit.SECONDS)) {
try {
} finally {
lock.unlock();
} catch (InterruptedException e) {
...
}
156
...
...
Most other Date methods are deprecated. They supported time and date manipulation,
parsing, and formatting, but they have been superseded by newer classes.
TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
package util;
158
import java.util.Date;
import java.util.Calendar;
import java.util.TimeZone;
System.out.println(date);
Calendar c = Calendar.getInstance();
System.out.println("WeekDay:" + c.get(Calendar.DAY_OF_WEEK));
}
159
o For example, to get a date/time formatter with the default formatting style
for the default locale:
DateFormat df = DateFormat.getDateTimeInstance();
o DateFormat df = DateFormat.getDateInstance(
DateFormat.LONG, Locale.FRANCE);
package com.marakana.demo;
import java.util.Date;
import java.text.*;
DateFormat df;
df = DateFormat.getDateTimeInstance();
System.out.println(df.format(now));
df = DateFormat.getInstance();
System.out.println(df.format(now));
df = DateFormat.getDateInstance(DateFormat.MEDIUM);
System.out.println(df.format(now));
df = DateFormat.getTimeInstance(DateFormat.LONG);
System.out.println(df.format(now));
try {
df = DateFormat.getDateInstance(DateFormat.MEDIUM);
System.out.println(df.format(birthday));
} catch (ParseException e) {
e.printStackTrace();
}
161
o For example, to get a number formatter with the default formatting style for
the default locale:
NumberFormat nf = NumberFormat.getInstance();
o NumberFormat nf
= NumberFormat.getCurrencyInstance(Locale.JAPAN);
package com.marakana.demo;
import java.text.*;
import java.util.Locale;
162
NumberFormat form;
System.out.println("FORMAT");
if (l.getCountry().length() == 0) {
System.out.print(l.getDisplayName());
switch (j) {
case 0:
case 1:
case 2:
default:
}
163
try {
} catch (ParseException e) {}
this.color = color;
this.figure = figure;
o Enum definitions are loaded at runtime, so enums can evolve and change
without breaking existing code.
o You can switch on enum values.
o They can have fields and methods to add state and behavior.
o They have a default toString() that returns the enum value as a String —
but you can override it if you want!
o The enum type has a default values() method that returns an array of all
the enum values. For example:
Use enums any time you need a fixed set of constants. For example: choices on a menu,
rounding modes, command line flags, etc.
public static enum Figure {KING, QUEEN, ROOK, BISHOP, KNIGHT, PAWN};
this.color = color;
this.figure = figure;
return this.figure;
}
166
return this.color;
System.out.println(d);
EnumSet.of(Style.BOLD, Style.ITALIC)
15.9. Annotations
o They have no direct effect on the operation of the code they annotate.
Annotations have a number of uses, including:
Information for the compiler
Annotations can be used by the compiler to detect errors or suppress warnings.
Compile-time and deployment-time processing
Software tools can process annotation information to generate code, XML files, etc.
Runtime processing
Libraries and frameworks can use annotations conditionally process classes and
methods, and to inject objects into annotated classes and methods.
The Java annotation facility consists of:
Syntax for declaring annotation types
Syntax for annotating declarations
APIs for reading annotations reflectively
Class file representation for annotations
Annotation Processing Tool (apt)
@Unfinished(
date = "5/11/2001"
)
class HeartOfGold { }
@SuppressWarnings(value = "unchecked")
void myMethod() { }
If there is just one element named "value", then the name may be omitted:
@SuppressWarnings("unchecked")
168
void myMethod() { }
@Override
void myMethod() { }
@SuppressWarnings({"unchecked","deprecation"})
o Code reusability
Reuse existing/legacy code with Java (mostly C/C++)
o Performance
Native code used to be up to 20 times faster than Java, when running
in interpreted mode
Modern JIT compilers (HotSpot) make this a moot point
o Allow Java to tap into low level O/S, H/W routines
JNI code is not portable!
Note
JNI can also be used to invoke Java code from within natively-written applications - such
as those written in C/C++.
In fact, the java command-line utility is an example of one such application, that
launches Java code in a Java Virtual Machine.
package com.marakana.jniexamples;
170
static { System.loadLibrary("HelloImpl"); } //
hello.sayHi(args[0], Integer.parseInt(args[1])); //
The method sayHi will be implemented in C/C++ in separate file(s), which will be compiled into a
library.
The library filename will be called libHelloImpl.so (on Unix), HelloImpl.dll (on Windows)
and libHelloImpl.jnilib (Mac OSX), but when loaded in Java, the library has to be loaded
as HelloImpl.
...
#include <jni.h>
...
...
#include <stdio.h>
#include "com_marakana_jniexamples_Hello.h"
jint i;
jboolean iscopy;
-I/usr/local/jdk1.6.0_03/include \
-I/usr/local/jdk1.6.0_03/include/linux com_marakana_jniexamples_Hello.c
On Mac OSX :
-I/System/Library/Frameworks/JavaVM.framework/Headers com_marakana_jniexamples_Hello.c
export LD_LIBRARY_PATH=.
Finally, run your application in the directory where your compiled classes are stored
("classes" for example):
Hello Student
Hello Student
Hello Student
Hello Student
Hello Student
Note
Common mistakes resulting in java.lang.UnsatisfiedLinkErrorusually come from
incorrect naming of the shared library (O/S-dependent), the library not being in the
search path, or wrong library being loaded by Java code.
o Mapping for objects is more complex. Here we will focus only on strings and
arrays but before we dig into that let us talk about the native methods
arguments
JNI passes objects to native methods as opaque references
Opaque references are C pointer types that refer to internal data structures in the
JVM
Let us consider the following Java class:
package com.marakana.jniexamples;
static { System.loadLibrary("helloname"); }
hello.sayHelloName(name);
174
}
...
#include <jni.h>
...
...
A .c file like this one would not produce the expected result:
#include <stdio.h>
#include "com_marakana_jniexamples_HelloName.h"
If you remember the previous example, we had a native method where we wanted
to display "Hello name":
#include <stdio.h>
#include "com_marakana_jniexamples_HelloName.h"
This example would not work since the jstring type represents strings in the Java virtual
machine. This is different from the C string type (char *)
Here is what you would do, using UTF-8 string for instance:
176
#include <stdio.h>
#include "com_marakana_jniexamples_HelloName.h"
This returns a pointer to an array of bytes representing the string in UTF-8 encoding (without
making a copy)
When we are not making a copy of the string, calling ReleaseStringUTFCharsprevents the
memory area used by the string to stay "pinned". If the data was copied, we need to
call ReleaseStringUTFChars to free the memory which is not used anymore
Here is another example where we would construct and return
a java.lang.Stringinstance:
#include <stdio.h>
#include "com_marakana_jniexamples_GetName.h"
char buffer[20];
scanf("%s", buffer);
}
177
package com.marakana.jniexamples;
//Array declaration
arr[i] = i;
}
}
static {
178
System.loadLibrary("arrayreader");
}
This method will return the sum of each element in the array
After running javah, create your .c file that would look like this:
#include <stdio.h>
#include "com_marakana_jniexamples_ArrayReader.h"
jint *native_array;
jint i, result = 0;
if (native_array == NULL) {
return 0;
}
result += native_array[i];
}
return result;
We could also have used GetIntArrayRegion since we exactly know the size of the array
179
if (class != NULL) {
}
(*env)->DeleteLocalRef(env, class); //
Throw the exception using the class reference we got before and the message for the exception
ThrowExceptionByClassName(env,"java/lang/IllegalArgumentException","This exception is
thrown from C code");
For the rest, it differs depending on whether we are accessing a field or a method
From this Java class, we will see how to call its methods or access its properties in
the native code:
package com.marakana.jniexamples;
this.name = name;
}
//Native method
instanceAccessor.setName("Jack");
instanceAccessor.propertyAccess(); //
instanceAccessor.methodAccess(); //
}
//Load library
static {
System.loadLibrary("instanceaccess");
}
Name property that we are going to modify along this code execution
This method will be called by the native code to modify the name property
This native method modifies the name property by directly accessing the property
This native method modifies the name property by calling the Java methodsetName()
#include <stdio.h>
#include "com_marakana_jniexamples_InstanceAccess.h"
jfieldID fieldId;
jstring jstr;
if (fieldId == NULL) {
}
/* Getting a jstring */
if (cString == NULL) {
}
if (jstr == NULL) {
183
}
}
jstring jstr;
if (methodId == NULL) {
}
Gets a field Id from the object class, specifying the property to get and the internal type. you
can find information on the jni type
there:http://download.oracle.com/javase/6/docs/technotes/guides/jni/spec/types.html
This will return the value of the property in the native type: here a jstring
This creates a new java.lang.String that is going be use to change the value of the property
Gets a method id from the object class previously obtained, specifying the name of the method
along with its signature. There is a very useful java tool that you can use to get the signature of
a method: javap -s -p ClassName for instancejavap -s -p InstanceAccess
This creates a new java.lang.String that we are going to use as an argument when calling the
java method from native code
Calling CallVoidMethod since the Java method return type is void and we are passing the
previously created jstring as a parameter
17. java.sql
Java Database Connectivity API (JDBC)
Type One
o JDBC-ODBC Bridge plus ODBC driver
o Depends on support for ODBC
o Not portable
Type Two
o JNI/Native Java driver
o Requires DB native library
o Not portable
Type Three
o Pure Java to Middleware driver
o Depends on Middleware server
o Driver is portable, but the middleware server might not be
Type Four
o Pure Java Driver
o Talks directly to the RDBMS
o Portable
17.3. Getting a JDBC Connection
Make sure JDBC driver is in CLASSPATH
Register JDBC driver
o Class.forName("my.sql.Driver");
o Run with -Djdbc.drivers=my.sql.Driver
o System.setProperty("jdbc.drivers", "my.sql.Driver");
186
For example, to run your application against a MySQL RDBMS, you would run JVM with
(all on one line):
Note that you can also pass the username and password at run time:
DataSource ds = (DataSource)ctx.lookup(”java:comp/env/jdbc/MyDS");
try {
try {
try {
} finally {
result.close();
} finally {
stmt.close();
} finally {
con.close();
try {
try {
stmt.executeUpdate();
} finally {
stmt.close();
188
} finally {
con.close();
try {
try {
try {
while (resultSet.next()) {
System.out.print(resultSet.getString("CustomerID"));
System.out.print(", ");
System.out.print(resultSet.getString("CompanyName"));
System.out.print(", ");
System.out.print(resultSet.getString("ContactName"));
System.out.println();
}
189
} finally {
resultSet.close();
} finally {
stmt.close();
} finally {
con.close();
From JavaDoc: In general, using the column index is more efficient. For maximum
portability, result set columns within each row should be read in left-to-right order, and
each column should be read only once.
try {
try {
stmt.setString(1, customerID);
try {
if (resultSet.next()) {
190
System.out.print(metaData.getColumnName(c));
System.out.print(": ");
System.out.println(resultSet.getObject(c));
} finally {
} finally {
} finally {
17.7. Updates
Update actions (INSERT, UPDATE, DELETE) are triggered through
try {
try {
stmt.setString(1, "John");
stmt.setString(2, "555-12-345");
stmt.setString(3, "john@company.com");
stmt.setInt(4, 1974);
stmt.setInt(5, 7);
if (result == 0) {
} else {
System.out.println("Employee added.");
} finally {
} finally {
Toolkits and libraries for XML processing fall into two categories
o Event-driven processors
o Object model construction processors
A parser reads the data and notifies specialized handlers (call-backs) that
undertake some actions when different parts of the XML document are encountered:
o Start/end of document
o Start/end of element
o Text data
o Processing instruction, comment, etc.
SAX (Simple API for XML) – a standard event-driven XML API
For example, consider the following XML document:
<?xml version="1.0"?>
<dvd>
<title>
Matrix, The
</title>
</dvd>
parser.parse(in, myDvdHandler);
@Override
this.currentText = null;
}
194
@Override
throws SAXException {
@Override
if (qName.equals("title")) {
this.dvd.setTitle(this.currentText.toString().trim());
Based on the idea of parsing the whole document and constructing an object
representation of it in memory
o A series of parent-child nodes of different types
DOM (Document Object Model)
o Standard, language-independent specification written in OMG’s IDL for the
constructed object model
Also known as the tree-based approach
For example, consider the following XML document:
<?xml version="1.0"?>
<dvd>
<title>
Matrix, The
195
</title>
</dvd>
Document
if (name.equals(node.getNodeName())) {
return node;
} else {
n = n.getNextSibling()) {
if (found != null) {
return found;
return null;
...
if (dvdNode != null) {
if (titleNode != null) {
dvd.setTitle(titleNode.getTextContent());
...
Many of the design patterns in use today and described here originate from the
famousGang of Four book: "Design Patterns: Elements of Reusable Object-Oriented
Software" by Eric Gamma, Richard Helm, Ralph Johnson, and John Vlissides (Addison-
Wesley Publishing Co., 1995; ISBN: 0201633612)
19.2. Singleton
return instance;
// doing something
MySingleton.getInstance().doX();
int b = MySingleton.getInstance().getB();
// do something with b
}
199
19.5. Adapter
Convert the interface of a class into another interface clients expect
Allow classes to work together despite their incompatible interfaces
Typically used in development to glue components together, especially if 3rd party
libraries are used
Also known as wrapper
/**
202
*/
this.enumeration = enumeration;
return this.enumeration.hasMoreElements();
return this.enumeration.nextElement();
/**
* Not supported.
*/
19.6. Composite
Compose objects into three structures to represent part-whole hierarchies
203
this.executables.add(executable);
this.executables.remove(executable);
204
((Executable) i.next()).execute();
19.7. Decorator
Attach additional responsibilities to an object dynamically and transparently (run-
time)
An alternative to sub classing (compile-time)
Remove responsibilities no longer needed
Figure 13. Decorator Design Pattern
Cipher.getInstance("DES/CBC/PKCS5Padding"));
super.write(b);
this.counter++;
bout.write(b);
this.next = next;
super(next);
if (isSpam(message)) {
// handle spam
} else {
super.handle(message);
...
handler.handle(emailMessage);
...
this.salary = amount;
super.setChanged();
super.notifyObservers();
if (o instanceof Employee) {
if (o instanceof Employee) {
}
208
if (o instanceof Employee) {
19.10. Strategy
Defined family of interchangeable and encapsulated algorithms
Change algorithms independently of clients that use them
E.g: java.util.Comparator, java.io.FileFilter
Figure 15. Strategy Design Pattern
Integer.parseInt((String) o2);
19.11. Template
Define a skeleton of an algorithm
Defer some steps to subclasses
Redefine other steps in subclasses
Often a result of refactoring common code
Figure 16. Template Design Pattern
210
if (this.initialized) {
} else {
this.result = operand;
this.initialized = true;
...
s.executeUpdate();
...
...