Có những công cụ sửa đổi quyền truy cập nào trong java. Các công cụ sửa đổi Java: tĩnh, cuối cùng, trừu tượng, đồng bộ hóa, tạm thời, dễ bay hơi

Ở đây chúng tôi sẽ cố gắng đề cập đến hầu hết các trường hợp sử dụng công cụ sửa đổi quyền truy cập. Các ngoại lệ duy nhất là việc sử dụng chúng cho lồng nhau ( lồng vào nhau) và nội bộ ( bên trong) các lớp, cũng như đối với các giao diện, vì chúng tôi chưa xem xét các chủ đề này.

Các lớp và gói được sử dụng cùng với các công cụ sửa đổi truy cập đóng vai trò là phương tiện đóng gói, tức là phương tiện ẩn các chi tiết triển khai đằng sau một giao diện đơn giản.

Các công cụ sửa đổi quyền truy cập có thể được áp dụng cho cả các lớp và các thành viên của chúng - các trường và phương thức. Tổng cộng có bốn công cụ sửa đổi quyền truy cập và ở đây chúng tôi sẽ mô tả ngắn gọn về chúng, sau đó chúng tôi sẽ xem xét chi tiết từng công cụ.

  • công cộng- bất kỳ thành phần nào được khai báo là công cộng, có thể truy cập từ bất kỳ mã nào
  • được bảo vệ- cho phép truy cập vào thành phần trong gói và các lớp con cháu
  • riêng- cho phép truy cập vào các thành phần trong lớp
  • vỡ nợ(không có từ khóa) - Cho phép truy cập vào các thành phần trong gói

Các lớp kế thừa là các lớp được kế thừa từ một lớp. Chúng tôi chưa nghiên cứu tính kế thừa.

Tiếp cận các lớp học

Theo mặc định, các lớp cấp cao nhất có sẵn trong gói mà chúng được định nghĩa.... Tuy nhiên, nếu lớp cấp cao nhất được khai báo là công cộng sau đó nó có sẵn ở mọi nơi (hoặc bất cứ nơi nào mà gói chính nó có sẵn). Chúng tôi đã giới hạn câu lệnh này cho các lớp cấp cao nhất vì các lớp có thể được khai báo là thành viên của các lớp khác. Vì các lớp bên trong này là thành viên của lớp nên chúng tuân theo các quy tắc kiểm soát quyền truy cập vào các thành viên trong lớp..

Tiếp cận các thành viên trong lớp

Các thành viên của lớp luôn có sẵn bên trong cơ thể của lớp. Vỡ nợ các thành viên lớp cũng có sẵn trong gói mà lớp được định nghĩa.

Công cụ sửa đổi

Đối với một lớp không được lồng vào nhau, chỉ có thể chỉ định một trong hai mức truy cập có thể có: vỡ nợcông cộng . Khi lớp được khai báo là công cộng, nó phải là người duy nhất công cộng lớp được khai báo trong tệp và tên tệp phải khớp với tên lớp.

Làm sao công cộng các lớp, trường, phương thức và hàm tạo có thể được khai báo.

Công cụ sửa đổi được bảo vệ

Chúng ta sẽ xem xét kỹ hơn công cụ sửa đổi này trong chủ đề kế thừa lớp. Nếu kế thừa không được sử dụng, thì công cụ sửa đổi này hoạt động, giống như công cụ sửa đổi mặc định.

Điều duy nhất có thể nói ngắn gọn bây giờ là các thành phần được khai báo là được bảo vệ sẽ có quyền truy cập bất kỳ lớp trẻ nào từ bất kỳ gói nào hoặc bất kỳ lớp nào từ cùng một gói.

Làm sao được bảo vệ các trường, phương thức, hàm tạo, lớp lồng nhau và giao diện lồng nhau có thể được khai báo.

được bảo vệ .

Công cụ sửa đổi riêng

Đây là công cụ sửa đổi hạn chế nhất về giới hạn truy cập. Các mặt hàng được khai báo là riêng chỉ có thể truy cập trong cùng một lớp và không ai bên ngoài lớp đó.

Làm sao riêng các trường, phương thức, hàm tạo, lớp lồng nhau và giao diện lồng nhau có thể được khai báo.

Các lớp và giao diện cấp cao nhất không thể được khai báo là riêng .

Về cơ bản, công cụ sửa đổi quyền truy cập là một chủ đề đơn giản, nhưng chúng ta sẽ quay lại với chúng sau. Trong khi đó chỉ là một người quen. Và bây giờ một chút thực hành ...

Tôi đã tạo các lớp Mod02.java, DefMod.java, ProMod.java và PrvMod.java thuộc gói pro.java.pkg002, cũng như lớp PubMod.java thuộc gói pro.java.pkg003. Tiếp theo, tôi sẽ chỉ cung cấp ảnh chụp màn hình của các lớp này và kết quả của chương trình:

Ngôn ngữ Java cung cấp nhiều bổ ngữ, được chia thành các loại sau:

  • công cụ sửa đổi truy cập
  • Công cụ sửa đổi không truy cập

Một bổ ngữ được sử dụng để xác định một lớp, phương thức hoặc biến, thường ở đầu một câu lệnh. Qua ví dụ minh họa sau:

Lớp public className (// ...) private boolean myFlag; tĩnh cuối tuần kép = 9,5; static cuối cùng được bảo vệ int BOXWIDTH = 42; public static void main (Đối số chuỗi) (// 方法 小)

Công cụ sửa đổi kiểm soát truy cập

Java, bạn có thể sử dụng các ký tự điều khiển truy cập để bảo vệ quyền truy cập vào các lớp, biến, phương thức và hàm tạo. Java hỗ trợ bốn quyền khác nhau.

Giá trị mặc định, còn được gọi là giá trị theo vỡ nợ, hiển thị trong cùng một gói, không sử dụng bất kỳ công cụ sửa đổi nào.

Riêng tư đối với được chỉ định riêng một bổ ngữ hiển thị trong cùng một lớp.

Có, để chỉ ra chung sửa đổi hiển thị cho tất cả các lớp.

Được bảo vệ, trong được bảo vệ trình sửa đổi chỉ định rằng tất cả các lớp và lớp con trong cùng một gói đều có thể nhìn thấy được.

Công cụ sửa đổi quyền truy cập mặc định không sử dụng bất kỳ từ khóa nào

Sử dụng các biến và phương thức được khai báo trong công cụ sửa đổi truy cập mặc định cho một lớp trong cùng một gói hiển thị. Một giao diện trong đó các biến được khai báo ngầm là cuối cùng tĩnh công khai và một giao diện nơi công cụ truy cập mặc định là công khai.

Câu lệnh trong ví dụ sau, các biến và phương thức không thể sử dụng bất kỳ công cụ sửa đổi nào.

Phiên bản chuỗi = "1.5.1"; boolean processOrder () (trả về true;)

Công cụ sửa đổi quyền truy cập riêng tư-riêng tư

Phần bổ trợ truy cập riêng là mức truy cập cứng nhất, nó được khai báo là các phương thức, biến riêng và thuộc về lớp phương thức khởi tạo chỉ có thể được truy cập, nhưng các lớp và giao diện không thể được khai báo là private.

Các biến được khai báo là kiểu truy cập riêng tư chỉ có thể được truy cập bên ngoài lớp thông qua lớp phương thức getter công khai.

Công cụ sửa đổi Private Access được sử dụng chủ yếu cho lớp bảo vệ các chi tiết triển khai và dữ liệu đằng sau lớp.

Các lớp sau sử dụng công cụ sửa đổi quyền truy cập riêng tư:

Public class Logger (private String format; public String getFormat () (return this.format;) public void setFormat (String format) (this.format = format;))

Ví dụ, định dạng biến của lớp Logger là một biến riêng để các lớp khác không thể trực tiếp lấy và đặt giá trị của biến. Để có thể làm việc với một biến khác, lớp định nghĩa hai phương thức công khai: GetFormat () (định dạng giá trị trả về) và SetFormat (Chuỗi) (thiết lập định dạng)

Mở công cụ sửa đổi quyền truy cập -public

Nó được khai báo là các lớp công khai, phương thức, hàm tạo và giao diện có thể là bất kỳ kiểu truy cập nào khác.

Nếu nhiều lượt truy cập đối ứng của các lớp công khai nằm trong các gói khác nhau, bạn cần nhập gói lớp công khai tương ứng cư trú. Bởi vì kế thừa lớp, một lớp của tất cả các phương thức và biến công khai có thể được kế thừa bởi các lớp con của nó.

Các tính năng sau sử dụng kiểm soát truy cập công khai:

Công khai tĩnh void main (Đối số chuỗi) (// ...)

Phương thức Java program () chính phải được cài đặt ở những nơi công cộng, nếu không trình thông dịch Java sẽ không thể chạy lớp.

Các công cụ sửa đổi quyền truy cập được bảo vệ được bảo vệ

Được khai báo là các biến, phương thức và hàm tạo được bảo vệ trong cùng một gói có thể thuộc bất kỳ kiểu truy cập nào khác và có thể được truy cập trong các gói khác nhau của lớp con.

Công cụ sửa đổi quyền truy cập được bảo vệ không thể được sửa đổi bởi các lớp và giao diện, các phương thức và biến thành viên có thể được khai báo là bảo vệ, nhưng không thể khai báo các biến và phương thức thành viên của giao diện được bảo vệ.

sửa đổi Các lớp con có thể được truy cập bằng các Phương thức và Biến được Bảo vệ đã khai báo, để chúng ta có thể bảo vệ các lớp không liên quan bằng cách sử dụng các phương thức và biến này.

Lớp cha sau sử dụng công cụ sửa đổi quyền truy cập được bảo vệ, các lớp con ghi đè phương thức openSpeaker () của lớp cha.

Class AudioPlayer (boolean openSpeaker (Speaker sp) (// 实现 细节)) class StreamingAudioPlayer (boolean openSpeaker (Speaker sp) (// 实现 细节))

Nếu phương thức openSpeaker () được khai báo là private, thì ngoài lớp AudioPlayer, nó không thể truy cập phương thức. Nếu openSpeaker () được khai báo là public, thì tất cả các lớp đều có khả năng truy cập vào phương thức. Nếu chúng ta muốn làm cho quá trình hiển thị với các lớp con của lớp, thì phương thức được khai báo là bảo vệ.

Kiểm soát truy cập và kế thừa

Lưu ý các quy tắc kế thừa các phương pháp sau:

    Lớp cha được khai báo là các phương thức public trong lớp con cũng phải public.

    Lớp cha được khai báo như một phương thức được bảo vệ trong lớp con, hoặc được khai báo là được bảo vệ, hoặc được khai báo công khai. Bạn không thể được tuyên bố là riêng tư.

    Lớp cha được khai báo là một phương thức private và không thể được kế thừa.

Công cụ sửa đổi không truy cập

Để đạt được một số tính năng khác, Java cũng cung cấp một số công cụ sửa đổi không truy cập.

static modifier được sử dụng để tạo các phương thức lớp và biến lớp.

Phần bổ trợ cuối cùng dùng để trang trí các lớp, phương thức và biến, lớp sửa đổi cuối cùng không thể kế thừa, phương thức lớp đã sửa đổi không thể kế thừa, ghi đè, hằng số biến sửa đổi không thể thay đổi.

Công cụ sửa đổi trừu tượng được sử dụng để tạo các lớp trừu tượng và các phương thức trừu tượng.

Các công cụ sửa đổi đồng bộ và dễ bay hơi, chủ yếu dành cho các luồng lập trình.

Công cụ sửa đổi tĩnh

    Biến tĩnh:

    Từ khóa static dùng để khai báo các biến static độc lập với đối tượng, cho dù instance của lớp có bao nhiêu đối tượng thì nó cũng chỉ là một bản sao của biến static. Biến tĩnh còn được gọi là biến lớp. Biến cục bộ không thể được khai báo là biến tĩnh.

    Phương pháp tĩnh:

    Từ khóa static dùng để khai báo một đối tượng độc lập với phương thức static. Phương thức static không thể sử dụng lớp biến non-static. Phương thức tĩnh để lấy dữ liệu từ danh sách tham số và sau đó tính toán dữ liệu.

Quyền truy cập vào các biến và phương thức của lớp có thể được sử dụng trực tiếp bởi các trình truy cập classname.variablename và classname.methodname.

Trong ví dụ sau, một công cụ sửa đổi tĩnh được sử dụng để tạo các phương thức lớp và biến lớp.

Public class InstanceCounter (private static int numInstances = 0; protected static int getCount () (return numInstances;) private static void addInstance () (numInstances ++;) InstanceCounter () (InstanceCounter.addInstance ();) public static void main ( Đối số chuỗi) (System.out.println ("Bắt đầu bằng" + InstanceCounter.getCount () + "thể hiện"); for (int i = 0; i< 500; ++i){ new InstanceCounter(); } System.out.println("Created " + InstanceCounter.getCount() + " instances"); } }

Ví dụ về kết quả trên từ thao tác chỉnh sửa như sau:

Bắt đầu với 0 phiên bản Đã tạo 500 phiên bản

Bộ phân loại cuối cùng

Các biến cuối cùng:

Các biến cuối cùng có thể được khởi tạo rõ ràng và chỉ được khởi tạo một lần. Thư mục được khai báo là các đối tượng lá không thể trỏ đến đối tượng khác. Nhưng mục tiêu cuối cùng là nơi dữ liệu có thể được thay đổi. Tham chiếu đối tượng cuối cùng này không thể thay đổi, nhưng có thể thay đổi giá trị của nó.

Bổ ngữ cuối cùng thường được sử dụng cùng nhau để tạo một hằng số tĩnh của lớp bổ trợ.

Kiểm tra lớp công khai (giá trị int cuối cùng = 10; // 下面 是 声明 常量 的 实例 public static final int BOXWIDTH = 6; static final String TITLE = "(! LANG: Manager"; public void changeValue(){ value = 12; //将输出一个错误 } } !}

Phương pháp cuối cùng

Các phương thức của lớp cuối cùng được kế thừa bởi các lớp con, nhưng không thể sửa đổi các lớp con.

Mục đích chính của một phương thức là ngăn câu lệnh cuối cùng của phương thức đó bị thay đổi.

Như sẽ được hiển thị bên dưới, sử dụng các phương thức cuối cùng của các bổ trợ khai báo.

Kiểm tra lớp công khai (public Final void changeName () (// 方法 小))

Hạng mục cuối cùng

Các lớp cuối cùng không thể được kế thừa, không lớp nào có thể kế thừa bất kỳ đặc điểm nào của lớp cuối cùng.

Bài kiểm tra cuối cùng của lớp công khai (// 类 小)

Bổ ngữ trừu tượng

Lớp trừu tượng:

Một lớp trừu tượng không thể được sử dụng để khởi tạo một đối tượng, mục đích duy nhất của câu lệnh là lớp trừu tượng cho các phần mở rộng trong tương lai của lớp đó.

Lớp không thể được thay đổi trừu tượng và cuối cùng. Nếu lớp chứa các phương thức trừu tượng, thì lớp đó phải được khai báo là lớp trừu tượng, nếu không, sẽ xảy ra lỗi trình biên dịch.

Một lớp trừu tượng có thể chứa các phương thức trừu tượng và các phương thức không trừu tượng.

Tóm tắt lớp Caravan (private giá đôi; private String model; private String year; public abstract void goFast (); // 抽象 方法 public abstract void changeColor ();)

Phương pháp trừu tượng

Không có phương thức nào là một triển khai phương thức trừu tượng, một triển khai phương thức cụ thể của các lớp con được cung cấp. Các phương thức trừu tượng không thể được khai báo cuối cùng và nghiêm ngặt.

Bất kỳ lớp con nào kế thừa từ một lớp trừu tượng phải thực hiện tất cả các phương thức trừu tượng của lớp cha, trừ khi lớp con là một lớp trừu tượng.

Nếu lớp chứa một số phương thức trừu tượng, thì lớp đó phải được khai báo là lớp trừu tượng. Một lớp trừu tượng không thể chứa các phương thức trừu tượng.

Một khai báo phương thức trừu tượng kết thúc bằng dấu chấm phẩy, ví dụ: public abstract pattern ();

Lớp trừu tượng công khai SuperClass (abstract void m (); // 抽象 方法) Lớp SubClass mở rộng SuperClass (// 实现 抽象 方法 void m () (.........))

Công cụ sửa đổi đồng bộ

Phương thức từ khóa đồng bộ để khai báo chỉ một luồng truy cập cùng một lúc. Một công cụ sửa đổi đồng bộ có thể được áp dụng cho bốn công cụ sửa đổi truy cập.

Công khai đồng bộ hóa void showDetails () (.......)

Công cụ sửa đổi nhất thời

Đối tượng tuần tự hóa chứa các biến tạm thời của phiên bản máy ảo java (JVM) đã được sửa đổi để bỏ qua biến cụ thể này.

Một công cụ sửa đổi được bao gồm trong định nghĩa biến khai báo để xử lý trước kiểu dữ liệu và các lớp biến.

Công khai tạm thời int giới hạn = 55; // sẽ không tồn tại public int b; // sẽ tồn tại

Bộ điều chỉnh dễ bay hơi

Một biến thành viên được sửa đổi dễ bay hơi buộc phải đọc lại giá trị của biến thành viên từ bộ nhớ dùng chung mỗi khi nó được truy cập. Ngoài ra, khi các biến thành viên thay đổi, luồng buộc phải thay đổi giá trị đang được ghi trở lại bộ nhớ chia sẻ. Vì vậy, tại bất kỳ thời điểm nào, hai chủ đề khác nhau luôn thấy cùng một giá trị biến thành viên.

Lớp công khai MyRunnable triển khai Runnable (riêng boolean dễ bay hơi đang hoạt động; public void run () (active = true; while (active) // 第一 行 (// 代码)) public void stop () (active = false; // 第二行))

Trong trường hợp bình thường, một luồng gọi phương thức Run () (trên một luồng mở Runnable) trong một luồng gọi phương thức stop () khác. Nếu giá trị hoạt động trong dòng đầu tiên đệm được sử dụng trong hàng thứ hai khi chu kỳ hoạt động là sai, nó không dừng lại.

Tuy nhiên, trong đoạn mã trên, chúng ta đang sử dụng một kích hoạt biến động đã được sửa đổi, vì vậy vòng lặp sẽ dừng lại.

Lớp bổ trợ
Lớp Modifier mã hóa tất cả các modifier,
được sử dụng trong khai báo kiểu, trong biểu mẫu
hằng số:
TÓM TẮT, CUỐI CÙNG, GIAO DIỆN, TỰ NHIÊN,
RIÊNG TƯ, ĐƯỢC BẢO VỆ, CÔNG CỘNG, THỐNG KÊ,
NGHIÊM TÚC, ĐỒNG BỘ HÓA, TRANSIDENT,
BAY HƠI.
Mỗi hằng số có một phương thức yêu cầu của biểu mẫu
isMod (int modifier) ​​(ở đây Mod là một trong những điều trên
tên đã cho, ví dụ, isPublic),
trả về true nếu công cụ sửa đổi
mod có trong khai báo kiểu.

Hãy xem một ví dụ. Để đó đi
khai báo hiện trường
public static final int s = 10;
thì giá trị được trả về bởi phương thức
getModifier của đối tượng tương ứng
lớp Field sẽ trông như thế nào
Modifier.PUBLIC | Modifier.STATIC |
Modifier.FINAL
Công cụ sửa đổi nghiêm ngặt được giới thiệu
NGHIÊM TÚC liên tục.
Phương thức - truy vấn có thể được sử dụng trong
mẫu sau

Modifier.isPrivate (field.getModifiers ());
điều này tương đương với điều kiện sau
(field.getModifiers () & Modifier.PRIVATE)! = 0
Lớp thực địa
Là một phần của lớp Field, các phương thức được triển khai,
cho phép yêu cầu thông tin về
loại trường, cũng như đọc và đặt nó
Ý nghĩa.
Hãy xem xét một số phương thức của lớp Field
1.getType () - trả về một đối tượng lớp
Lớp tương ứng với kiểu của trường hiện tại.
Ví dụ, đối với một trường kiểu int, chúng ta nhận được
int.class.

2. Phương thức đặt và nhận - cho phép bạn đọc
giá trị hiện tại của trường và cũng đặt một giá trị mới.
Hãy xem xét một ví dụ:
public static void printField (Đối tượng o,
Chuỗi tên) ném
NoSuchFieldException,
IllegalAccessException (
Trường Field = o.getClass (). GetField (tên);
Giá trị ngắn = (Ngắn) field.get (o);
System.out.println (giá trị);
}
Những thứ kia. phương thức get trả về giá trị mà theo đó
đề cập đến trường hoặc đối tượng tương ứng
lớp-vỏ.
Một ví dụ về việc sử dụng phương thức set trông như thế này:

public static void setField (Đối tượng o, Tên chuỗi,
nv ngắn) ném
NoSuchFieldException,
IllegalAccessException (
Trường Field = o.getClass (). GetField (tên);
field.set (o, new Short (nv));
}
Để lưu trữ nv trong một trường của một đối tượng nhất định
bạn cần sử dụng các lớp trình bao bọc.
Ngoài ra còn có các phương pháp có dạng
getPrimitiveType (như getInt) và
setPrimitiveType. Những phương pháp này có thể
sử dụng để thay đổi các trường trong một lớp,
có một kiểu nguyên thủy. Ví dụ,
field.setShort (o, nv);

Lớp phương pháp
Các công cụ của lớp Phương pháp - cho phép bạn có được
thông tin đầy đủ về
khai báo phương thức của một lớp nhất định,
và gọi các phương thức này trong
bối cảnh của các đối tượng đã cho.
Xem xét các phương thức của lớp Method.
1.public Class getReturnType () - trả về
đối tượng Lớp tương ứng với kiểu
giá trị được trả về bởi phương thức hiện tại.
Nếu thay vì trả về, hãy nhập
khai báo phương thức chỉ định một dịch vụ
từ vô hiệu, phương thức được đề cập sẽ trả về
đối tượng void.class.

2.public Class getParameterTypes () - trả về

các tham số được chỉ định trong khai báo
phương pháp hiện tại. Các đối tượng được nhập vào một mảng tại
theo thứ tự mà các tham số được liệt kê trong
khai báo phương thức. Nếu phương pháp không có
tham số, một mảng trống được trả về.
3.public Class getExceptionTypes () - trả về
một mảng các đối tượng Lớp tương ứng với các kiểu
ngoại lệ được chỉ định trong câu
khai báo ném của phương thức hiện tại. Các đối tượng
được nhập vào mảng theo thứ tự
tên của các loại ngoại lệ được liệt kê trong
khai báo phương thức.

4. gọi đối tượng công khai (Đối tượng onThis, Đối tượng args)
ném IllegalAccessException,
Ngoại lệ Đối số bất hợp pháp,
Đưa ra những mục tiêu ngoại lệ
Gọi phương thức được xác định bởi đối tượng hiện tại
Phương thức, trong ngữ cảnh của một đối tượng onThis với một phép gán
giá trị của các đối số được truyền bởi mảng args.
Đối với các phương thức không tĩnh, sự lựa chọn triển khai
được thực hiện trên cơ sở của loại thực tế
đối tượng được xác định bởi tham số onThis. Vì
phương thức tĩnh trên Điều này không được chấp nhận trong
chú ý và có thể vô hiệu.
Độ dài của mảng args phải bằng một số
các tham số trong khai báo phương thức và các kiểu đối tượng của các phần tử mảng phải có thể gán được
các loại tham số phương pháp tương ứng - trong
nếu không một ngoại lệ sẽ được ném ra
IIlegalArgumentException.

10.

Nếu thành phần của đối tượng xác định
onThis, no type, member
đó là phương pháp hiện tại,
một ngoại lệ được ném ra
Ngoại lệ Đối số bất hợp pháp.
Nếu onThis là null và phương thức không
static, một loại ngoại lệ được ném
NullPointerException.
Nếu việc thực thi phương thức được gọi
chấm dứt bất thường, bị vứt bỏ
một ngoại lệ của kiểu InvocationTargetException.

11.

Hãy xem một ví dụ. Hãy gọi bằng cách
phương thức phản ánh return str.indexOf (".", 8)
sau đó chúng tôi có
cố gắng (
Сlass strClass = str.getClass ();
Phương thức indexM = strClass.getMethod ("indexOf",
new Class (string.class, int.class));
Kết quả đối tượng = indexM.invoke (str, đối tượng mới (
".", new lnteger (8)));
return ((Số nguyên) kết quả) .intValue ();
}
bắt (NoSuchMethodException e) (…… ..)
bắt (invocationTargetException e) (…… ..)
bắt (bất hợp phápAccessException e) (……)

12.

Lớp xây dựng
Để tạo các phiên bản (đối tượng) mới
phương pháp loại có thể được sử dụng
mới của đối tượng Lớp,
tương ứng với loại này.
Phương thức này gọi hàm tạo không có đối số,
thuộc về loại và trả về một tham chiếu
đến một đối tượng mới được tạo của lớp Đối tượng,
phải được chuyển đổi rõ ràng thành
loại bắt buộc.
Hãy xem một ví dụ.

13.

static double testData = (0,3,1.3e-2, 7,9, 3,17);

cố gắng (
for (int arg = 0; arg< args.length; arg++){
Tên chuỗi = args;
Lớp classFor = Class.forName (tên);
SortDouble sắp xếp =
(SortDouble) classFor.newInstance ();
SortMetrics metrics = sorter.sort (testData);
System.out.println (tên + ":" + số liệu);
for (int i = 0; i< testData.length; i++)
System.out.println (“" + testData [i]);))
bắt (Ngoại lệ e) (System.err.println (e);))

14.

Phương pháp mới khi không chính xác
ứng dụng có khả năng ném ra lớn
số lượng các đối tượng ngoại lệ khác nhau
các loại.
InstantiationException - nếu lớp, đối tượng
thứ nên được tạo ra không sở hữu
một hàm tạo không có đối số, hoặc
được định nghĩa là trừu tượng, hoặc trong
thực sự là một giao diện,
hoặc thực hiện thủ tục tạo
đối tượng bị gián đoạn vì bất kỳ cái nào khác
lý do.
IllegalAccessException - nếu lớp là của nó
không có hàm tạo đối số nào khả dụng.

15.

SecurityException - nếu chính sách hợp lệ
an ninh nghiêm cấm việc tạo ra các đối tượng mới
ExceptionInInitializerError - Ném khi
khởi tạo lớp.
Các phương thức khác được định nghĩa trong lớp Constructor.
public Сlass getParameterTypes ()

tương ứng với các loại tham số
được chỉ định trong khai báo phương thức khởi tạo hiện tại.
public Class getExceptionTypes ()
Trả về một mảng các đối tượng Lớp,
tương ứng với các loại ngoại lệ
đặt trong mệnh đề ném của khai báo
hàm tạo hiện tại.

16.

public Object newlnstance (Object args)
ném InstantiationException,
IllegalAccessException,
Ngoại lệ Đối số bất hợp pháp,
Đưa ra những mục tiêu ngoại lệ
Sử dụng hàm tạo được cung cấp bởi dòng điện
một đối tượng Constructor để tạo và khởi tạo
một phiên bản mới của lớp trong đó hàm tạo
đã khai báo, truyền các đối số đã cho.
Trả về một liên kết đến mới được tạo và
một đối tượng được khởi tạo. Chiều dài của mảng args
phải khớp với số lượng tham số trong
một khai báo phương thức khởi tạo và các kiểu đối tượng của các phần tử mảng phải có thể gán được
các loại tham số hàm tạo tương ứng -
nếu không một ngoại lệ sẽ được ném ra
Ngoại lệ Đối số bất hợp pháp.

17.

Hãy xem xét một ví dụ:
lớp Myclass (
int riêng tư a;
public Myclass (int k) (a = k;)
public int func (int a, int b) (return a + b;)
}
lớp công cộng Chính (
public static void main (String args) (
cố gắng (
String name = "Myclass";
Lớp mycl = Class.forName (tên);
Lớp d = (int.class);
Hàm tạo c = mycl.getConstructor (d);
Myclass ob = (Myclass) c.newInstance (Đối tượng mới (
new Integer (10)));
System.out.println (ob.func (3,5)); )
bắt (Ngoại lệ e) ();
}}

18.

Lớp AccessibleObject
Các lớp Field, Constructor và Method là
bắt nguồn từ lớp AccessibleObject,
điều này làm cho nó có thể giải quyết hoặc
cấm kiểm tra các dấu hiệu truy cập cấp độ
các ngôn ngữ như công cộng và riêng tư.
Lớp AccessibleObject có các phương thức
1.public void setAccessible (cờ boolean)
Đặt cờ truy cập đối tượng thành
theo giá trị đối số: true
có nghĩa là đối tượng không còn tuân theo
quy tắc truy cập được đặt ở cấp độ
ngôn ngữ (và sẽ luôn có sẵn), sai
buộc đối tượng duy trì
cấp độ truy cập.
Nếu cơ quan có thẩm quyền thay đổi cờ truy cập
không đủ, một loại ngoại lệ được ném
Ngoại lệ an ninh

19.

2. công khai tĩnh
void setAccessible (mảng AccessibleObject,
cờ boolean)
Cho phép đặt cờ truy cập thành
các đối tượng được truyền dưới dạng một mảng.
Nếu trong quá trình xử lý tiếp theo
đối tượng ném một loại ngoại lệ
Các đối tượng SecurityException nằm
trong mảng trước đó, lưu trữ tập hợp mới
các giá trị cấp độ truy cập và tất cả các giá trị khác
các đối tượng vẫn ở trạng thái như cũ.
3.public boolean isAccessible ()
Trả về giá trị hiện tại của cờ truy cập
đối tượng

20.

Lớp mảng
Lớp mảng được sử dụng để tạo một mảng
bằng phương tiện phản ánh.
Có hai dạng của phương thức được sử dụng để tạo mảng
newInstance.
public Object newlnstance (Class compType, int length)
Trả về một tham chiếu đến một mảng mới kiểu compType
độ dài độ dài cho trước.
public Object newInstance (Class compType, int dim)
Trả về một tham chiếu đến một kiểu mảng đa chiều mới
compType có kích thước được cung cấp bởi các giá trị
các phần tử của mảng tham số mờ.
Nếu mờ là trống hoặc lâu hơn
số thứ nguyên cho phép (thường là 255),

llegalArgumentException.

21.

Hãy xem một số ví dụ.
Ví dụ 1. Hãy tạo một mảng kiểu byte
byte ba = (byte)
Array.newlnstance (byte.class, 13);
Điều này cũng giống như
byte ba = byte mới;
Ví dụ 2.
int dims = (4, 4);
ma trận kép = (kép)
Array.newlnstance (double.class, dims);
Điều này cũng giống như
ma trận kép = new double;

22.

Lớp Array có các phương thức get và set.
Cho một mảng xa các giá trị kiểu int được đưa ra; sau đó
biểu thức xa [i] sẽ khớp với:
Integer n = Array.get (xa, i)
Bạn có thể gán giá trị cho một phần tử mảng như sau:
xa [i] = 23; giống như
Array.set (xa, i, new Integer (23));
Gói lớp
Gọi phương thức getPackage của lớp Class cho phép
lấy một đối tượng của lớp Gói chứa
mô tả của gói có chứa
lớp (lớp Gói chính nó nằm trong gói
java.lang).
Phương thức getName () của đối tượng Package trả về
tên đầy đủ đủ điều kiện của gói hiện tại.

23.

Lớp proxy
Lớp Proxy cho phép bạn tạo động
các lớp triển khai một hoặc nhiều
các giao diện.
Giả sử có một lớp A,
triển khai một số giao diện.
Máy Java trong thời gian chạy có thể
tạo lớp proxy cho
hạng A, tức là một lớp học
triển khai tất cả các giao diện của lớp A, nhưng
thay thế việc gọi tất cả các phương thức này
giao diện để gọi phương thức gọi,
giao diện InvocationHandler, dành cho
mà bạn có thể xác định
thực hiện.

24.

Tạo một lớp proxy bằng cách gọi phương thức
Proxy.getProxyClass chấp nhận ClassLoader và
một mảng giao diện và trả về một đối tượng
lớp java.lang.Class được tải bằng
của giá trị được truyền vào ClassLoader và triển khai giá trị được truyền vào trong mảng
các giao diện.
Có một số hạn chế đối với các tham số được truyền:
1. Tất cả các đối tượng trong mảng giao diện phải
các giao diện. Chúng không thể là các lớp hoặc
nguyên thủy.
2. Mảng giao diện không được chứa hai
các đối tượng.
3. Tất cả các giao diện trong mảng giao diện phải
được tải bởi ClassLoader được chuyển đến phương thức
getProxyClass.
4. Tất cả các giao diện không công khai phải được xác định
trong cùng một gói, nếu không thì lớp proxy đã tạo
sẽ không thể thực hiện tất cả chúng.

25.

5. Không có hai giao diện nào có thể chứa
phương pháp có cùng tên và
chữ ký tham số, nhưng khác với
trả lại các loại.
6. Độ dài của mảng giao diện bị giới hạn
65535 giao diện. Không có lớp Java
không thể triển khai nhiều hơn 65535
các giao diện.

26.

Thuộc tính lớp proxy động
1. Lớp proxy là công khai, được cung cấp
là cuối cùng và không trừu tượng.
2. Tên lớp proxy mặc định không
được xác định, nhưng bắt đầu từ Proxy. Mọi thứ
không gian tên bắt đầu bằng Proxy
dành riêng cho các lớp proxy
(Điều này không bắt buộc trong các phiên bản Java gần đây.)
3. Lớp proxy kế thừa từ
java.lang.reflect.Proxy.
4. Lớp proxy thực hiện tất cả các giao diện,
được chuyển khi tạo, theo thứ tự chuyển.

27.

5. Nếu lớp proxy thực hiện một
giao diện, sau đó nó sẽ được tạo trong gói
xác định điều này rất không công khai
giao diện. Nói chung, một gói trong đó
lớp proxy sẽ được tạo không xác định.
6. Phương thức Proxy.isProxyClass trả về true cho
các lớp học được tạo bằng
Proxy.getProxyClass và cho các lớp đối tượng,
được tạo bằng Proxy.newProxyInstance và
sai khác.
Phương pháp này được sử dụng bởi hệ thống con
Bảo mật Java và bạn cần hiểu điều đó để
một lớp vừa được kế thừa từ
java.lang.reflect.Proxy nó sẽ trả về false.

28.

Các thuộc tính của phiên bản đã tạo của lớp proxy như sau:
1. Đối tượng của lớp proxy được truyền tới tất cả các giao diện,
được truyền trong mảng giao diện. Nếu IDemo là một trong những
của các giao diện đã qua, sau đó là hoạt động của phiên bản proxy
IDemo sẽ luôn trả về true và hoạt động proxy (IDemo)
sẽ hoàn thành một cách chính xác.
2. Phương thức tĩnh Proxy.getInvocationHandler
trả về trình xử lý cuộc gọi được chuyển vào khi tạo
một phiên bản của lớp proxy. Nếu được chuyển đến cho
đối tượng phương thức không phải là một phiên bản của một lớp proxy, sau đó
một ngoại lệ IllegalArgumentException sẽ được ném ra.
3. Lớp xử lý cuộc gọi thực thi giao diện
InvocationHandler, trong đó phương thức gọi được định nghĩa,
có chữ ký sau:
Gọi đối tượng công khai (proxy đối tượng, phương thức phương thức,
Vật thể mũi tên) ném Có thể ném

29.

Hãy xem xét một ví dụ:
gói javaapplication3;
giao diện Tài khoản (
double getBalance ();
void changeBalance (int sum);
void percents (double per);)
lớp MyAccount triển khai Tài khoản (
số dư kép tư nhân;
public MyAccount () (số dư = 0.0;)
public double getBalance () (trả về số dư;)
public void changeBalance (int sum) (
số dư + = tổng;)
phần trăm khoảng trống công cộng (đôi mỗi) (
số dư + = số dư * per / 100; ); )

30.

lớp MyAccountProxy triển khai
InvocationHandler (
Tài khoản cá nhân ac;
public MyAccountProxy (Tài khoản tài khoản) (ac = acc;)
public static Account newInstance (Account da) (
return (Tài khoản) Proxy.newProxyInstance (
da.getClass (). getClassLoader (),
da.getClass (). getInterfaces (),
mới MyAccountProxy (da));
}

31.

Gọi đối tượng công khai (Đối tượng proxy,
Method method, Object args)
ném Có thể ném (
if (method.getName () == "percents") (
double d = ((Double) args) .doubleValue ();
nếu (d<0) d=0;
nếu (d> 30) d = 30;
args = new Double (d);

khác (
return method.invoke (ac, args); )
}
}

32.

lớp công cộng Chính (
public static void main (String args) (
MyAccount ma = new MyAccount ();
Tài khoản
a = (Tài khoản) MyAccountProxy.newInstance (ma);
a.changeBalance (150);

a. khẩu độ (20);
System.out.println (a.getBalance ());
a. khẩu độ (35);
System.out.println (a.getBalance ());))

33.

Đang tải các lớp học
Hệ thống thời gian chạy tải các lớp dưới dạng
sự xuất hiện của nhu cầu đối với chúng.
Các tính năng chức năng của thủ tục khởi động
các lớp về cơ bản phụ thuộc vào
triển khai các máy ảo Java, nhưng trong
trong hầu hết các trường hợp để tìm các lớp học,
được ứng dụng giải quyết nhưng không được tải
bởi hệ thống thực thi, cơ chế được áp dụng
xem đường dẫn tìm kiếm lớp học.
Để tạo một ứng dụng có thể
tải các lớp theo những cách khác với
được cung cấp theo mặc định, bạn nên
sử dụng một đối tượng của lớp ClassLoader,
có thể nhận được mã bytecode để thực hiện những điều mong muốn
lớp và tải nó vào môi trường thời gian chạy
các hệ thống.

34.

Lớp ClassLoader là một lớp trừu tượng.
Để tạo trình tải lớp của riêng bạn,
nó là cần thiết để tạo một lớp kế thừa từ
ClassLoader và phương thức ghi đè
lớp bảo vệ findClass (Tên chuỗi) ném
ClassNotFoundException
Cái nào tìm thấy mã bytecode của lớp với giá trị đã cho
tên được đặt tên và tải dữ liệu vào môi trường
máy ảo bằng cách trả về một đối tượng Lớp,
đại diện cho lớp được tìm thấy.
Đối tượng trình nạp có thể ủy quyền
quyền tải các lớp cho "cha"
trình nạp lớp cha.
Bộ tải lớp "cha" có thể là
được đưa ra dưới dạng đối số cho hàm tạo lớp
ClassLoader.

35.

ClassLoader được bảo vệ ()
Tạo đối tượng ClassLoader một cách ngầm định
sử dụng như "cha mẹ"
trình tải hệ thống classloader
(có thể lấy bằng
gọi phương thức getSystemClassLoader).
ClassLoader được bảo vệ (ClassLoader cha)
Tạo một đối tượng ClassLoader bằng cách sử dụng
trình tải lớp "cha" được chỉ định.
Phần chính của lớp ClassLoader
là phương thức loadClass

36.

ném công khai Сlass loadClass (Tên chuỗi)
ClassNotFoundException
trả về đối tượng Lớp cho lớp với
tên và tùy chọn tải cái này
Lớp học. Nếu không thể tải lớp,
một loại ngoại lệ được ném
ClassNotFoundException.
Lược đồ tải lớp được gợi ý bởi phương thức
loadClass là mặc định và thường không
overridden trông như thế này:
1. kiểm tra bằng cách gọi một phương thức
findLoadedClass của lớp ClassLoader, không phải
lớp được chỉ định đã được tải trước đó chưa; như một phần của
ClassLoader cung cấp một bảng các đối tượng
Lớp cho tất cả các lớp được tải bằng phương tiện
trình tải lớp hiện tại; nếu lớp học là
đã tải trước đó, phương thức findLoadedClass
sẽ trả về một tham chiếu đến một đối tượng Lớp hiện có;

37.

2. nếu lớp không được tải, nó được gọi là
loadClass của trình tải "mẹ"
các lớp học; nếu bộ nạp khởi động hiện tại không
sở hữu một "cha mẹ", được sử dụng
bộ tải lớp hệ thống;
3. nếu lớp vẫn chưa được tải,
phương thức findClass được gọi là doing
tìm kiếm và tải lớp.
Như vậy, cần phải thực hiện
phiên bản gốc của các phương pháp sau
ClassLoader:

38.

Lớp đồng bộ được bảo vệ
loadClass (Tên chuỗi, phân giải boolean)

Lớp được bảo vệ findClass (Tên chuỗi)
ném ClassNotFoundException
bảo vệ java.net.URL findResource (Tên chuỗi)
bảo vệ java.util.Enumeration
findResources (String name) ném IOException
(Lớp trừu tượng ClassLoader đại diện cho
chỉ việc triển khai phương thức loadClass dựa trên
trên các phương thức được bảo vệ - findLoadedClass và findClass).

39.

Hãy xem một ví dụ.
class PlayerLoader mở rộng ClassLoader (
public Class findClass (String name) ném
ClassNotFoundException (
cố gắng (
byte buf = bytesForClass (tên);
trả về defineClass (tên, buf, 0, buf.length);
}
bắt (IOException e) (
ném ClassNotFoundException mới (e.toString ());
}
}
// ... Khai báo phương thức bytesForClass và các phương thức khác
phương pháp
}

40.

Phương thức findClass thường thực hiện hai
chức năng.
Đầu tiên, nó phải phát hiện mã bytecode
của lớp đã cho và lưu trữ nó trong một mảng
của kiểu byte - nhiệm vụ này trong ví dụ
được gán cho phương thức bytesForСlass.
Thứ hai, nó sử dụng phương pháp được áp dụng
định nghĩalass để thực thi thực tế
tải lớp được xác định bởi mã bytecode.
Phương thức defineСlass có dạng

41.

được bảo vệ cuối cùng Lớp xác định Lớp (Tên chuỗi,
dữ liệu byte, int offset, int length) ném
ClassFormatError
Trả về đối tượng Lớp cho lớp có tên đã cho
Tên; biểu diễn nhị phân của lớp được chuyển đến
dưới dạng dữ liệu mảng.
Chỉ các byte được sử dụng để tải lớp,
chứa trong các phần tử của mảng dữ liệu với các chỉ số
bù đắp để bù đắp + độ dài. Nếu byte từ chỉ định
khoảng cách không phù hợp với định dạng yêu cầu
mô tả lớp, đối tượng ngoại lệ được ném
thuộc loại ClassFormatError.
Phương thức chịu trách nhiệm duy trì tham chiếu đến đối tượng
Lớp cho lớp đã tải trong bảng đã tải
các lớp được xem bởi phương thức findLoadedClass.

42.

Hãy xem xét phương thức bytesForClass.
ném byte byte byteForClass (tên chuỗi) được bảo vệ
lOException, ClassNotFoundException (
FileInputStream in = null;
cố gắng (


if (length == 0) ném ClassNotFoundException (tên) mới;
byte buf = byte mới;

trả về buf;
}
cuối cùng (
if (in! = null) in.close ();
}
}

43.

Do đó, mã hoàn chỉnh trông giống như:
nhập java.lang.reflect. *;
nhập java.io. *;
class MyClassLoader mở rộng ClassLoader (
lớp công khainém findClass (Tên chuỗi)
ClassNotFoundException (
byte buf = ReadFromBuffer (tên);
if (name.equals ("MyInterface1")) (

) else if (buf == null) (
trả về findSystemClass (tên);
) khác (
trả về defineClass (tên, buf, 0, buf.length);
}
}

44.

ném byte ReadFromBuffer (Tên chuỗi) được bảo vệ
ClassNotFoundException (
FileInputStream in = null;
cố gắng (
in = new FileInputStream (tên + ".class");
int length = in.available (); // số byte có sẵn
if (length == 0) ném
new ClassNotFoundException (tên);
byte buf = byte mới;
in.read (buf); // Đọc byte
trả về buf;
}
catch (FileNotFoundException e) (return null;)
catch (IOException e) (trả về null;)
cuối cùng (
thử (if (in! = null) in.close ();)
bắt (IOException e) ()
}
}

45.

Lớp đồng bộ được bảo vệ
ném loadClass (Tên chuỗi, phân giải boolean)
ClassNotFoundException (
Kết quả lớp = findClass (tên);
if (giải quyết) ResolutionClass (kết quả);
trả về kết quả;
}
}

46.

public class Main1 (
public static void main (String args) (
cố gắng (
String name = "Myclass";
ClassLoader ld = new MyClassLoader ();
Lớp cl = Class.forName (tên, true, ld);
Constructor s = cl.getConstructor (int.class);
MyInterface1
ob = (MyInterface1) s.newInstance (
new Integer (8));
System.out.println (ob.func (3,5));
) bắt (Ngoại lệ e) ();
}
}

47.

giao diện công cộng MyInterface1 (
public int func (int a, int b);
}
public class Myclass triển khai MyInterface1 (
int riêng tư a;
public Myclass (int k) (a = k;)
public int func (int a, int b) (return a + b;)

Này! Trong bài giảng hôm nay chúng ta sẽ làm quen với khái niệm “ truy cập sửa đổi"Và hãy xem xét các ví dụ về việc làm việc với họ. Mặc dù từ "làm quen" sẽ không đúng hoàn toàn: bạn đã quen với hầu hết chúng từ các bài giảng trước. Để đề phòng, hãy làm mới bộ nhớ của điều chính. Truy cập công cụ sửa đổi- đây thường là những từ khóa điều chỉnh mức độ truy cập vào các phần khác nhau của mã của bạn. Tại sao "thường xuyên" nhất? Bởi vì một trong số chúng được đặt theo mặc định và không được chỉ định bởi từ khóa :) Có bốn công cụ sửa đổi quyền truy cập trong Java. Hãy liệt kê chúng theo thứ tự từ nghiêm ngặt nhất đến "nhẹ" nhất:

  • riêng;
  • được bảo vệ;
  • default (gói hiển thị);
  • công cộng.
Hãy xem xét từng người trong số họ, quyết định khi nào họ có thể hữu ích cho chúng ta và đưa ra ví dụ :)

Công cụ sửa đổi riêng


Riêng tư là công cụ sửa đổi quyền truy cập nghiêm ngặt nhất. Nó giới hạn khả năng hiển thị của dữ liệu và phương thức trong một lớp duy nhất. Bạn biết công cụ sửa đổi này từ bài giảng về getters và setters. Bạn có nhớ ví dụ này không? public class Cat (public String name; public int age; public int weight; public Cat (String name, int age, int weight) (this. name = name; this. age = age; this. weight = weight;) public Cat () () public void sayMeow () (System. out. println ("Meo meo!");)) public class Main (public static void main (String args) (Cat cat = new Cat (); cat. name = " "; cat. age = - 1000; cat. weight = 0;)) Chúng tôi đã xem xét nó trong một trong những bài báo trước đó. Ở đây, chúng tôi đã mắc một sai lầm nghiêm trọng: chúng tôi đã mở dữ liệu của mình, do đó các lập trình viên đồng nghiệp có quyền truy cập trực tiếp vào các trường của lớp và thay đổi giá trị của chúng. Hơn nữa, các giá trị này đã được chỉ định mà không cần kiểm tra, do đó trong chương trình của chúng tôi, bạn có thể tạo ra một con mèo có tuổi -1000 năm, tên "" và trọng lượng 0. Để giải quyết vấn đề này, chúng tôi đã sử dụng getters and setters và cũng bị hạn chế quyền truy cập vào dữ liệu bằng cách sử dụng công cụ sửa đổi riêng tư. public class Cat (private String name; private int age; private int weight; public Cat (String name, int age, int weight) (this. name = name; this. age = age; this. weight = weight;) public Cat () () public void sayMeow () (System. out.println ("Meo meo!");) public String getName () (return name;) public void setName (String name) (this. name = name;) public int getAge () (return age;) public void setAge (int age) (this. age = age;) public int getWeight () (return weight;) public void setWeight (int weight) (this. weight = weight;)) Thực tế , hạn chế quyền truy cập vào các trường và triển khai setter getters là ví dụ phổ biến nhất của việc sử dụng private trong công việc thực tế. Đó là thực hiện đóng gói trong một chương trình là mục đích chính của sửa đổi này. Nhân tiện, điều này không chỉ áp dụng cho các trường. Hãy tưởng tượng rằng chương trình của bạn có một phương thức thực hiện một số chức năng RẤT phức tạp. Hãy nghĩ về điều này để làm ví dụ ... Giả sử phương thức readDataFromCollider () của bạn chấp nhận một địa chỉ có dữ liệu làm đầu vào, đọc dữ liệu từ Large Hadron Collider ở định dạng byte, chuyển đổi dữ liệu này thành văn bản, ghi nó vào một tệp và in nó . Ngay cả mô tả của phương thức cũng trông đáng sợ, chứ đừng nói đến mã :) Để tăng khả năng đọc của mã, sẽ tốt hơn là không viết logic phương thức phức tạp ở một nơi, mà ngược lại, hãy chia chức năng thành các phương thức riêng biệt. Ví dụ: phương thức readByteData () chịu trách nhiệm đọc dữ liệu, convertBytesToSymbols () chuyển đổi dữ liệu được đọc từ máy va chạm thành văn bản, saveToFile () lưu văn bản đã nhận vào một tệp và printColliderData () in ra tệp dữ liệu của chúng ta. Phương thức readDataFromCollider () cuối cùng sẽ trở nên dễ dàng hơn nhiều: public class ColliderUtil (public void readDataFromCollider (Path pathToData) (byte colliderData = readByteData (pathToData); String textData = convertBytesToSymbols (colliderData); File fileWithFromData) Đường dẫn pathToData) ( // đọc dữ liệu theo byte) public String convertBytesToSymbols (byte colliderDataInBytes) () public File saveToFile (String colliderData) () public void printColliderData (File fileWithColliderData) ( // in dữ liệu từ tệp)) Tuy nhiên, như bạn nhớ từ bài giảng về giao diện, người dùng chỉ có quyền truy cập vào giao diện cuối cùng. Và 4 phương pháp của chúng tôi không phải là một phần của nó. Họ công ty con: Chúng tôi tạo ra chúng để cải thiện khả năng đọc của mã và không gắn bốn nhiệm vụ khác nhau vào một phương pháp. Bạn không cần phải cấp cho người dùng quyền truy cập vào các phương pháp này. Nếu người dùng có quyền truy cập vào phương thức convertBytesToSymbols () khi làm việc với trình va chạm, rất có thể anh ta sẽ không hiểu phương thức này là gì và tại sao nó lại cần thiết. Những byte nào đang được chuyển đổi? Họ đến từ đâu vậy? Tại sao chuyển đổi chúng thành văn bản? Logic chạy trong phương pháp này không phải là một phần của giao diện người dùng. Chỉ phương thức readDataFromCollider () là một phần của giao diện. Bạn sẽ làm gì với bốn phương pháp "nội bộ" này? Đúng! Hạn chế quyền truy cập vào chúng bằng công cụ sửa đổi riêng tư. Vì vậy, họ sẽ có thể bình tĩnh làm công việc của họ bên trong lớp và không đánh lừa người dùng, những người không cần logic của từng người trong số họ riêng biệt. public class ColliderUtil (public void readDataFromCollider (Path pathToData) (byte colliderData = readByteData (pathToData); String textData = convertBytesToSymbols (colliderData); File fileWithData = saveToFile (textData); printColliderData) (fileToData) // đọc dữ liệu theo byte) private String convertBytesToSymbols (byte colliderDataInBytes) ( // chuyển đổi byte thành ký tự) private File saveToFile (String colliderData) ( // lưu dữ liệu đã đọc vào một tệp) private void printColliderData (File fileWithColliderData) ( // in dữ liệu từ tệp } }

Công cụ sửa đổi được bảo vệ

Công cụ sửa đổi quyền truy cập mạnh nhất tiếp theo được bảo vệ.
Các trường và phương thức được chỉ định với công cụ sửa đổi quyền truy cập được bảo vệ sẽ hiển thị:
  • trong tất cả các lớp nằm trong cùng một gói với của chúng tôi;
  • trong tất cả các lớp kế thừa từ lớp của chúng ta.
Thật khó để tưởng tượng ra ngay khi cần thiết. Đừng ngạc nhiên: có ít trường hợp sử dụng được bảo vệ hơn nhiều so với các trường hợp riêng tư và chúng rất cụ thể. Hãy tưởng tượng rằng chúng ta có một lớp trừu tượng AbstractSecretAgent, biểu thị một tác nhân bí mật của một số dịch vụ đặc biệt, cũng như gói top_secret, chứa lớp này và những người thừa kế của nó. Các lớp bê tông được kế thừa từ nó - FBISecretAgent, MI6SecretAgent, MossadSecretAgent, v.v. Bên trong lớp trừu tượng, chúng ta muốn triển khai một bộ đếm tác nhân. Khi một đối tượng tác nhân mới được tạo ở đâu đó trong chương trình, nó sẽ phát triển. gói top_secret; public abstract class AbstractSecretAgent (public static int agentCount = 0;) Nhưng các đặc vụ của chúng tôi là bí mật! Điều này có nghĩa là chỉ họ và không ai khác được biết về số của họ. Chúng ta có thể dễ dàng thêm công cụ sửa đổi được bảo vệ vào trường agentCount, và sau đó các đối tượng thuộc các lớp nhân viên bí mật khác hoặc các lớp nằm trong gói top_secret "bí mật" của chúng ta, có thể nhận được giá trị của nó. public abstract class AbstractSecretAgent (protected static int agentCount = 0;) Đối với các tác vụ cụ thể như vậy, cần có công cụ sửa đổi được bảo vệ :)

Gói sửa đổi hiển thị

Ở phía dưới danh sách là công cụ sửa đổi mặc định, hoặc, như nó còn được gọi là, gói hiển thị. Nó không được biểu thị bằng một từ khóa vì nó được đặt theo mặc định trong Java cho tất cả các trường và phương thức. Nếu bạn viết mã của mình - int x = 10 ... thì biến x sẽ có quyền truy cập rất gói này. Thật dễ dàng để nhớ những gì anh ấy đang làm. Trên thực tế, default = protected -inheritance :) Các trường hợp sử dụng nó bị hạn chế, như với công cụ sửa đổi được bảo vệ. Thông thường, quyền truy cập mặc định được sử dụng trong một gói nơi có một số lớp tiện ích không triển khai chức năng của tất cả các lớp khác trong gói này. Hãy cho một ví dụ. Hãy tưởng tượng rằng chúng ta có một gói “ dịch vụ". Bên trong nó là các lớp khác nhau hoạt động với cơ sở dữ liệu. Ví dụ: có một lớp UserService đọc dữ liệu người dùng từ cơ sở dữ liệu, một lớp CarService đọc dữ liệu về ô tô từ cùng một cơ sở dữ liệu và các lớp khác, mỗi lớp hoạt động với loại đối tượng riêng và đọc dữ liệu về chúng từ cơ sở dữ liệu. các dịch vụ trọn gói; dịch vụ gói UserService () lớp công khai; public class CarService () Tuy nhiên, một tình huống có thể dễ dàng xảy ra khi dữ liệu trong cơ sở dữ liệu ở một định dạng nhưng chúng ta cần nó ở một định dạng khác. Hãy tưởng tượng rằng ngày sinh của người dùng trong cơ sở dữ liệu được lưu trữ ở định dạng TIMESTAMP VỚI TIME ZONE ... 2014 - 04 - 04 20: 32: 59.390583 + 02 ... thay vào đó chúng ta cần đối tượng đơn giản nhất - java.util.Date. Với mục đích này, chúng ta có thể tạo một Mapper lớp đặc biệt bên trong gói dịch vụ. Anh ta sẽ chịu trách nhiệm chuyển đổi dữ liệu từ cơ sở dữ liệu thành các đối tượng Java thông thường. Lớp trợ giúp đơn giản. Chúng tôi thường tạo tất cả các lớp dưới dạng ClassName lớp công khai, nhưng điều này là không bắt buộc. Chúng ta có thể khai báo lớp trợ giúp của mình đơn giản là lớp Mapper. Trong trường hợp này, nó vẫn thực hiện công việc của mình, nhưng không hiển thị với bất kỳ ai bên ngoài gói dịch vụ! các dịch vụ trọn gói; các dịch vụ trọn gói class Mapper (); public class CarService (Mapper mapper;) Và trên thực tế, đây là logic chính xác: tại sao bất kỳ ai bên ngoài một gói sẽ thấy một lớp trợ giúp chỉ hoạt động với các lớp của cùng một gói?

Công cụ sửa đổi

Cuối cùng nhưng không kém phần quan trọng, công cụ sửa đổi công khai! Bạn đã gặp anh ấy vào ngày đầu tiên học tại CodeGym bằng cách chạy public static void main (String args) lần đầu tiên trong đời.
Bây giờ bạn đã nghiên cứu các bài giảng về giao diện, mục đích của nó là rõ ràng đối với bạn :) Sau cùng, công khai được tạo ra để cung cấp một cái gì đó cho người dùng. Ví dụ: giao diện của chương trình của bạn. Giả sử bạn đã viết một chương trình phiên dịch và nó có thể dịch văn bản tiếng Nga sang tiếng Anh. Bạn đã tạo một phương thức dịch (String textInRussian), bên trong đó các logic cần thiết được triển khai. Bạn đã đánh dấu phương thức này bằng từ public và bây giờ nó sẽ trở thành một phần của giao diện: public class Translator (public String translate (String textInRussian) ( // dịch văn bản từ tiếng Nga sang tiếng Anh)) Bạn có thể liên kết một lệnh gọi đến phương thức này với nút "dịch" trên màn hình chương trình - và thế là xong! Bất cứ ai cũng có thể sử dụng nó. Các phần mã được đánh dấu bằng công cụ sửa đổi dành cho người dùng cuối. Để đưa ra một ví dụ từ cuộc sống thực, riêng tư là tất cả các quá trình diễn ra bên trong TV khi nó đang chạy và công khai là các nút trên điều khiển từ xa của TV mà người dùng có thể điều khiển nó. Đồng thời, anh ta không cần biết TV hoạt động như thế nào và hoạt động như thế nào. Điều khiển từ xa là một tập hợp các phương thức công khai: on (), off (), nextChannel (), beforeChannel (), gainVolume (), ReduceVolume (), v.v.

Cập nhật lần cuối: 03.10.2019

Tất cả các thành viên của một lớp - các trường, phương thức, thuộc tính - tất cả chúng đều có truy cập sửa đổi... Công cụ sửa đổi quyền truy cập cho phép bạn đặt phạm vi hợp lệ cho các thành viên trong lớp. Nghĩa là, các công cụ sửa đổi quyền truy cập xác định ngữ cảnh trong đó một biến hoặc phương thức nhất định có thể được sử dụng. Trong các chủ đề trước, chúng ta đã gặp nó khi chúng ta khai báo các trường lớp là công khai (nghĩa là với công cụ sửa đổi công khai).

Các công cụ sửa đổi quyền truy cập sau được sử dụng trong C #:

    public: một công khai, lớp công khai, hoặc một thành viên của một lớp. Một thành viên lớp như vậy có thể truy cập từ bất kỳ đâu trong mã, cũng như từ các chương trình và tổ hợp khác.

    private: một lớp riêng hoặc thành viên của một lớp. Đại diện hoàn toàn ngược lại với công cụ sửa đổi công khai. Một lớp hoặc thành viên lớp riêng như vậy chỉ có thể truy cập được từ mã trong cùng lớp hoặc ngữ cảnh.

    được bảo vệ: Một thành viên lớp như vậy có thể truy cập từ bất kỳ đâu trong lớp hiện tại hoặc trong các lớp dẫn xuất. Tuy nhiên, các lớp dẫn xuất có thể nằm trong các hợp ngữ khác.

    nội bộ: một lớp và các thành viên của lớp có công cụ sửa đổi tương tự có thể truy cập từ bất kỳ đâu trong mã trong cùng một hợp ngữ, nhưng nó không khả dụng với các chương trình và tập hợp khác (như trường hợp của công cụ sửa đổi công khai).

    nội bộ được bảo vệ: kết hợp chức năng của hai bổ ngữ. Các lớp và thành viên lớp có bổ trợ này có sẵn từ hợp ngữ hiện tại và từ các lớp dẫn xuất.

    Riêng tư được bảo vệ: Một thành viên lớp như vậy có thể truy cập từ bất kỳ đâu trong lớp hiện tại hoặc trong các lớp dẫn xuất được định nghĩa trong cùng một hợp ngữ.

Chúng tôi có thể đặt công cụ sửa đổi quyền truy cập một cách rõ ràng, ví dụ:

Trạng thái lớp được bảo vệ riêng tư (int a; int a; được bảo vệ void Print () (Console.WriteLine ($ "a = (a)");))

Hoặc chúng ta có thể bỏ qua việc chỉ định:

Trạng thái lớp (int a; void Print () (Console.WriteLine ($ "a = (a)");))

Nếu không có công cụ sửa đổi truy cập nào được xác định cho các trường và phương thức, thì công cụ sửa đổi riêng được sử dụng cho chúng theo mặc định.

Các lớp và cấu trúc được khai báo không có bổ ngữ có quyền truy cập nội bộ theo mặc định.

Tất cả các lớp và cấu trúc được xác định trực tiếp trong không gian tên không được lồng trong các lớp khác chỉ có thể có các bổ ngữ công khai hoặc nội bộ.

Hãy xem một ví dụ và tạo lớp State sau:

Public class State (// giống với private int defaultVar; int defaultVar; // trường chỉ có thể truy cập được từ lớp hiện tại private int privateVar; // có thể truy cập từ lớp hiện tại và các lớp dẫn xuất được định nghĩa trong cùng một dự án được bảo vệ private int protectedPrivateVar; // có sẵn từ lớp hiện tại và các lớp dẫn xuất được bảo vệ int protectedVar; // có sẵn ở bất kỳ đâu trong dự án hiện tại internal int internalVar; // khả dụng ở bất kỳ đâu trong dự án hiện tại và từ các lớp kế thừa trong các dự án khác được bảo vệ bên trong int protectedInternalVar; // có sẵn ở bất kỳ đâu trong chương trình, cũng như cho các chương trình và tổ hợp khác public int publicVar; // theo mặc định có một công cụ sửa đổi private void defaultMethod () => Console.WriteLine ($ "defaultVar = (defaultVar)"); / / phương thức chỉ có thể truy cập được từ lớp hiện tại private void privateMethod () => Console.WriteLine ($ "privateVar = (privateVar)"); // có thể truy cập từ lớp hiện tại và các lớp dẫn xuất được định nghĩa trong cùng một đoạn private void protectedPrivateMethod () => Console.WriteLine ($ "protectedPrivateVar = (protectedPrivateVar)"); // có thể truy cập từ lớp hiện tại và các lớp dẫn xuất được bảo vệ void protectedMethod () => Console.WriteLine ($ "protectedVar = (protectedVar)"); // có sẵn ở bất kỳ đâu trong dự án hiện tại nội bộ void internalMethod () => Console.WriteLine ($ "internalVar = (internalVar)"); // có sẵn ở bất kỳ đâu trong dự án hiện tại và từ các lớp kế thừa trong các dự án khác được bảo vệ bên trong void protectedInternalMethod () => Console.WriteLine ($ "protectedInternalVar = (protectedInternalVar)"); // có sẵn ở bất kỳ đâu trong chương trình, cũng như các chương trình và tập hợp khác public void publicMethod () => Console.WriteLine ($ "publicVar = (publicVar)"); )

Vì lớp State được khai báo với công cụ sửa đổi, nó sẽ có thể truy cập được từ bất kỳ đâu trong chương trình, cũng như từ các chương trình và tổ hợp khác. Lớp State có năm trường cho mỗi cấp độ truy cập. Thêm một biến không có công cụ sửa đổi, biến đó là riêng tư theo mặc định.

Ngoài ra còn có sáu phương thức sẽ hiển thị giá trị của các trường lớp trên màn hình. Xin lưu ý rằng vì tất cả các sửa đổi đều cho phép bạn sử dụng các thành viên lớp bên trong lớp này, nên tất cả các biến lớp, bao gồm cả các biến riêng, đều có sẵn cho tất cả các phương thức của nó, vì chúng đều nằm trong ngữ cảnh của lớp State.

Bây giờ chúng ta hãy xem cách chúng ta có thể sử dụng các biến của lớp của chúng ta trong chương trình (nghĩa là trong phương thức Chính của lớp Chương trình), nếu lớp Trạng thái và lớp Chương trình nằm trong cùng một dự án:

Chương trình lớp (static void Main (string args) (State state1 = new State (); // chúng ta sẽ không thể gán giá trị cho biến defaultVar, // vì nó có một công cụ sửa đổi riêng và lớp Chương trình không nhìn thấy it // Và dòng này là môi trường sẽ gạch chân là sai state1.defaultVar = 5; // Lỗi, bạn không thể truy cập // Điều tương tự cũng áp dụng cho biến privateVar state1.privateVar = 5; // Lỗi, bạn không thể truy cập // gán giá trị của biến protectedPrivateVar sẽ không hoạt động, // vì lớp Chương trình không phải là lớp con của lớp State1.protectedPrivateVar = 5; // Lỗi, bạn không thể truy cập // gán giá trị của biến protectedVar cũng sẽ không thành công, // vì lớp Chương trình không phải là lớp con của lớp State1.protectedVar = 5; // Lỗi, bạn không thể truy cập // biến InternalVar với công cụ sửa đổi bên trong có thể truy cập từ bất kỳ đâu trong dự án hiện tại / / do đó, hãy gán nó một cách an toàn giá trị state1.internalVar = 5; // biến protectedInternalVar cũng có thể truy cập được từ bất kỳ đâu trong trạng thái dự án hiện tại, state1.protectedInternalVar = 5; // publicVar có sẵn công khai state1.publicVar = 5; ))

Do đó, chúng tôi chỉ có thể đặt các biến internalVar, protectedInternalVar và publicVar, vì các công cụ sửa đổi của chúng cho phép chúng tôi sử dụng chúng trong ngữ cảnh này.

Tình hình tương tự với các phương pháp:

Chương trình lớp (static void Main (string args) (State state1 = new State (); state1.defaultMethod (); // Lỗi, không thể truy cập state1.privateMethod (); // Lỗi, không thể truy cập state1.protectedPrivateMethod () ; // Lỗi, bạn không thể truy cập state1.protectedMethod (); // Lỗi, bạn không thể truy cập state1.internalMethod (); // định mức state1.protectedInternalMethod (); // định mức state1.publicMethod (); // định mức ))

Ở đây, chỉ có ba phương thức khả dụng cho chúng tôi: internalMethod, protectedInternalMethod, publicMethod, có các công cụ sửa đổi nội bộ, nội bộ được bảo vệ và công khai, tương ứng.

Nhờ có một hệ thống bổ trợ truy cập như vậy, có thể ẩn một số khía cạnh của việc triển khai lớp khỏi các phần khác của chương trình.

Mặc dù thực tế là các công cụ sửa đổi nội bộ và công khai tương tự nhau về hoạt động của chúng, nhưng chúng có sự khác biệt lớn. Các lớp và thành viên của một lớp với công cụ sửa đổi công khai cũng sẽ có sẵn cho các chương trình khác nếu lớp đã cho được đặt trong một dll thư viện động và sau đó được sử dụng trong các chương trình này.