Sưu tầm bởi:
www.daihoc.com.vn
19
Lớp do người dùng định nghĩa (user-defined)
Định nghĩa phương thức
Hành vi của các đối tượng của một lớp được xác định bởi các phương thức của lớp đó.
Cú pháp định nghĩa phương thức
[<Phạm vi hoặc thuộc tính kiểm soát truy nhập>]<Kiểu trả về><Tên phương thức>
([<Danh sách tham biến hình thức>])[<Mệnh đề throws>]
{
<Nội dung phương thức>
}
Trong đó
<Kiểu trả về> có thể là kiểu nguyên thủy, kiểu lớp hoặc không có giá trị trả lại (kiểu void)
<Danh sách tham biến hình thức> bao gồm dãy các tham biến (kiểu và tên) phân cách
với nhau bởi dấu phẩy.
Các kiểu phạm vi hay kiểm soát truy cập
public: Các thành phần được khai báo là public có thể được truy cập ở bất kỳ nơi
nào có thể truy cập được và chúng được thừa kế bởi các lớp con của nó.
private: Các thành phần được khai báo là private chỉ có thể được truy cập trong
chính lớp đó
protected: Các thành phần được khai báo là protected có thể được truy cập và
thừa kế bởi các lớp con và có thể truy xuất bởi mã lệnh của cùng gói đó.
Constructor
Constructor là một phương thức đặc biệt không có giá trị trả về và có tên trùng
với tên lớp. Trường hợp không có constructor nào được đưa ra trình biên dịch cung cấp
constructor mặc định cho lớp đó.
Một đối tượng được tạo mới và được cho trước một giá trị khởi đầu. Các trường
có thể được khởi tạo bằng một giá trị khi chúng được khai báo, điều này đủ để đảm bảo
một trạng thái khởi đầu đúng đắn.
Các phương thức
Các phương thức của một lớp thường chứa mã có thể hiểu và thao tác một
trạng thái của đối tượng. Một số lớp có các trường public để người lập trình có thể thao
tác trực tiếp, nhưng trong hầu hết các trường hợp điều này không phải là một ý tưởng
tốt.
public class Point
Sưu tầm bởi:
www.daihoc.com.vn
20
{
protected double x,y;
public Point(double x,double y)
{
this.x=x;
this.y=y;
}
public void move(double dx, double dy)
{
x=x+dx;
y=y+dy;
}
public void print()
{
System.out.println("x="+x+", y="+y);
}
public static void main(String[] args)
{
Point p=new Point(3.0,6.0);
System.out.println("Thong tin ve toa do diem ban dau:");
p.print();
p.move(-1.5,2.0);
System.out.println("Thong tin ve toa do diem sau khi tinh tien theo vec
to:");
p.print();
}
}
C:\>java Point
Thong tin ve toa do diem ban dau:
x=3.0, y=6.0
Thong tin ve toa do diem sau khi tinh tien theo vec to:
x=1.5, y=8.0
Tham chiếu this
Thông thường, đối tượng nhận phương thức cần phải biết tham chiếu của nó.
Sưu tầm bởi:
www.daihoc.com.vn
21
Trong lớp Point có constructor
public Point(double x,double y)
{
this.x=x;
this.y=y;
}
Giả sử nếu sửa đổi constructor bằng cách thay đổi như sau:
public Point(double x,double y)
{
x=x;
y=y;
}
Khi biên dịch chương trình sẽ báo lỗi vì có sự nhập nhằng trong các lệnh gán. Tham
chiếu this đã khắc phục được điều này, this.x và this.y muốn đề cập tới trường thông tin
của lớp Point còn x, y là tham biến truyền vào của constructor.
2.4.2. Thừa kế trong Java
class Point3C extends Point2C
{
protected double z;
public Point3C(double x, double y, double z)
{
super(x,y);
this.z=z;
}
public void move(double dx, double dy, double dz)
{
super.move(dx,dy);
z+=dz;
}
public void print()
{
super.print();
Sưu tầm bởi:
www.daihoc.com.vn
22
System.out.print(" z="+z);
}
public static void main(String[] args)
{
Point3C p=new Point3C(3.0,4.5,5.0);
System.out.println("Toa do ban dau:");
p.print();
System.out.println();
p.move(-1.0,0.5,-1.0);
System.out.println("Toa do sau khi tinh tien:");
p.print();
System.out.println();
}
}
Từ khóa super
Từ khóa super được sử dụng để gọi constructor của lớp cha hoặc truy xuất tới các
thành phần của lớp cha được che dấu bởi một thành phần của lớp con.
Ở trên ta đã xét hai đoạn mã, đoạn mã thứ nhất khai báo lớp Point2C biểu diễn một đối
tượng điểm hai chiều, đoạn mã thứ hai khai báo lớp Point3C biểu diễn một đối tượng
điểm ba chiều. Lớp Point3C được kế thừa lớp từ lớp Point2C. Lời gọi super(x,y) trong
lớp Point3C gọi tới constructor Point2C hay super.move(dx,dy) gọi tới phương thức
move(dx,dy) của lớp Point2C.
Biên dịch chương trình
C:\>javac Point3C.java
Thực thi chương trình
C:\>java Point3C
Kết quả chương trình
Toa do ban dau:
x=3.0, y=4.5 z=5.0
Toa do sau khi tinh tien:
x=2.0, y=5.0 z=4.0
2.4.3. Truyền tham số trong Java
Sưu tầm bởi:
www.daihoc.com.vn
23
Thông thường, trong một ngôn ngữ lập trình thường có hai cách truyền tham biến cho
một thủ tục: truyền theo tham trị và truyền theo tham chiếu.
Truyền theo tham trị
Phương thức sẽ sao chép giá trị của một tham biến vào tham biến hình thức của thủ
tục. Vì vậy, những thay đổi đối với tham số thủ tục sẽ không ảnh hưởng tới tham số
thực sự.
class CallByValue
{ void test(int i,int j)
{
i*=2;
j*=2;
}
public static void main(String[] args)
{
CallByValue cbl=new CallByValue();
int a=10, b=30;
System.out.println("Gia tri a va b truoc khi goi phuong thuc:"+a+" "+b);
cbl.test(a,b);
System.out.println("Gia tri a va b truoc sau goi phuong thuc:"+a+" "+b);
}
}
C:\MyJava>javac CallByValue.java
C:\MyJava>java CallByValue
Gia tri a va b truoc khi goi phuong thuc:10 30
Gia tri a va b truoc sau goi phuong thuc:10 30
Tất cả các tham số đối với các phương thức Java là “gọi theo trị”. Nghĩa là, các giá trị
của các biến tham số trong một phương thức là các bản sao của các giá trị do người gọi
xác định.
Ví dụ:
class TruyenThamTri
{
public static void main(String[] args)
{
double one =1.0;
System.out.println("Truoc khi goi ham:one="+one);
Sưu tầm bởi:
www.daihoc.com.vn
24
chia(one);
System.out.println("Sau loi goi ham chia:one ="+one);
}
public static void chia(double x)
{
x/=2.0;
System.out.println("Sau khi chia:x="+x);
}
}
C:\MyJava\Baitap>java TruyenThamTri
Truoc khi goi ham:one=1.0
Sau khi chia:x=0.5
Sau loi goi ham chia:one =1.0
Truyền theo tham chiếu
Một tham chiếu tới tham biến được truyền cho tham số. Bên trong thủ tục, tham chiếu
này được sử dụng để truy xuất tới tham số thực sự được xác định trong lời gọi. Điều
này nghĩa là những thay đổi đối với tham biến sẽ ảnh hưởng tới tham số đã được sử
dụng để gọi phương thức.
Mảng trong Java được xem là đối tượng. Các phần tử của mảng có thể có kiểu nguyên
thủy hoặc kiểu tham chiếu (kiểu lớp)
Ví dụ: Lọc ra phần tử lớn nhất của một mảng và đưa về cuối mảng.
C:\MyJava\Baitap>java Loc
8 1 4 3 2 5
1 4 3 2 5 8
Vì trong Java các lời gọi hàm đều thực hiện theo tham trị (call by value) với kiểu nguyên
tố và tham chiếu đối với kiểu lớp nên hàm doiCho() thay đổi được các phần tử của day.
Các tham biến final
Tham biến hình thức có thể được khai báo với từ khóa final đứng trước. Tham biến final
là tham biến không được khởi tạo giá trị cho đến khi nó được gán một trị nào đó và khi
đã được gán trị thì không thể thay đối giá trị đó được.
Ví dụ
class BienFinal
{
public static void main(String[] args)
{
Sưu tầm bởi:
www.daihoc.com.vn
25
HangSX banh = new HangSX();
int giaBan=20;
double tien = banh.tinh(10,giaBan);
System.out.println("Gia ban: "+giaBan);
System.out.println("Tien ban duoc: "+tien);
}
}
class HangSX
{
double tinh(int so, final double gia)
{
gia = gia/2.0;
return so*gia;
}
};
Khi biên dịch hàm tinh(), chương trình dịch sẽ thông báo lỗi và không được phép thay
đổi giá trị của biến final gia.
Các đối trong chương trình
Chúng ta có thể truyền các tham số cho chương trình trên dòng lệnh
Ví dụ
class TinhTong
{
public static void main(String[] args)
{
float s=0.0f;
for(int i=0; i<args.length;i++)
s+=Float.valueOf(args[i]).floatValue();
System.out.println("Tong cua day so la "+s);
}
}
Kết quả thực hiện chương trình
C:\MyJava\Baitap>java TinhTong 12 34 56
Tong cua day so la 102.0
Sưu tầm bởi:
www.daihoc.com.vn
26
2.4.4. Đa hình trong Java
Các phương thức nạp chồng (overloaded method)
Các phương thức nạp chồng là các phương thức nằm trong cùng một lớp
có cùng tên nhưng khác nhau về danh sách tham số.
Các phương thức nạp chồng là một dạng của tính đa hình thời gian biên dịch.
Ví dụ
class TinhToan
{
public static void main(String[] args)
{
Tinh c = new Tinh();
c.add(10,20);
c.add(40.0f,35.65f);
c.add("Good ","Morning");
}
}
class Tinh
{
public void add(int a, int b)
{
int c = a+b;
System.out.println("Phep cong hai so nguyen :"+c);
}
public void add(float a, float b)
{
float c = a+b;
System.out.println("Phep cong hai so dau phay dong :"+c);
}
public void add(String a, String b)
{
String c = a+b;
System.out.println("Phep cong hai xau :"+c);
}
};
Sưu tầm bởi:
www.daihoc.com.vn
27
Kết quả:
C:\MyJava\Baitap>java TinhToan
Phep cong hai so nguyen :30
Phep cong hai so dau phay dong :75.65
Phep cong hai xau :Good Morning
Giải thích: Trong chương trình trên phương thức add() là phương thức được nạp chồng.
Có ba phương thức có cùng tên add() nhưng có các tham số khác nhau. Khi chúng ta
gọi phương thức add()…????
2.4.5. Các thành phần static
Đôi khi các thành phần static ta cần phải định nghĩa các thành phần lớp được sử dụng
độc lập với bất kỳ đối tượng nào của lớp. Thông thường một thành phần của lớp phải
được truy xuất thông qua đối tượng của lớp. Tuy nhiên, ta có thể có thể tạo ra một
thành phần mà được sử dụng độc lập. Để tạo ra một thành phần như vậy trước khai
báo của mỗi thành phần ta đặt một từ khóa static. Khi một thành phần được khai báo
static, nó có thể được truy xuất trước khi một đối tượng được tạo ra và không cần tham
chiếu tới bất kỳ đối tượng nào. Các thành phần static bao gồm: biến static, phương thức
static, khối static.
Biến static
Biến static về cơ bản là biến tổng thể. Khi các đối tượng của một lớp được khai báo,
không có bản sao của biến đối tượng nào được tạo ra. Thay vào đó, tất cả các đối
tượng cùng chung một biến static.
Ví dụ về biến static
class StaticVariable {
static int count=20;
StaticVariable(){
count++;
}
public static void main(String[] args)
{
StaticVariable c1=new StaticVariable();
System.out.println("Bien dem count="+count);
StaticVariable c2=new StaticVariable();
System.out.println("Bien dem count="+count);
StaticVariable c3=new StaticVariable();
System.out.println("Bien dem count="+count);
}
}
Sưu tầm bởi:
www.daihoc.com.vn
28
Biến count được khai báo là static nên nó chỉ có một bản sao trong mọi đối tượng, vì
vậy khi đối tượng được tạo ra thì các biến count được tăng lên 1 do trong hàm
constructor biến count được tăng lên 1.
Phương thức static
Các phương thức được khai báo static có một số hạn chế sau:
o Chúng chỉ có thể gọi các phương thức static khác.
o Chúng chỉ truy xuất tới các dữ liệu static
o Chúng không thể tham chiếu tới this và super
Ví dụ
class StaticMethod
{
public static void main(){
System.out.println("Hello");
}
public static void main(String[] args)
{
main();
System.out.println("Hello World!");
}
}
Trong ví dụ này ta thấy khai báo hai phương thức main đều là phương thức tĩnh.
Phương thức main này gọi tới phương thức main khác.
Khối static
Nếu cần tính toán để khởi tạo các biến static, ta có thể khai báo khối static để nó có thể
xử lý ngay tức thời khi lớp lần đầu tiên được tải vào bộ nhớ. Các khối static luôn được
xử lý trước
Ví dụ
class StaticDemo
{
static{
System.out.println("Khoi static 1");
}
public static void main(String[] args)
{
System.out.println("Hello World!");
Sưu tầm bởi:
www.daihoc.com.vn
29
}
static {
System.out.println("Khoi static 2");
}
}
Vì khối static luôn được xử lý trước nên kết quả in ra của chương trình trên sẽ là:
Khoi static 1
Hello World!
Khoi static 2
2.4.6. Các thành phần final
Biến final
Một biến được khai báo final. Làm như vậy sẽ ngăn ngừa nội dung của biến bị sửa đổi.
Điều này nghĩa là ta phải khai báo một biến final khi nó được khai báo.
Ví dụ
final double pi=3.1416;
Sử dụng final với thừa kế
Mặc dù nạp chồng phương thức là một trong các đặc trưng mạnh của Java, nhưng sẽ
có những lúc ta cần ngăn ngừa điều này xảy ra. Để không cho phép một phương thức
được nạp chồng, xác định từ khóa final như là một bổ từ tại đầu mỗi khai báo của nó.
Các phương thức được khai báo là final không thể được nạp chồng.
Ví dụ
class A {
final void method(){
}
}
class B extends A{
final void method(){
}
}
Khai báo lớp B có lỗi, vì ở lớp A, phương thức method đã được khai báo với từ khóa
final nên nó không thể được nạp chồng trong lớp B.
Sử dụng từ khóa final để cấm thừa kế
Đôi khi ta cần cấm một số lớp không có lớp con. Ta có thể thực hiện điều này bằng
cách khai báo lớp với từ khóa final.
Ví dụ
Sưu tầm bởi:
www.daihoc.com.vn
30
final class A {
}
Lúc này, các lớp khác không thể thừa kế từ lớp A.
2.5. Các lớp trừu tượng
Trong lập trình Java, có những lúc ta cần định nghĩa lớp cha và khai báo cấu trúc một
cách khái quát mà không cài đặt cụ thể cho từng phương thức. Các lớp cha sẽ định
nghĩa dạng tổng quát hóa được dùng chung bởi các lớp con của nó, việc cài đặt chi tiết
các phương thức này sẽ được thực hiện ở trong từng lớp con cụ thể.
Ví dụ:
abstract class Hinh2D
{
double a,b,r;
public abstract double dientich();
public abstract double chuvi();
}
class HinhTron extends Hinh2D
{
public HinhTron(double r)
{
this.r=r;
}
public double dientich()
{
return Math.PI*r*r;
}
public double chuvi()
{
return Math.PI*2*r;
}
}
class HinhChuNhat extends Hinh2D
{
public HinhChuNhat(double a,double b)
{
this.a=a;
this.b=b;
Sưu tầm bởi:
www.daihoc.com.vn
31
}
public double dientich()
{
return a*b;
}
public double chuvi()
{
return (a+b)*2;
}
}
class AbstractDemo
{
public static void main(String args[])
{
Hinh2D ht=new HinhTron(1);
System.out.println("Dien tich hinh tron ban kinh 1.0 la:"+ht.dientich());
System.out.println("Chu vi hinh tron ban kinh 1.0 la:"+ht.chuvi());
Hinh2D hcn=new HinhChuNhat(3,4);
System.out.println("Dien tich hinh chu nhat la:"+hcn.dientich());
System.out.println("Chu vi hinh chu nhat la "+hcn.chuvi());
}
};
Kết quả thực hiện chương trình
C:\MyJava>java AbstractDemo
Dien tich hinh tron ban kinh 1.0 la:3.141592653589793
Chu vi hinh tron ban kinh 1.0 la:6.283185307179586
Dien tich hinh chu nhat la:12.0
Chu vi hinh chu nhat la 14.0
Trong chương trình trên ta khai báo lớp trừu tượng Hinh2D, lớp này có các phương
thức trừu tượng là dientich() để tính diện tích của hình và lớp chuvi() để tính chu vi. Các
lớp trừu tượng không được cài đặt mã lệnh.
Các lớp HinhTron và HinhChuNhat là các lớp con cụ thể của lớp trừu tượng Hinh2D.
Các lớp này cài đặt các phương thức tính diện tích và chu vi cụ thể
2.6. Giao tiếp (Interface)
Sưu tầm bởi:
www.daihoc.com.vn
32
Thừa kế đóng một vai trò rất quan trọng trong việc tiết kiệm thời gian và công sức của
người lập trình. Hầu hết các chương trình trong thực tế đều sử dụng đa thừa kế. Trong
đa thừa kế, chúng ta có thể thừa kế các phương thức và thuộc tính từ một số lớp khác
nhau. Java không hỗ trợ đa thừa kế. Tuy nhiên, nhận thấy tầm quan trọng của đa thừa
kế trong Java, Java đã đưa ra khái niệm interface. Với giao tiếp ta có thể xác định một
lớp phải làm gì nhưng không xác định cách làm thế nào.
Định nghĩa
Một giao tiếp là một tập hợp các định nghĩa phương thức (không có cài đặt). Một giao
tiếp cũng có thể định nghĩa các hằng.
Ta cũng có thể đặt câu hỏi vậy giao tiếp khác gì so với các lớp trừu tượng? Dưới đây là
những sự khác biệt giữa giao tiếp và các lớp trừu tượng:
o Một giao tiếp không thể thực thi bất kỳ phương thức nào, ngược lại
một lớp trừu tượng có thể thực thi một số phương thức nào đó.
o Một lớp có thể thực thi nhiều giao tiếp nhưng một lớp chỉ có một lớp
cha.
o Một giao tiếp không phải là bộ phận của sơ đồ phân cấp lớp, các lớp
có thể thực thi cùng một giao tiếp.
Khai báo một giao tiếp
Cú pháp chung khi khai báo một giao tiếp là
public interface InterfaceName extends SuperInterfaces
{
//Thân giao tiếp
}
Hai thành phần bắt buộc trong một khai báo giao tiếp là-từ khóa interface và tên của
giao tiếp. Từ khóa bổ trợ truy xuất là public chỉ ra rằng giao tiếp có thể được sử dụng
bởi bất kỳ lớp nào bất kỳ gói nào. Nếu không xác định giao tiếp là public thì giao tiếp sẽ
chỉ có thể truy xuất bởi các lớp được định nghĩa trong cùng gói với giao tiếp.
Một khai báo giao tiếp có thể có một thành phần khác: danh sách các giao tiếp cha. Một
giao tiếp có thể thừa kế các giao tiếp khác, giống như một lớp có thể thừa kế hoặc là
lớp của lớp khác. Danh sách các giao tiếp cha được phân cách bởi dấu phẩy.
Thân giao tiếp
Thân giao tiếp chứa các khai báo phương thức cho tất cả các phương thức có trong
giao tiếp. Một khai báo phương thức trong một giao tiếp kết thúc bởi dấu chấm phẩy (;)
vì một giao tiếp không cung cấp cách cài đặt cho các phương thức được khai báo trong
nó.
Một giao tiếp có thể chứa các khai báo hằng ngoài các khai báo phương thức. Các khai
báo thành phần trong một giao tiếp không được phép sử dụng một số từ khóa bổ trợ
như private, protected transient, volatile, hoặc synchronized trong các khai báo thành
phần của một giao tiếp.
Trong ví dụ sau ta sẽ tìm hiểu cách định nghĩa một giao tiếp và cách thực thi một giao
tiếp trong.
public interface CalculatorInterface
{
Sưu tầm bởi:
www.daihoc.com.vn
33
public double add(double x, double y);
public double sub(double x, double y);
public double mul(double x, double y);
public double div(double x, double y);
}
Thực thi giao tiếp
Một giao tiếp định nghĩa một tập hợp hợp các quy ước về hành vi. Một lớp thực thi một
giao tiếp tuân theo những quy ước đã được khai báo trong giao tiếp đó. Để khai báo
một lớp thực thi một giao tiếp, ta đưa vào mệnh đề implements trong khai báo lớp. Một
lớp có thể thực thi nhiều giao tiếp (Java hỗ trợ đa thừa kế giao tiếp), vì vậy sau từ khóa
implements là một danh sách các giao tiếp được thực thi bởi một lớp.
Chú ý: Mệnh đề implements đứng sau mệnh đề extends nếu tồn tại mệnh đề extends.
class CalculatorTest implements CalculatorInterface
{
public double add(double x, double y)
{
return x+y;
}
public double sub(double x, double y)
{
return x-y;
}
public double mul(double x, double y)
{
return x*y;
}
public double div(double x, double y)
{return x/y;
}
public static void main(String[] args) throws Exception
{
CalculatorInterface cal=new CalculatorTest();
if(args.length!=2)
{
Sưu tầm bởi:
www.daihoc.com.vn
34
System.out.println("Cach chay chuong trinh: java CalculatorImpl
so1 so2");
return;
}
else
{
double x,y,z;
x=Double.parseDouble(args[0]);
y=Double.parseDouble(args[1]);
System.out.println(x+"+"+y+"="+cal.add(x,y));
System.out.println(x+"-"+y+"="+cal.sub(x,y));
System.out.println(x+"*"+y+"="+cal.mul(x,y));
System.out.println(x+"/"+y+"="+cal.div(x,y));
}
}
}
Kết quả thực hiện chương trình là
C:\MyJava>java CalculatorTest 12 3
12.0+3.0=15.0
12.0-3.0=9.0
12.0*3.0=36.0
12.0/3.0=4.0
Sử dụng giao tiếp như là một kiểu
Khi ta định nghĩa một giao tiếp mới, ta có thể định nghĩa kiểu dữ liệu tham chiếu mới.
Giao tiếp có thể được sử dụng khi khai báo một biến tham chiếu. Giả sử MyInterface là
một giao tiếp thì ta có thể khai báo như sau:
MyInterface mi;
2.7. Các gói và sử dụng gói trong Java
Các gói có các thành phần là các lớp, các interface, và các gói con có liên quan với
nhau. Việc tổ chức thành các gói có một số lợi ích sau đây:
o Các gói cho phép ta tổ chức các lớp thành các đơn vị nhỏ hơn (như
các thư mục), và giúp cho việc định vị và sử dụng các lớp tương ứng
trở nên dễ dàng hơn.
o Tránh được các vấn đề về xung đột tên.
o Cho phép ta bảo vệ các lớp, dữ liệu và các phương thức theo một
quy mô lớn hơn so với phạm vi lớp.
Sưu tầm bởi:
www.daihoc.com.vn
35
o Các tên gói có thể được sử dụng để định danh các lớp của bạn.
Truy xuất tới các thành phần của gói trong Java
Để truy xuất tới thành phần của gói trong Java ta có thể sử dụng cú pháp sau:
MyPackage.MyClass
MyPackage là tên gói, MyClass là tên lớp nằm trong gói MyPackage.
Khai báo các gói trong chương trình
Để có thể sử dụng các thành phần của một gói trong chương trình Java, ta cần phải
khai báo gói cụ thể chứa lớp đó:
import ten_goi.*;// ten_goi: tên gói
Với khai báo như trên, ta có thể truy xuất tới tất cả các lớp, các interface nằm trong gói
đó. Để khai báo sử dụng một lớp cụ thể trong chương trình ta khai báo dòng lệnh sau:
import ten_goi.ten_lop; // ten_lop: tên lớp
Giả sử ta có gói MyPackge, bên trong gói MyPackage lại có một số gói con như
SubPackage1, SubPackage2, ta có thể khai báo sử dụng các thành phần trong gói con
SubPackage1 như sau:
import MyPackage.SubPackage1.*;
Cách tạo ra các gói trong Java
Bước 1: Khai báo một gói trong Java
Giả sử ta khai báo một gói có tên là mypackage, bên trong gói này có lớp Calculator.
package mypackage;
public class Calculator
{
public double cong(double a,double b)
{
return a+b;
}
public double nhan(double a, double b)
{
return a*b;
}
public double tru(double a,double b)
{
return a-b;
}
public double chia(double a,double b) throws Exception
{
Sưu tầm bởi:
www.daihoc.com.vn
36
return a/b;
}
}
Bước 2: Biên dịch
C:\>javac -d C:\MyJava Calculator.java
Một vài điều cần lưu ý khi khai báo các thành viên của gói.
Thứ nhất, các thành phần của gói cần được khai báo với thuộc tính public, nếu cần truy
xuất chúng từ bên ngoài.
2.6. Quản lý ngoại lệ (Exception Handling)
Khái niệm
Trong quá trình xử lý, các ứng dụng có thể bất ngờ gặp các lỗi với các mức độ nghiêm
trọng khác nhau. Khi một phương thức tác động trên một đối tượng, đối tượng có thể
phát hiện các vấn đề trạng thái bên trong (chẳng hạn các giá trị không nhất quán, như
lỗi chia 0), phát hiện các lỗi với các đối tượng hay dữ liệu mà nó thao tác (như file hay
địa chỉ mạng) xác định nó vi phạm các qui tắc cơ bản (như đọc dữ liệu từ một luồng đã
bị đóng), Rất nhiều người lập trình không thể kiểm tra tất cả các trạng thái lỗi có thể
xảy ra.
Exception cung cấp một cách để kiểm tra các lỗi mà không chia cắt mã. Exception cũng
đưa ra một cơ chế báo lỗi một cách trực tiếp chứ không sử dụng các cờ hay các hiệu
ứng phụ.
Các ngoại lệ trong Java
Trong Java có một lớp Exception, mọi lớp ngoại lệ là lớp con của lớp này. Lớp
Exception là lớp con của lớp Throwable
Throwable
Exception
Sưu tầm bởi:
www.daihoc.com.vn
37
Hình 2.7
Lớp Throwable chứa một xâu được sử dụng để mô tả ngoại lệ. Ngoại lệ được phân
thành hai loại: Ngoại lệ được kiểm tra (checked exception) và ngoại lệ không được kiểm
tra (unchecked exception).
Ngoại lệ được kiểm tra là ngoại lệ mà trình biên dịch sẽ kiểm tra phương thức của
người lập trình và chỉ đưa ra ngoại lệ khi chúng được thông báo để đưa ra.
Ngoại lệ không được kiểm tra là lớp con của các lớp Error; RuntimeException.
Java cung cấp một mô hình quản lý các ngoại lệ cho phép kiểm tra các lỗi ở các vị trí có
liên quan.
Khối try và catch
Cú pháp
o Khối try
Bao gồm một tập hợp các lệnh có thể phát sinh ngoại lệ trong khi xử lý. Một phương
thức, có thể đưa ra một ngoại lệ cũng được đặt try
Các khối try lồng nhau
try{
stmt1;
stmt2;
try{
stmt3;
stmt4;
}
catch(Exception e)
{
}
}
catch(Exception e)
{
}
Khi các khối try được lồng nhau, khối try bên trong được xử lý trước và một ngoại lệ
được đưa ra trong khối đó được đón bắt trong các khối try catch con. Nếu khối catch
bên trong không thỏa mãn thì các khối try bên ngoài được kiểm tra. Nếu một khối catch
phù hợp được tìm thấy, thì ngoại lệ được quản lý trong khối đó ngược lại thì môi trường
Java Runtime quản lý ngoại lệ.
try
{
doFileProcessing();
Sưu tầm bởi:
www.daihoc.com.vn
38
displayResults();
}
catch(Exception e)
{
System. er.println(e.getMessage());
}
Bất kỳ lỗi nào xảy ra trong quá trình xử lý doFileProcessing() hay displayResult() thì sẽ
đựơc đón bắt bởi khối catch và được xử lý.
Nếu có lỗi xảy ra trong quá trình xử lý doFileProcessing(), phương thức displayResult()
sẽ không bao giờ được gọi, và khối catch sẽ được xử lý.
Một khối try có thể có nhiều khối catch và xử lý các kiểu khác nhau
try
{
}
catch(Exception e)
{
}
catch(Exception e)
{
}
finally
{
//Thực hiện công việc thu dọn
}
Ví dụ:
class TryCatch
{
public static void main(String[] args)
{int x,y;
try{
x=Integer.parseInt(args[0]);
y=Integer.parseInt(args[1]);
x=x/y;
System.out.println("x="+x);
}
Sưu tầm bởi:
www.daihoc.com.vn
39
catch(ArithmeticException e)
{
System.out.println("Khong the chia cho 0");
System.err.println(e);
}
}
}
Kết quả 1
C:\MyJava\Baitap>java TryCatch 18 9
x=2
Kết quả 2
C:\MyJava\Baitap>java TryCatch 9 0
Khong the chia cho 0
java.lang.ArithmeticException: / by zero
Khối finally
Khối finally là khối mà chúng ta thấy các lệnh trả về các tài nguyên cho hệ thống và các
lệnh khác để in ra bất kỳ thông báo nào.
Các lệnh trong khối finanally có thể là:
o Đóng một file.
o Đóng một resultset (Lập trình cơ sở dữ liệu).
o Ngắt liên kết được thiết lập với cơ sở dữ liệu.
…
Khối finally luôn được xử lý dù ngoại lệ có xảy ra hay không
Mệnh đề throw
Các ngoại lệ được đưa ra bằng cách sử dụng lệnh throw, nó nhận một đối tượng làm
tham số, đối tượng thuộc lớp là lớp con của lớp Throwable
Ví dụ:
class ArraySizeException extends NegativeArraySizeException
{
ArraySizeException()
{
super("Nhap kich thuoc mang khong hop le");
}
}
Sưu tầm bởi:
www.daihoc.com.vn
40
class ThrowDemo
{
int size, a[];
ThrowDemo(int s)
{
size =s;
try{
checkSize();
}
catch(ArraySizeException e)
{
System.out.println(e);
}
}
void checkSize() throws ArraySizeException
{
if(size<0) throw new ArraySizeException();
a= new int[3];
for(int i=0;i<3;i++)a[i]=i+1;
}
public static void main(String[] args)
{
new ThrowDemo(Integer.parseInt(args[0]));
}
}
Kết quả thực hiện chương trình
C:\MyJava\Baitap>java ThrowDemo -1
ArraySizeException: Nhap kich thuoc mang khong hop le
Giải thích:
Chúng ta đã tạo ra một lớp có tên ArraySizeException, lớp này là lớp con của lớp
NegativeArraySizeException. Bằng cách tạo ra một đối tượng của lớp này, chúng ta đã
in ra thông báo ngoại lệ. Phương thức checkSize() có thể đưa ra ngoại lệ
ArraySizeException.
không có ngoại lệ có ngoại lệ
try