li tak sing comps311f introduction. introduction name: li tak sing ( 李德成 ) email:...
TRANSCRIPT
Li Tak Sing
COMPS311FIntroduction
IntroductionName: Li Tak Sing (李德成 )Email: [email protected]: 27686816Room: A0916Course Web site:
http://plbpc001.ouhk.edu.hk/~mt311fYou can find course schedule, handle out,
assignments there. You will also need to submit the assignments via a link found there.
You can also download all the course materials of the distance learning version of the course at the website.
Text booksThere are two textbooks:
Introduction to JAVA Programming 7th Edn, by Y. Daniel Liang, Pearson Education.
Concepts of Programming Languages, 9th Edn, by Robert W. Sebesta, Pearson Education
You do not need to by any of the textbooks if you have your own Java textbook or programming languages textbook.
Assessment policyTwo assignments
Assignment 1: 10 Jan 2010 (7.5%)Assignment 2: 18 Apr 2011 (7.5%)
Two testsTest 1: 12 Jan 2010 (7.5%)Test 2: 20 Apr 2010 (7.5%)
Examination (70%)In order to pass the course, the total score
and the score in the examination must both be greater than 40.
Contents of the courseUnit 1: Object-oriented programming (3 weeks)Unit 2: Multithreading (3 weeks)Unit 3: Networking and RMI (3 weeks)Unit 4: Database programming (2 weeks)Unit 5: Web Programming (3 weeks)Unit 6: XML (3 weeks)Unit 7: Security (3 weeks)Unit 8: Programming paradigms and languages
(2 weeks)Unit 9: Variables, types, expressions and
assignment statements (2 weeks)Unit 10: Control structures (2 weeks)
Unit 1 Object-oriented programmingYou can download the PDF of the materials
of unit 1 at: http://plbpc001.ouhk.edu.hk/~mt311f
Abstract data typeAbstraction: to describe an object using the
most important information only. For example, there are thousands of
components of a car. However, if you are asked to describe a car, you would not describes it in terms of all of its component. Rather, you would just select a few important components to describe it. For example, a car is something that has wheels, steering wheels, engine and seats.
Java abstract data typepublic class car {
Wheel wheel[]=new Wheel[4];
SteeringWheel steeringWheel;
Engine engine;
}
This is an abstract data type of a car The car is described in terms of three of its main
components: wheel, steering wheel and the engine. Java programs are collections of classes All program codes are stored inside classes Java is a strong typing language which means that all errors
regarding typing will be reported. You also need to declare the type of all entities before they can be used.
Java abstract data typeA bank accountpublic class Account {
int balance;
}
This class now only contains data, no program code. This class contains one field called balance which is an integer. Usually when you define a class, you also define some procedures to manipulate the attributes of the class. They are called methods in OO terms. For example, we can have two methods, one to get the balance, the other to set the balance.
Bank account with setter and getterpublic class Account {
int balance;
void setBalance(int b) { balance=b;}
int getBalance() {return balance;}
}
For method setBalance, a parameter is passed into the method which is an integer named b. In fact, the method also have access to another entity, which is the bank account itself. Each method of a class is associated with an instance of the class. So in the code inside the method setBalance, we have accessed b, which is passed as a parameter, and we have accessed balance, which an attribute of the instance of Account.
For method getBalance, it does not have any parameter, so the code inside getBalance can only access the content of the associated Account.
A program that uses Account
.....
Account account=new Account(); //create a new account
account.setBalance(100); //set the balance to 100
System.out.println(account.getBalance()); //print the
//balance
....
In the above code, a new instance of Account, account, is created. Then the setBalance method of account is called with 100 as the parameter. Then, 100 is assigned to the balance attribute of account.
Static attributesAttributes model the properties of an
instance of a class. However, there are properties that are those of the whole class, not just an instance.
For example, assume that we have a class for OUHK student.
Static attributesThe attribute name, birthday are of course
properties of a particular instance of the class Student.
However, the average age of all students is not a property of any particular student. Instead it is the property of all students. In Java term, we can say that the average age of all students is the property of the class Student.
Static attributesThe property of a class is defined as static
attribute using the static keyword:
public class Student {
String name;
Date birthday;
static int averageAge;
}
Static attributesA static attribute is the property of a class,
not that of a particular instance. So it is referenced using the name of the class:
....
Student student=new student();
student.name="Chan Tai Man";
Student.averageAge=23;
....
Static attributesNote that it is ok to access a static attribute
through either an object or the class. So both of the following two statements are correct:
student.averageAge=24;Student.averageAge=32;
Static attributesHowever, even if you access a static
attribute using an instance of the class, the accessed attribute is still nothing to do with that instance.
The name of the class is not needed if you want to access a static attribute of a class inside a method of the same class.
Static attributespublic class ABC {
static int def;
public void meth() {
def=4;
}
}
The static attribute def of ABC is referenced inside the method meth of ABC. There is no need to specify the class name ABC here.
Static attributesHowever, if you like, you can replace def
in the above program by any of the followings:this.def (This is only valid if it is used
inside a method of ABC)ABC.def (This is valid anywhere in your
program)
Static methodsJust like static attributes, we can also have
static methods. A static method can access all static
attributes of the class. A static method cannot access non-static
attributes as the static method does not have an associated instance.
Static methodsJust like static attributes, a static method
should be accessed through the name of the class. But you can still access it through the name of an object or using 'this' or even without any qualifier if inside a method of the same class. However, in all cases, the static method is still not associated with any instance of the class.
Static methodspublic class Student {
String name;
Date birthday;
static int averageAge;
static void setAverageAge(int i) {
averageAge=i;
}
}
Static methodsThe following code contains errors
public class Student {
String name;
Date birthday;
static int averageAge;
static void setName(String n) {
name=n;
}
}
Static methodsHowever, the following code is correct:public class Student {
String name;
Date birthday;
static int averageAge;
static void setName(Student s, String n) {
s.name=n;
}
}
A static method cannot directly access non-static attributes of the class. But it can access it through an instance of the class.
Main programA main program in Java must be a public
and static method of a class in the following form:
public class Student {
....
public static void main(String st[]) {
....
}
}
Main methodSince a main method is a static method, it
can only access static attributes and methods of the class.
If you want to access non-static attributes, you need to create an instance of the class first and then access them through the instance.
Main methodpublic class Student {
String name;
Date birthday;
static int averageAge;
public static main(String st[]) {
Student student=new Student();
student.name="Li Tak Sing";
averageAge=23;
student.averageAge=23;
Student.averageAge=23;
}
}
InheritanceConsider the staff of a company.We want to have a class to model all the
staff of a company. The common attributes of all of these staff are:nameaddressdate of birthrank
Inheritancepublic class Staff {
private String name;
private String address;
private Date dateOfBirth;
private String rank;
public Staff(String _name, String _address, String _dateOfBirth,
Date _dateOfBirth, String _rank) {
name=_name; address=_address; dateOfBirth=_dateOfBirth; rank=_rank;
}
public String name() {return name;}
public String address() {return address;}
public Date dateOfBirth() {return dateOfBirth;}
public String rank() {return rank;}
}
InheritanceNow, the staff can be further classified as
clerical staff, managerial staff. Now, do we need a blank new class to model a clerical staff?
Obviously, a clerical is also a staff and therefore it should have all the attributes and methods of a staff.
InheritanceIt should also has additional attributes and
methods for a clerical staff. For example, it may be required to store the typing speed.
Inheritancepublic class Clerical {
private String name;
private String address;
private Date dateOfBirth;
private String rank;
public Staff(String _name, String _address, String _dateOfBirth,
Date _dateOfBirth, String _rank) {
name=_name; address=_address; dateOfBirth=_dateOfBirth; rank=_rank;
}
public String name() {return name;}
public String address() {return address;}
public Date dateOfBirth() {return dateOfBirth;}
public String rank() {return rank;}
private int typingSpeed;
public void setTypeingSpeed(int s) {typingSpeed=s;}
public int typingSpeed() {return typingSpeed;}
}
InheritanceFor managerial staff, we need to store
professional qualification.
public class Managerial {
private String name;
private String address;
private Date dateOfBirth;
private String rank;
public Staff(String _name, String _address,
Date _dateOfBirth, String _rank) {
name=_name; address=_address; dateOfBirth=_dateOfBirth; rank=_rank;
}
public String name() {return name;}
public String address() {return address;}
public Date dateOfBirth() {return dateOfBirth;}
public String rank() {return rank;}
private String professionalQualification;
public void setProfessionalQualification(s) {professionalQualification=s;}
public String professionalQualification() {return professionalQualification;}
}
InheritanceThe disadvantage of having these Clerical
and Managerial classes:lots of code has been duplicated. So if we
want to add an attribute to all staff, say, the date that the staff jointed the company, then it has to be updated in two places instead of two.
The code does not show the relationship between Staff, Clerical and Managerial. It seems that they are classes with no relationship at all.
InheritanceIn fact, we need a mechanism so that we
can create Clerical, Managerial based on Staff.
This is done in Java using the 'extends' keyword.
Inheritancepublic class Clerical extends Staff {
private int typingSpeed;
public void setTypeingSpeed(int s) {typingSpeed=s;}
public int typingSpeed() {return typingSpeed;}
}
public class Managerial extends Staff {
private String professionalQualification;
public void setProfessionalQualification(s) {professionalQualification=s;}
public String professionalQualification() {return professionalQualification;}
}
InheritanceIf we draw the contents of Clerical and
Managerial, they look like this:
Staff
Clerical
Staff
Managerial
InheritanceIn the above examples, Clerical is said to
inherit all attributes and methods of Staff with some additional attributes and methods.
So, although we did not state it explicitly, a Clerical object would still has the name attribute, the dateOfBirth attribute, etc.
Staff is said to be the super class of Clerical. Clerical is said to be the derived class, or the sub class of Staff.
InheritanceHowever, the latest Clerical and Managerial
classes are not without problems.In staff, it has a constructor which accepts
several parameters. So if Clerical is also a staff, then how can a Clerical be constructed in order to initialize the embeded Staff inside Clerical?
InheritanceSince Clerical is also a Staff, therefore in
the constructor of Clerical, we need to invoke the constructor of Staff in order to initialize the attributes of Staff.
This is done by using the 'super' keyword.
Inheritancepublic class Clerical extends Staff {
public Clerical(
private int typingSpeed;
public void setTypeingSpeed(int s) {typingSpeed=s;}
public int typingSpeed() {return typingSpeed;}
public Clerical(String _name, String _address,
Date _dateOfBirth, String _rank) {
super(_name, _address, _dateOfBirth, _dateOfBirth, _rank);
}
}
ConstructorIf a class B is extended from a class A,
when an instance of B is created, we must first create an instance of A first and then use this A to create a B.
Therefore, in the constructor of B, we must execute the constructor of A first.
If we do not execute the constructor of A in the constructor of B explicitly, then Java will invoke the default constructor of A for you.
Constructorpublic class A {
public A() {
System.out.println("the constructor of A is called");
}
}
public class B extends A {
public B() {
System.out.println("the constructor of B is called");
}
}
ConstructorWhen the following code is executed:
...
B b=new B();
...
The following would be displayed:the constructor of A is called
the constructor of B is called
Constructorpublic class A {
public A(int i) {
System.out.println("the constructor of A is called "+i);
}
}
public class B extends A {
public B() {
System.out.println("the constructor of B is called");
}
}
ConstructorThe program has a syntax error. Since we
do not invoke the constructor of A in the constructor of B, so Java invokes the default constructor of A. The default constructor has no parameter. Unfortunately, A does not have that constructor, so it result in syntax error.
In order to solve the problem, we need to call the constructor of A explicitly.
Constructorpublic class A {
public A(int i) {
System.out.println("the constructor of A is called "+i);
}
}
public class B extends A {
public B() {
super(3);
System.out.println("the constructor of B is called");
}
}
ConstructorThe super constructor must be the first
statement in constructor of a subclass.If the super constructor is not called in the
constructor of a subclass, then the default constructor of the superclass will be called. In this case, if the superclass does not have the default constructor, an error will be reported.
InterfaceA Java class can have only one super class.
That is to said, Java does not allow multiple inheritance.
Problem of multiple inheritanceAssume that we have a class A. A has two
subclass B and C. Now, if multiple inheritance is allowed, then we may have the case that a class D is the subclass of both B and C.
Problem of multiple inheritance
A
B C
D
Multiple inheritanceIf we draw the content of B, C, it would look
like this:
A
B
A
C
Problems of multiple inheritanceSo if we look at the contents of D:
A
B
A
C
D
D
Problems of multiple inheritanceSo we can see that now inside an object of
D, there are actually two instances of A and this is actually physically meaningless.
That is why Java does not allow multiple inheritance. That is to say, all class can have only one superclass.
In Java, if you do not use the 'extends' keyword in declaring a class, then Java assumes that you want to extend the class from Object.
ObjectObject is the root class of all classes in
Java. So all java objects are actually instances of Object.
So Object is the only class in Java that does not have a superclass.
InterfaceAs Java does not allow multiple inheritance,
then how can we model a real world object that have multiple characteristics?
InterfaceFor example, consider the staff example we
mentioned earlier. All the staff can be classified as permanent staff and temporary staff.
For a permanent staff, we would record the date when he/she jointed the company.
For a temporary staff, we would record the date that the contract ends.
InterfaceSo a staff can be classified into four groups:
permanent clerical stafftemporary clerical staffpermanent managerial stafftemporary managerial staff
InterfaceIf multiple inheritance is allowed, we would
have a class diagram like this:
Interface
Staff
Clerical Managerial Permanent Temporary
PermanentClerical
TemporaryClerical
PermanentManagerial
TemporaryManagerial
InterfaceWe can do this using interface.
As the name implies, an interface only define the interface of a class of objects. It does not give any actual implementation of the objects.
InterfaceFor example, consider the following
interface
public interface Permanent {
public Date dateJoining();
}
The above statements define an interface called Permanent. This interface has a method called dateJoining but it does not give the implementation of the method.
InterfaceSo we can use this interface to define a
PermanentClerical class:
public class PermanentClerical extends Clerical implements Permanent {
private Date dateJoining;
public Date dateJoining() {return dateJoining;}
public PermanetClerical(
public PermanentClerical(String _name, String _address,
Date _dateOfBirth, String _rank, Date _dateJoining) {
super(_name, _address, _dateOfBirth, _dateOfBirth, _rank);
dateJoining=_dateJoining;
}
}
InterfaceSo we can see that the above code
implements the method dateJoining defined in the interface Permanent.
Now, a PermanentClerical object is a Clerical object and also a Permanent object. So we can pass a PermanentClerical object to methods that accepts either a Clerical object, a Staff object, or a Permanent object.
InterfaceWe can also have the following statements:
PermanentClerical p=new PermanentClerical("Chan Tai Man","ABC Street",
new Date(78,1,2),"CO", new Date(99,3,12));
Clerical c1=p; //ok, p is a Clerical
InterfacePermanent p1=p; // ok, p is a Permanent
Staff s1=p; // ok, p is a Staff
Note that Permanent is an Interface, there we cannot create a Permanent object using the new keyword:Permanent p1=new Permanent();
However, it is ok to declare a variable or attribute of type Permanent and assign a Permanet object to it.
InterfaceJust like here, we cannot create a
Permanent object directly, but we can create a PermanentClerical object and then assign this object to a variable of type Permanent.
instanceofSo we can see that when you are given a
variable of type Staff, it can actually refer to a Staff, a ClericalStaff, a PermanentClerical or a Managerial etc. So, how do we know the actual identity of the object referenced by a variable? This is done by the operator 'instanceof'.
instanceofStaff p=new PermanentClerical("Chan Tai Man","ABC Street",
new Date(78,1,2),"CO", new Date(99,3,12));
if (p instanceof Staff) {
System.out.println("p is an instance of Staff"); //true
}
if (p instanceof Permanent) {
System.out.println("p is an instance of Permanent"); //true
}
if (p instanceof Clerical) {
System.out.println("p is an instance of Clerical"); //true
}
if (p instanceof Managerial) {
System.out.println("p is an instance of Managerial"); //false
}
InterfaceIf we draw the contents of
PermanentClerical, it would look like this:
ClericalStaff
PermanetClerical
InterfaceWe can see that in the last diagram, there
is no block corresponds to the interface Permanent. This is because Permanent is only an interface and does not provide any data to be stored there.
CastingAs stated earlier, a Staff variable can
actually refers to a Clerical object. So if this is the case, how can we access this object as a Clerical object?
Staff p=abc.method(); // this method returns a Staff object which is
// actually a Clerical object.
int s=p.typingSpeed(); //error as p is a Staff variable and therefore we cannot
//access the typingSpeed method.
CastingIn order to access the typingSpeed method,
we need casting:
Clerical c=(Clerical)p;
int i=c.typingSpeed();
Note that if p is really not a Clerical, then a runtime error will be reported.
Casting
Staff p=new Clerical(.....);
Clerical s=(Clerical)p; //ok
PermenantClerical p2=(PermenantClerical)p; //runtime error because p is
//not a PermenantClerical
Managerial m=(Managerial)p; //runtime error because p is
//not a Managerial
Permanent p3=(Permanent)p; //runtime error because p is not
//a Permanent
CastingStaff p=new PermanentClerical(.....);
Clerical s=(Clerical)p; //ok
PermenantClerical p2=(PermenantClerical)p; //ok
Managerial m=(Managerial)p; //runtime error because p is
//not a Managerial
Permanent p3=(Permanent)p; //ok
AccessibilityAll private attributes and methods of a
class are not accessible even in a subclass of that class.
All public attributes and methods of a class are accessible in its subclass.
Accessibilitypublic class A {
public int i=0;
private int j=0;
}
public class B extends A {
public void method() {
int k=i+1; //correct
int k=j+1; //error because j is not accessible.
}
}
AccessibilityA class and its subclass does not have to
be in the same package.So if an item of a class does not have an
access modifier, it would not be accessible in a subclass if the subclass is not in the same package as its superclass.
Accessibilitypackage package1;
public class A {
public int i=0;
private int j=0;
int k=0;
}
package package2;
public class B extends package1.A {
public void method() {
int n=i+1; //correct
int n=j+1; //error because j is not accessible.
int n=k+1; //error because A and B are not in the same package.
}
}
AccessibilityThe 'protected' access modifier specifies
that an item is to be accessible by its subclasses.
Accessibilitypackage package1;
public class A {
public int i=0;
private int j=0;
protected int k=0;
}
package package2;
public class B extends package1.A {
public void method() {
int n=i+1; //correct
int n=j+1; //error because j is not accessible.
int n=k+1; //correct
}
}
PolymorphismIn the same class, we can have two
methods with the same name as long as they have different signatures. This is called overloading.
When a class B is a subclass of class A, class B can has a method that has the same signature of a method in A. This is called overriding.
Polymorphismpublic class A {
public meth(int i, int j) {
System.out.println("the sum is "+(i+j));
}
}
public class B extends A {
public meth(int i, int j) {
System.out.println("the product is "+(i+j));
}
}
PolymorphismSince B is a subclass of A, this means that
an object of B is actually also an object of A. For example, in the staff example earlier, a Clerical object is also a Staff object.
So if we have a variable of type A, it can be assigned to an object of B or an object of A.
Polymorphism
A a1=new A(); //correct
A a2=new B(); //correct, B is also A
B b1=new A(); //incorrect, A is not B
B b2=new B(); //correct
From this, we can see that a variable of A can actually refer to an object of B or an object of A.
A variable of B in this example can only refer to an object of B.
Dynamic bindingbinding means the assignment of a value to
an item.dynamic refers to something that happens
during the execution of a program.So dynamic binding means the assignment
of a value to an item during the execution of a program.
Dynamic bindingOn the other hand, static binding refers to
the assignment of a value to an item before the program is executed.
For example, the range of a byte in Java is from -128 to 127. Here, the value is -128 to 127, the item is the range of a byte. This assignment happened well before the execution of any program. So this binding is static.
BindingConsider the following Java code:
int i=4;here, the type of i is int. This binding
happens before the program is executed, so this binding is static.
the value of i is set to 4. This binding happens after the program is executed, so the binding is dynamic.
PolymorphismConsider again the following program:public class A {
public void meth(int i, int j) {
System.out.println("the sum is "+(i+j));
}
}
public class B extends A {
public void meth(int i, int j) {
System.out.println("the product is "+(i*j));
}
}
Polymorphism...
A a=new A();
a.meth(3,4);
a=new B();
a.meth(3,4);
....
The output of the program fragment is:the sum is 7
the product is 12
Dynamic bindingFrom this example, we can see that when
the method a.meth() is first called, the version defined in A is called. However, in the second case, the version defined in B is called.
So you can see that although the same variable 'a' is used, the actual version of meth() to be invoked changed according to the actual type of the object that it refers to.
Dynamic bindingWe would say that the binding of which
version of meth to invoke is done during runtime. So this is dynamic binding.
PolymorphismPolymorphism refers to the case when a
method is invoked, the actual version to be invoked would depend on the actual type of the object.
This has to be done with dynamic binding.
Use of polymorphismConsider a class that models different
geometrical shapes. The class:
public class Shape {
public double area() { // we do not know how to find the area yet.
return 0;
}
public double volumeOfCylinder(double h) { //this method return the volume of
//the cylinder using this shape as the base.
return area()*h;
}
}
Use of polymorphismNow, we have a class that represents all
square. Obviously all squares are shape. So Square should be subclass of Shape. However, now we know how to calculate the area of a Square. So we have:
Square
public class Square extends Shape {
private double length;
public Square(double length) {
this.length=length;
}
public double length() {return length;}
public double area() {return length*length;}
}
SquareNow, can we still use the
volumeOfCylinder() method of Shape to find the volume of the cylinder using the square as the base?
....
Square square=new Square(4);
double volume=square.volumeOfCylinder();
....
Circlepublic class Circle extends Shape {
private double radius;
public Circle(double radius) {
this.radius=radius;
}
public double radius() {return radius;}
public double area() {return Math.PI*radius*radius;}
}
CircleAgain, we can still use the volumeOfCylinder
method of Shape to find the volume of the cylinder which uses the circle as the base:
....
Circle c=new Circle(3);
double vol=c.volumeOfCylinder(2);
....
PolymorphismIf we do not have polymorphism, then we
need to duplicate the code for volumeOfCylinder in Square and Circle.
AbstractLet's consider the class Shape again:
public class Shape {
public double area() { // we do not know how to find the area yet.
return 0;
}
public double volumeOfCylinder(double h) { //this method return the volume of
//the cylinder using this shape as the base.
return area()*h;
}
}
AbstractWe can see that the area method is
actually quite meaningless because Shape is a generic class that does not refer to any real shape. So we do not actually know how to calculate the area for a shape. We would only know how to calculate the area when we deal with the subclasses of Shape, which are Circle or Square.
AbstractIn addition, we would not create an
instance of Shape as it does not represent a real shape. We would only create a Circle as it is a real shape or we would create a Square.
That is the case when we use the Java keyword 'abstract'.
AbstractWhen a method is declared as abstract,
then should not provide the implementation of the method. The implementation should be provided in the subclasses of this class.
When a class is declared as abstract, then we cannot create an instance of the class.
AbstractWhen a class has at least one abstract
method, then the class must be declared as abstract.
An abstract class is very much like an interface in that we cannot create an instance in both cases.
However, in an abstract class, there can be non-abstract methods which do provide implementations.
AbstractHowever, in an interface, no
implementation is provided for all methods there.
We go back to the declaration of Shape:
Shapeabstract public class Shape {
abstract public double area();
public double volumeOfCylinder(double h) { //this method return the volume of
//the cylinder using this shape as the base.
return area()*h;
}
}
AbstractWhen you derive a subclass from an
abstract class, you have the option of either providing implementation to an abstract method or not providing the implementation.
If you do not provide implementation to all the abstract method of a superclass, then you need to declare the subclass as abstract too.
AccessibilityWhen a method is overridden in a subclass,
it must have the following properties:the method in the subclass cannot be more
restrictive than that in the superclassSo if we have a public method in a class A,
we cannot override this method in subclass B of A so that it becomes a protected method.
If a method is private in a class A, then it is not viewable outside the class. So it cannot be overridden in subclass of A.
Accessibilitypublic class A {
public void meth() {
System.out.println("meth in A");
}
public void meth2() {
meth();
}
}
public class B extends A {
public int meth() {
System.out.println("meth in B");
return 0;
}
}
.....
A a=new A();
a.meth2();
a=new B();
a.meth2();
.....
AccessibilityThe problem of last program:
The return type of meth() in A is void. In B, it is int. So the two methods have the same signature but different return types. It is not allowed.
Accessibilitypublic class A {
public void meth() {
System.out.println("meth in A");
}
public void meth2() {
meth();
}
}
public class B extends A {
protected void meth() {
System.out.println("meth in B");
}
}
.....
A a=new A();
a.meth2();
a=new B();
a.meth2();
.....
AccessibilityThe problem of this code:
meth in A is public and meth in B is protected. So it is more restrictive in B than in A. It is not allowed in Java.
Accessibilitypublic class A {
protected void meth() {
System.out.println("meth in A");
}
public void meth2() {
meth();
}
}
public class B extends A {
public void meth() {
System.out.println("meth in B");
}
}
.....
A a=new A();
a.meth2();
a=new B();
a.meth2();
.....
AccessibilityThe program has no problem. meth in A is
protected and that in B is public. So it is less restrictive in B than in A. It is ok in Java.
The output of the code is:
meth in A
meth in B
Accessibilitypublic class A {
private void meth() {
System.out.println("meth in A");
}
public void meth2() {
meth();
}
}
public class B extends A {
public void meth() {
System.out.println("meth in B");
}
}
.....
A a=new A();
a.meth2();
a=new B();
a.meth2();
.....
AccessibilityThe code has no problem. Note that meth
in A is private. Therefore it is not accessible outside A. Now, in B, it has a method with the same signature of meth in B. However, the meth in B is not overriding the meth in A although they have the same signature. This is because in B, it cannot see the existence of meth in A, so it cannot override meth in A.
AccessibilityThe output of the method is therefore:
meth in A
meth in A
Note that when meth2 of B is called, it will invoke the meth of A, not that of B. It is because A in meth is never overridden.
Accessibilitypublic class A {
private void meth() {
System.out.println("meth in A");
}
public void meth2() {
meth();
}
}
public class B extends A {
public int meth() {
System.out.println("meth in B");
return 0;
}
}
.....
A a=new A();
a.meth2();
a=new B();
a.meth2();
.....
AccessibilityThe program has no problem as meth in A
is private and therefore it cannot be overridden in B. So although meth in B is of different return type as that in A, it still has no problem. So the output of the code is the same as that in the previous code.
Anonymous classIf we have a class A, we can create a
subclass of A without giving the class a name. This is call an anonymous class.
Anonymous classpublic class A {
public void meth() {
System.out.println("meth in A");
}
public static void main(String st[]) {
A b=new A() {
public void meth() {
System.out.println("meth in a sub class of A");
}
};
b.meth();
}
}
Anonymous classIn the examination, the new object is not
an A, it is a subclass of A with the method meth overridden. This class can only be used where it is defined. So it is not very useful if you want to use it again in somewhere else. However, it has the advantage that you can use even the private attributes of the class where this anonymous class is used.
Anonymous classNote that inside an anonymous class, you
can access the attributes and methods of the class where the anonymous class is defined. You can also access local variables of the method where the anonymous class is defined provided they are final. This is because local variable would no longer exists when the method is finished.
public class A {
private int i=4;
public void meth() {
System.out.println("i*4 is "+(i*4));
}
public void meth2() {
int j=4;
final int k=3;
A a=new A() {
public void meth() {
System.out.println("i-4 is "+(i-4)); //ok
System.out.println("j-4 is "+(j-4)); //error
System.out.println("k-4 is "+(k-4)); //ok
}
};
a.meth();
}
public static void main(String st[]) {
A a=new A();
a.meth2();
}
}
Anonymous ActionListenerActionListener is an interface and therefore
we cannot use the 'new' keyword to an instance of an ActionListener. However, we can define an anonymous ActionListener class which gives the implementation of the actionPerformed method.
Anonymous ActionListener
button.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
System.out.println("abc");
}
});
Inner classAnother way to define an action listener is
to use inner class.When you define a class within another
class, the former one is an inner class. You can define a static inner class or a non-
static inner class.A static inner class does not has any
associated object of the outer class.
Inner classFor a non-static inner class, each instance
of the inner class is associated with an instance of the outer class.
Inner classpublic class A {
private int a=1;
public B b;
public class B {
private int b=4;
public int meth() {
return a+b; // ok as each instance of B is associated with an
//instance of A.
}
}
public A() {
b=new B();
}
}
Inner classSo if you have the following code:....
A a=new A();
System.out.println(a.b.meth());
....
the number 5 will be printed out.
Inner classesLike anonymous class, you can also access
all methods and attributes of the outer class.
Unlike anonymous class, there is no local variables to refer to as it is not defined inside a method.
public class MyFrame extends javax.swing.JFrame {
public class MyListener implements java.awt.event.ActionListener {
public void actionPerformed(java.awt.event.ActionEvent a) {
System.out.println("abc");
}
}
private javax.swing.JButton button;
public MyFrame() {
javax.swing.JLabel label=new javax.swing.JLabel("press the button");
button=new javax.swing.JButton("button");
button.addActionListener(new MyListener());
this.setLayout(new java.awt.FlowLayout());
this.add(label);
this.add(button);
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
pack();
}
public static void main(String st[]) {
MyFrame f=new MyFrame();
}
}
Exception HandlingException is a runtime error. When a run time error appears, an
exception is thrown.For example, when you run the following
code: Integer i=null; i.toString();
an exception would be thrown because you are trying to invoke a method of a null object.
Exception HandlingIn fact the following message would be
displayed:Exception in thread "main" java.lang.NullPointerException
at lecture15_11_2005.Main.main(Main.java:29)
This is the default exception handling, i.e., to print out a message showing where the exception is thrown and what type of exception is thrown.
Exception HandlingIf you want to handle an exception
differently, then you can use the try-catch block.
Consider the following code:
try { Integer i=null; System.out.println(i.toString());}catch (Exception e) { System.out.println("an error occurs");}
try ... catchThe above statements state that try the
statements in the try block. Then if an exception is thrown and it is of type Exception, then, run the statements in the catch block.
Checked and unchecked exception There are two kinds of exceptions, namely
checked and unchecked.Checked exceptions are all subclass of
Exception. Unchecked exceptions are subclass of either Error or RuntimeException. Error refers to errors of the Java system itself and therefore we cannot handle it. RuntimeException are those that errors that can happen anywhere in a program when a program is executed.
Unchecked ExceptionFor example, NullPointerException can
happen anywhere in the program when you are using an object variable.
For this kind of errors, Java does not require you to handle it. Of course, you may still choose to handle it. If you do not handle an unchecked error and that error occurs, the default handler will be used which is to stop the program and display a message about this error.
Unchecked Exception
So both the following codes are correct:
public void method() {
Integer i=null;
System.out.println(i.toString());
System.out.println("error2");
}
public void method() {
try {
Integer i=null;
System.out.println(i.toString());
}
catch () {
System.out.println("error");
}
System.out.println("error2");
}
the 'throw' keywordIn the last exception, the
NullPointerException was generated when the Java runtime system discovered an error.
In fact, we can create any exception anywhere we want by using the 'throw' key word.
the 'throw' keywordConsider the following program:
.....
if (....) {
throw new NullPointerException();
}
...
This statement will throw the NullPointerException when the condition is satisfied.
Checked exceptionsAll subclasses of Exception other than
those of RuntimeError's are checked Exception. Unlike unchecked errors which can occur nearly everywhere in a program, checked errors usually occur at only a few points in a program.
Checked ExceptionsUnlike unchecked exceptions, you must
handle all checked exceptions. There are two ways to handle a checked exception in a method, either you handle it locally or you have the exception handled by the caller of the method.
Checked ExceptionsFor example, an IOException refers to an
exception that occurs during an IOException which is a checked exception. So if you have code like this:
public void method() { if (...) throw new IOException();}
the compiler would report an error saying that you did not handle the IOException.
Handling a checked exception locallyTo handle a checked exception locally, you
must include the statements that would generate that exception inside a try-catch block:
public void method() { try {
if (...) throw new IOException(); }
catch (IOException e) {
........
}
}
Letting the caller to handle the exceptionAnother way to handle an exception is to
let the caller to handle it. In this case, you must declare the method would throw such exception using the 'throws' keyword:
Letting the caller to handle the exception public void method() throws IOException {
if (...) throw new IOException();}
Now, there is no need to include a try-catch block here because the exception should now be handled by whatever method that called this one
Letting the caller to handle an exceptionSo the caller of the above method now
itself has two choices, either to handle it locally or to have it handled by its own caller by using the 'throws' keyword.
public class ABC {
public void method1() throws IOException {
.....
throw new IOException();
}
public void method2() throws IOException {
.....
method1();
}
public void method3() throws IOException {
.....
method2();
}
public void method4() {
.....
try { method3(); }
catch (IOException e) { .....}
}
}
Checked ExceptionIf you study the documents for methods
that would handle IO, security, etc, then you will see that most of these methods use the 'throws' keyword to tell you that they may throw certain exceptions when problems occur. So if you want to use these methods, you must either handle these exception locally using the try-catch block or you use the 'throws' keyword yourself to let the caller of the method you just wrote to handle it.
Checked ExceptionAssume that you want to open a file to read
the content, then you can write:public void String readFile(String filename) {
try {
FileReader reader=new FileReader(....);
.....
return result;
}
catch (IOException e) {
return null; //an error occurs and therefore a null is returned
}
}
Checked ExceptionOr you can write the method like this:public void String readFile(String filename) throws IOException {
FileReader reader=new FileReader(....);
.....
return result;
}
Checked ExceptionIn the former case, the user of the method
do not have to handle any exception. Actually, the user of the method would not know that there might or might not have errors. In the latter case, the user has to handle any possible error generated in the method or it itself has to use the 'throws' keyword to let the caller to handle it.
So be careful about the difference of 'throw' and 'throws''throw' is an action. This is to actually
throw an exception:
throw new IOException(); //an IOException is thrown
'throws' is a declaration. This is to declare that a method may throw such exception:
public void method() throws IOException() // this method may
// throw IOException, so the caller of this method must handle it
'throw'Therefore, you can create your own
exception and then throw it wherever you want.
Creating your own exceptionsNow, assume that you are writing a method
to calculate the amount of interest you are going to pay for a given amount of principal, interest rate and the year of loan. So the method look like this:
static public double interest(double principal, double rate, double length) {...}
Creating your own exceptionObviously, the result of the method would
be meaningless if either the principal, the interest rate or the length of loan is negative. Therefore we create three exceptions, known as NegativePrincipal, NegativeRate, NegativeLength.
Creating your own exceptionspublic class NegativePrincipal extends Exception {
.....
}
public class NegativeRate extends Exception {
....
}
public class NegativeLength extends Exception {
...
}
Creating your own exception static public double interest(double principal, double rate,
double length) throws NegativePrincipal, NegativeRate, NegativeLength { if (principal<0) throw new NegativePrincipal(); .......}
Calling the methodSo the user the method may look like this:try {
double interest=interest(1,-2,3);
System.out.println("the interest is "+interest);
}
catch (NegativePrincipal e) {
System.out.println("the principal is negative");
}
catch (NegativeRate e) {
System.out.println("the rate is negative");
}
catch (NegativeLength e) {
System.out.println("the length is negative");
}
Many catch blocksIf a try block is ended with more than one
catch block, then each of the catch block will be tried until there is a match.
try {
double interest=interest(1,-2,3);
System.out.println("the interest is "+interest);
}
catch (Exception e) {
System.out.println("an exception has been thrown");
}
catch (NegativePrincipal e) {
System.out.println("the principal is negative");
}
catch (NegativeRate e) {
System.out.println("the rate is negative");
}
catch (NegativeLength e) {
System.out.println("the length is negative");
}
the finally blockA try block can also be ended with a finally
block. If a try block has a finally block, then the
code will be executed after the code in the try block has been executed or after the code in a catch block is executed if an exception has been thrown.
finallyThis means that the code in the finally
block will always be executed even if the following things happen:the return statement is executed inside the
try block or a catch blockan exception is thrown inside the try block
finallypublic static void method(int i) {
try {
System.out.println("position 1");
if (i==1) {
throw new IOException();
}
System.out.println("position 2");
}
catch (IOException e) {
System.out.println("position 3");
}
finally {
System.out.println("position 4");
}
}
finallyThe output of the calling of the method: method(1):
position 1
position 3
position 4
finallyThe output of the calling of the method: method(2):
position 1
position 2
position 4
public static int method(int i) { try { System.out.println("position 1"); if (i==1) { throw new IOException(); } else if (i==2) { return 2; } System.out.println("position 2"); return 3; } catch (IOException e) { System.out.println("position 3"); return 4; } finally { System.out.println("position 4"); }}
Finallythe output of the following calls: System.out.println(method(1));
System.out.println(method(2));
System.out.println(method(3));
Finallyposition 1
position 3
position 4
4
position 1
position 4
2
position 1
position 2
position 4
3