- Ba tuyến chính học Java hướng đối tượng:
(1) Lớp Java và các thành viên của lớp:
Thuộc tính, phương thức, hàm khởi tạo;
Khối mã, lớp nội bộ
(2) Ba đặc trưng chính của hướng đối tượng: Đóng gói, Kế thừa, Đa hình
(3) Các từ khóa khác: this, super, static, final...
- Phương pháp phân tích hướng đối tượng để giải quyết vấn đề:
(1) Dựa trên yêu cầu vấn đề, chọn thực thể trong thế giới thực liên quan đến vấn đề;
(2) Từ thực thể, tìm kiếm các thuộc tính và chức năng liên quan đến việc giải quyết vấn đề, những thuộc tính và chức năng này tạo thành lớp trong thế giới khái niệm;
(3) Mô tả thực thể trừu tượng bằng ngôn ngữ lập trình, tạo ra định nghĩa lớp trong thế giới máy tính. Nghĩa là sử dụng ngôn ngữ lập trình nhất định, xây dựng lớp thành cấu trúc dữ liệu mà máy tính có thể nhận diện và xử lý;
(4) Thực thể hóa lớp thành đối tượng trong thế giới máy tính. Đối tượng là công cụ cuối cùng để giải quyết vấn đề trong thế giới máy tính;
3.
import java.util.Arrays;
public class ChuongTrinhChinh {
public static void main(String[] args) {
Nguoi n1 = new Nguoi();
n1.tuoi = 30;
n1.ten = "Van A";
n1.gioiTinh = true;
Nguoi n3 = n1;
System.out.println(n3.ten);
}
}
class Nguoi{
int tuoi;
String ten;
Boolean gioiTinh;
public void noiChuyen ngonNgu(String ngonNgu){
System.out.println("Chúng tôi nói " + ngonNgu + " ngôn ngữ này");
}
}
Đoạn mã này gán địa chỉ đối tượng mà biến n1 lưu giữ cho n3, dẫn đến n1 và n3 cùng trỏ đến một đối tượng thực thể trong không gian堆;
- Biến thành viên so với biến cục bộ:
(1) Điểm giống nhau:
Các biến đều có phạm vi ứng dụng tương ứng
(2) Điểm khác nhau:
Vị trí khai báo trong lớp khác nhau:
Thuộc tính: Định nghĩa trực tiếp trong cặp {} của lớp;
Biến cục bộ: Khai báo bên trong phương thức, tham số phương thức, bên trong khối mã, tham số hàm khởi tạo, biến bên trong hàm khởi tạo;
ps: Sự khác biệt về sửa đổi quyền hạn:
Thuộc tính: Có thể chỉ định quyền hạn khi khai báo thuộc tính, sử dụng sửa đổi quyền hạn:
private, public, mặc định, protected;
Biến cục bộ: Không thể sử dụng sửa đổi quyền hạn;
Trường hợp khởi tạo mặc định:
Thuộc tính: Thuộc tính của lớp, tùy theo loại, đều có giá trị khởi tạo mặc định.
Kiểu nguyên: 0
Kiểu dấu phẩy động: 0.0
Kiểu ký tự: 0
Kiểu boolean: false
Kiểu dữ liệu tham chiếu (lớp, mảng, giao diện): null
Biến cục bộ: Không có giá trị khởi tạo mặc định.
Có nghĩa là, trước khi gọi biến cục bộ, chúng ta phải gán giá trị rõ ràng;
Vị trí tải trong bộ nhớ:
Thuộc tính: Tải vào không gian堆;
Biến cục bộ: Tải vào không gian栈;
-
Khi sử dụng phương thức, có thể gọi thuộc tính hoặc phương thức của lớp hiện tại;
-
Giải thích phân tích bộ nhớ:
Biến kiểu tham chiếu, chỉ có thể lưu trữ hai loại giá trị: null hoặc giá trị địa chỉ;
- Mảng sinh viên:
import java.util.Arrays;
public class ChuongTrinhChinh {
public static void main(String[] args) {
SinhVien[] sv = new SinhVien[5];
sv[0] = new SinhVien();
System.out.println(sv[0].maSo);
}
}
class SinhVien {
int maSo;
int lop;
int diem;
}
Kết quả chạy như vậy là: 0; Nhưng nếu thiếu sv[0] = new SinhVien(); dòng mã này, sẽ kích hoạt ngoại con trống null, vì chỉ định nghĩa mảng, giá trị khởi tạo mặc định bên trong là null, cần new một đối tượng cho nó (mảng sinh viên lưu trữ địa chỉ); mới có thể sử dụng nó để gọi thuộc tính và phương thức;
- Đối tượng ẩn danh: Có thể không đặt tên cho đối tượng, new đối tượng trực tiếp rồi gọi phương thức của nó:
import java.util.Arrays;
public class ChuongTrinhChinh {
public static void main(String[] args) {
new DienThoai().guiEmail();
}
}
class DienThoai{
double gia;
public void guiEmail(){
System.out.println("Gửi email");
}
public ChoiGame(){
System.out.println("Chơi game");
}
public void hienThiGia(){
System.out.println("Giá là " + gia);
}
}
Nhưng mỗi lần đều new một đối tượng mới; có nghĩa là, đối tượng thu được theo cách này chỉ có thể sử dụng một lần;
import java.util.Arrays;
public class ChuongTrinhChinh {
public static void main(String[] args) {
new DienThoai().gia = 2000;
new DienThoai().hienThiGia();
}
}
class DienThoai{
double gia;
public void guiEmail(){
System.out.println("Gửi email");
}
public void choiGame(){
System.out.println("Chơi game");
}
public void hienThiGia(){
System.out.println("Giá là " + gia);
}
}
- Nạp chồng phương thức (Nguyên tắc đánh giá: hai giống một khác: cùng lớp, cùng tên, khác danh sách tham số):
(1) Trong cùng một lớp, cho phép nhiều hơn một phương thức cùng tên, miễn là số lượng và loại tham số của chúng khác nhau;
(2) Không liên quan đến kiểu trả về, chỉ xem danh sách tham số;
(3) Không liên quan đến sửa đổi quyền hạn của phương thức, tên biến tham số, nội dung phương thức;
- Cơ chế truyền giá trị tham số phương thức trong Java:
Cách giá trị tham số thực tế được truyền vào phương thức (chỉ có một cách truyền: truyền giá trị):
Nghĩa là truyền bản sao giá trị tham số thực tế vào phương thức, trong khi tham số bản thân không bị ảnh hưởng:
(1) Tham số là kiểu dữ liệu cơ bản: Truyền giá trị dữ liệu của tham số thực tế cho tham số hình thức;
(2) Tham số là kiểu dữ liệu tham chiếu: Truyền giá trị địa chỉ của biến tham số thực tế cho tham số hình thức;
import java.util.Arrays;
public class ChuongTrinhChinh {
public static void main(String[] args) {
DonHang dh1 = new DonHang();
DonHang dh2 = dh1;
dh1.maDon = 1001;
System.out.println(dh2.maDon);
dh2.maDon = 1002;
System.out.println(dh1.maDon);
}
}
class DonHang{
int maDon;
}
Ví dụ trên giải thích quy luật này: dh1 và dh2 có giá trị địa chỉ giống nhau, đều trỏ đến cùng một đối tượng thực thể trong không gian堆;
Đồng thời rút ra quy luật: Về việc gán giá trị biến:
Nếu biến là kiểu dữ liệu cơ bản: Lúc này gán là giá trị dữ liệu mà biến lưu trữ;
Nếu là kiểu dữ liệu tham chiếu: Gán là giá trị địa chỉ mà biến lưu trữ;
import java.util.Arrays;
public class ChuongTrinhChinh {
public static void main(String[] args) {
int x = 10;
int y = 20;
ChuongTrinhChinh ct = new ChuongTrinhChinh();
ct.hoanDoi(x, y);
System.out.println(x + "," + y);
}
public void hoanDoi(int a, int b){
int temp = a;
a = b;
b = temp;
}
}
Cách viết phương thức hoán đổi như vậy hoàn toàn không đạt được mục đích;
Vì sau khi gọi xong, biến cục bộ bên trong sẽ được coi là rác và thu hồi bộ nhớ, in ra là x và y được định nghĩa trong phương thức main;
Cách thực hiện khả thi là đặt x và y vào thuộc tính của một đối tượng, thông qua truyền đối tượng làm tham số, để thực hiện phương thức hoán đổi:
import java.util.Arrays;
public class ChuongTrinhChinh {
public static void main(String[] args) {
DuLieu dl = new DuLieu();
dl.x = 10;
dl.y = 20;
ChuongTrinhChinh test = new ChuongTrinhChinh();
test.hoanDoi(dl);
System.out.println(dl.x + "," + dl.y);
}
public void hoanDoi(DuLieu data) {
int temp = data.x;
data.x = data.y;
data.y = temp;
}
}
class DuLieu{
int x;
int y;
}
- Đóng gói và ẩn giấu:
Chúng ta hướng tới thiết kế chương trình "độ gắn kết cao, độcoupling thấp" trong thiết kế chương trình;
Độ gắn kết cao có nghĩa là một mô-đun chỉ tập trung vào việc hoàn thành một nhiệm vụ hoặc trách nhiệm duy nhất, các yếu tố bên trong mô-đun có mối liên hệ chặt chẽ. Ví dụ, một lớp chuyên chịu trách nhiệm xác thực người dùng, như xác thực tên người dùng, mật khẩu và tạo mã thông báo, đều do lớp đó thực hiện, mà không liên quan đến các chức năng khác không liên quan như xử lý tệp hoặc kết nối cơ sở dữ liệu.
Độcoupling thấp có nghĩa là mối quan hệ phụ thuộc giữa các mô-đun rất yếu, việc sửa đổi một mô-đun sẽ không ảnh hưởng đến các mô-đun khác. Ví dụ, mô-đun giao diện người dùng và mô-đun truy cập cơ sở dữ liệu tương tác thông qua giao diện trừu tượng, thay vì gọi trực tiếp các lớp cụ thể.
- Ví dụ thể hiện tính đóng gói: Chúng ta私有 hóa thuộc tính của lớp, đồng thời cung cấp các phương thức công khai public để lấy và đặt giá trị thuộc tính (mục đích: giới hạn giá trị thuộc tính được đặt,使其满足 các điều kiện giới hạn chúng ta đã đề ra):
import java.util.Arrays;
public class ChuongTrinhChinh {
public static void main(String[] args) {
DongVat d1 = new DongVat();
d1.setSoChan(10);
System.out.println(d1.getSoChan());
}
}
class DongVat {
private int soChan;
public void setSoChan(int s){
if (s >= 0 && s % 2 == 0 ){
soChan = s;
}
}
public int getSoChan(){
return soChan;
}
}
- Bốn sửa đổi quyền hạn:
Đối với sửa đổi quyền hạn của lớp, chỉ có thể sử dụng public và default;
(1) Bốn quyền hạn có thể sửa đổi: cấu trúc bên trong lớp, bao gồm thuộc tính, phương thức, hàm khởi tạo, lớp nội bộ;
- Hàm khởi tạo của lớp:
import java.util.Arrays;
public class ChuongTrinhChinh {
public static void main(String[] args) {
Nguoi p = new Nguoi();
}
}
class Nguoi {
String ten;
int tuoi;
public Nguoi(){
System.out.println("Nguoi()...");
}
}
Lưu ý:
(1) Nếu không xác định rõ ràng hàm khởi tạo của lớp, hệ thống sẽ mặc định cung cấp một hàm khởi tạo tham số rỗng;
(2) Chức năng của hàm khởi tạo:
2.1 Khởi tạo đối tượng
2.2 Khởi tạo thuộc tính của đối tượng
2.3 Nếu có nhiều hàm khởi tạo, chúng nạp chồng với nhau;
2.4 Nếu đã định nghĩa rõ ràng hàm khởi tạo của lớp, hệ thống sẽ không còn cung cấp hàm khởi tạo mặc định;
- Thứ tự gán giá trị thuộc tính: (1) -> (2) -> (3) -> (4)
(1) Khởi tạo mặc định
(2) Khởi tạo rõ ràng
(3) Gán giá trị trong hàm khởi tạo
(4) Gán giá trị thông qua "đối tượng.phương thức" hoặc "đối tượng.thuộc tính"