Access modifier trong Java xác định quyền truy cập của class và các biến, phương thức của class đó từ bên ngoài class và package. Còn non-access modifier thì thay đổi thuộc tính của class và các biến, phương thức của class đó.
Ví dụ, abstract là một non-access modifier, nếu bạn thêm nó vào định nghĩa của một class nào đó, thì class đó sẽ trở thành abstract class. Và khi đó, không một class nào có thể khởi tạo được đối tượng cho class này.
Trong Java chúng ta có những non-access modifider sau:
- abstract
- static
- final
- synchronized
- native
- strictfp
- transient
- volatile
Trong bài viết này, mình sẽ đề cập 3 non-access modifier cơ bản thường dùng là abstract, static và final. Những non-access modifier khác, mình có thể nói qua tổng quan như sau:
- synchronized: non-access modifier này chỉ áp dụng cho phương thức. Nó có tác dụng tránh cho phương thức bị truy cập cùng lúc bởi nhiều thread khác nhau. Tại một thời điểm chỉ có duy nhất một thread gọi vào phương thức được đánh dấu là synchronized.
- native: non-access modifier này cũng chỉ áp dụng cho phương thức. Nó được sử dụng khi các bạn có sử dụng các thư viện được viết bằng các ngôn ngữ khác như C, C++.
- strictfp: non-access modifier này được sử dụng với class, interface và phương thức. Nó được dùng để đảm bảo rằng tính toán trên dấu chấm động có kết quả giống nhau trên tất cả các môi trường. Chúng ta không thể sử dụng non-access modifier này với các lớp abstract, các constructor và biến.
- transient: non-access modifier này được sử dụng trong Serialization, nó có tác dụng giúp trạng thái của biến không được lưu giữ trong quá trình Serialization. Các bạn có thể xem thêm bài viết Nói về biến transient trong Java mà mình đã viết. Transient chỉ có thể sử dụng với biến, không dùng được với class, interface và phương thức.
- volatile: non-access modifier này dùng để cập nhập giá trị của biến tới tất cả các thread đang sử dụng biến này mỗi khi giá trị của biến thay đổi. Nó không thể dùng với class, interface và phương thức. Các bạn có thể xem thêm bài viết Nói về biến volatile trong Java mà mình đã viết.
OK, giờ chúng ta cùng tìm hiểu ba non-access modifier dùng thường xuyên nhé các bạn.
abstract modifier
Như mình nói ở trên, khi một class đươc định nghĩa với abstract modifier, class khác không thể khởi tạo đối tượng cho class này.
Ví dụ sau cho định nghĩa một abstract class:
1 2 3 4 5 6 7 8 9 |
package com.huongdanjava; public abstract class Student { public String name = "Khanh"; public void goToSchool() { } } |
Lúc này, chúng ta không thể khởi tạo đối tượng cho class Student.
Một interface mặc định là một abstract. Chúng ta không cần thêm modifier abstract khi định nghĩa một interface, Java compiler sẽ tự động thêm vào cho mình.
Thêm modifier abstract chỉ là dư thừa mà thôi:
Đối với phương thức, khi định nghĩa với abstract modifier thì nó sẽ không được hiện thực bất cứ code nào trong phần thân của phương thức. Nhiệm vụ hiện thực code cho phương thức này sẽ xảy ra trong các class con kế thừa class chứa phương thức này.
Khi bạn định nghĩa một phương thức với abstract modifier thì bắt buộc class chứa phương thức này cũng phải được định nghĩa là abstract class, nếu không chúng ta sẽ bị lỗi compile ngay:
Abstract modifier không thể dùng được với biến, mọi cố gắng sử dụng nó với biến sẽ xảy ra lỗi compile
final modifier
Một class được đánh dấu với final modifier sẽ không thể extends từ các class khác.
Ví dụ, mình có class Student định nghĩa với final modifier như sau:
1 2 3 4 5 6 7 8 9 10 |
package com.huongdanjava; public final class Student { private String name = "Khanh"; public void goToSchool() { } } |
Và class khác sẽ không thể extends class Student
Interface không thể định nghĩa với final modifier. Nguyên nhân thì các bạn cũng hiểu, vì một interface muốn sử dụng được, phải có một class khác hiện thực nó. Nếu mà dùng được với final thì làm sao class khác hiện thực được. 😀
Một phương thức được định nghĩa với final modifier thì phương thức đó không thể bị ghi đè trong class con extends từ class chứa phương thức này. Mọi cố gắng chỉ làm cho code bị lỗi compile mà thôi.
Chúng ta có thể sử dụng final modifier với một biến, khi đó giá trị của biến sẽ không thay đổi được sau khi bạn gán giá trị cho biến đó lần đầu tiên.
Ví dụ:
static modifier
Biến static không phụ thuộc vào đối tượng của class và có thể truy cập được biến static này ngay cả khi không có đối tượng nào của class đó được khởi tạo.
Ví dụ, mình có class Student với biến name được định nghĩa là biến static như sau:
1 2 3 4 5 6 7 8 9 |
package com.huongdanjava; public class Student { public static String name = "Khanh"; public void goToSchool() { } } |
Khi đó, biến name có thể sử dụng được mà không cần khởi tạo bất kỳ đối tượng Student nào:
Thông thường chúng ta hay sử dụng static và final modifier để định nghĩa cho một biến với giá trị không thay đổi, ví dụ
1 2 3 4 5 6 7 8 9 |
package com.huongdanjava; public class Student { public static final String NAME = "Khanh"; public void goToSchool() { } } |
Một phương thức static thì không thuộc về đối tượng của class, và nếu một biến hoặc phương thức của class được sử dụng trong phương thức static thì bắt buộc biến hoặc phương thức đó phải được định nghĩa là static.
Đối với class và interface thì nếu chúng ta muốn định nghĩa chúng là static thì bắt buộc phải định nghĩa nó bên trong một class khác.
Ví dụ, chúng ta không thể định nghĩa static class hoặc interface ở class chính
nhưng chúng ta có thể định nghĩa nó bên trong class Student.