JShell là một tính năng mới trong Java 9 để hỗ trợ chạy các đoạn mã. Các đoạn mã JShell hoàn toàn giống với mã nguồn Java trong một tệp cho một ứng dụng. Như đã thảo luận trong một bài viết trước, “Sử dụng JShell trong Java 9 trong NetBeans 9.0, Phần 3,” JShell không cho phép một số công cụ sửa đổi — bao gồm mặc định, truy cập, đồng bộ hóa, công khai, riêng tư và bảo vệ — được hỗ trợ trong tệp mã nguồn . JShell được thiết kế chủ yếu để kiểm tra và gỡ lỗi mã Java chứ không phải để chạy các ứng dụng hoàn chỉnh. Trong phần tiếp theo này, chúng ta sẽ chạy các đoạn mã cho các lớp, giao diện và mảng. Chúng tôi đã sử dụng NetBeans 9 như trong các bài viết trước. Chúng ta cũng sẽ thảo luận về các trường hợp ngoại lệ chưa được kiểm tra. Bài viết này có các phần sau:
- Sử dụng Lớp học
- Sửa đổi một lớp
- Các lớp danh sách
- Sử dụng Trình tạo lớp
- Mở rộng một lớp học
- Ghi đè một phương pháp
- Sử dụng Giao diện
- Sử dụng Triển khai Mặc định cho một Phương pháp
- Khai báo một phương thức giao diện là tĩnh
- Sử dụng Mảng
- Sử dụng các Ngoại lệ Bỏ chọn
- Kết luận
Sử dụng các lớp học
Trong phần này, chúng ta sẽ thảo luận về việc chạy các đoạn mã cho các lớp. Khai báo một lớp đơn giản C như sau.
[1]-> class C { } | created class C
Lớp C được tạo. Không giống như một phương thức có thể được gọi trực tiếp, một lớp trước tiên phải được khởi tạo như sau.
[3]-> new C() | $1 ==> [email protected]
Một phiên bản mới của lớp C, $ 1 được tạo. Cũng như khai báo phương thức, khai báo lớp có thể sửa đổi được bằng cách khai báo lại lớp. Một lớp có thể triển khai một giao diện bằng cách sử dụng triển khai . Ví dụ, khai báo một giao diện I .
[1]-> interface I{} | created interface I
Tạo lớp C để triển khai giao diện I .
[3]-> class C implements I{} | replaced class C [4]->
Lớp C , được tạo trước đây, được thay thế.
Khai báo lớp trong JShell không có khái niệm về ứng dụng như một lớp Java được khai báo trong tệp sẽ có. Một lớp Java trong tệp có public static void main (String [] argv) phương pháp là một ứng dụng Java. public static void main (String [] argv) phương thức có thể được thêm vào JShell nhưng chỉ là một đoạn mã khác. Tạo một lớp học Xin chào bao gồm phương thức public static void main (String [] argv) .
[1]-> class Hello{ public static void main(String[] argv){System.out.println (argv[0]+argv[1]);} } | created class Hello [2]->
main (Chuỗi []) phương thức là một static và được định nghĩa cho lớp chứ không phải là một thể hiện của lớp. Tạo Chuỗi [] mảng để cung cấp cho main (String []) phương pháp.
String[] strArray={"Hello"," JShell"};
Gọi main (String []) với String [] như một lập luận.
Hello.main(strArray)
Thông báo Hello JShell được xuất ra, như thể hiện trong Hình 1.
Hình 1: Gọi phương thức tĩnh trong một lớp
Sửa đổi một lớp
Một lớp có thể được sửa đổi nếu cần bằng cách sửa đổi hoặc xóa bất kỳ khai báo phương thức nào của nó hoặc thêm các phương thức mới. Khai báo lại lớp Xin chào không có main (String []) và lớp được thay thế.
[4]-> class Hello{ } | replaced class Hello [5]->
Thêm lại main (String []) nhưng với System.out.println hơi khác tuyên bố. Lớp Xin chào lại được thay thế.
[5]-> class Hello{ public static void main(String[] argv) {System.out.println(argv[0]);} } | replaced class Hello [5]->
Gọi static phương thức main (String []) với Hello.main (strArray) cho một đầu ra khác, như trong Hình 2.
Hình 2: Gọi một biến thể của phương thức main
Việc cung cấp để thay thế một lớp rất hữu ích khi phát triển một lớp. Có thể thêm một phương thức tại một thời điểm và thử nghiệm lớp. Ví dụ:thêm phương thức thứ hai hello (String) . Một lần nữa, lớp Xin chào được thay thế.
[9]-> class Hello{ void main(String[] argv){System.out.println(argv[0]);} String hello(String name){return name;} } | replaced class Hello
Phương thức hello (String) được thêm vào, là một phương thức cá thể, sẽ cần một cá thể lớp để gọi. Tạo một phiên bản lớp.
[10]-> new Hello() | $2 ==> [email protected]
Gọi phương thức hello (Chuỗi) sử dụng cá thể lớp $ 2 .
[11]-> $2.hello("John") | $6 ==> "John"
Các lớp danh sách
Một lớp Java là một kiểu. Giao diện cũng là một kiểu. Tất cả các kiểu được xác định trong phiên JShell được liệt kê với / type yêu cầu. Xác định một số lớp và giao diện.
[4]-> [1]-> class C{} | created class C [2]-> class D{} | created class D [3]-> class B{} | created class B [4]-> interface I{} | created interface I [5]-> interface J{} | created interface J
Chạy / type lệnh và tất cả các lớp và giao diện được liệt kê.
[6]-> /types | class C | class D | class B | interface I | interface J
Sử dụng công cụ tạo lớp
Lớp no-arg được định nghĩa ngầm trong một lớp nếu nó không xác định bất kỳ hàm tạo nào có args. Trước đây chúng tôi đã khởi tạo một lớp C đã không khai báo rõ ràng bất kỳ hàm tạo nào với new C () . Hàm tạo không đối số có thể được định nghĩa một cách rõ ràng.
Tiếp theo, tạo một lớp Hello khai báo một phương thức khởi tạo lớp. Hàm tạo có một tham số kiểu String . Hàm tạo có thể được khai báo với public công cụ sửa đổi và hoàn toàn là công khai nếu không được đặt thành công khai .
[6]-> class Hello{ String name; public Hello(String name){this.name=name;} void hello(){System.out.println("Hello "+name);} }
Tạo một phiên bản của lớp Hello .
Hello hello=new Hello("John")
Gọi phương thức phiên bản hello () để xuất một thông báo, như trong Hình 3.
Hình 3: Sử dụng một lớp có hàm tạo
Mở rộng lớp học
Một lớp có thể được mở rộng với phần mở rộng giống như trong tệp mã nguồn Java. Ví dụ:tạo lớp D khai báo một tên biến kiểu tt> String, một hàm tạo no-arg và một phương thức hello (String) . xin chào (Chuỗi) phương thức xuất ra một "Hello" tin nhắn bằng name arg cung cấp.
class D{ String name="Michael"; public D(){} void hello(String name){System.out.println("Hello "+name);} }
Tạo một lớp C mở rộng lớp C và khai báo hello () phương thức này không ghi đè lớp D ‘S xin chào (Chuỗi) phương pháp và các tham số là khác nhau. hello () phương thức gọi một tên trường, được kế thừa từ lớp D .
class C extends D{ void hello(){System.out.println("Hello "+name);} }
Khởi tạo lớp C và gọi hello () phương pháp.
new C().hello()
Thông báo “Xin chào” được xuất ra, như thể hiện trong Hình 4. Tên giá trị trường được đặt trong lớp D được sử dụng.
Hình 4: Mở rộng lớp học
Nếu chúng ta gọi hello (Chuỗi) phương thức mà lớp C kế thừa từ lớp D , chúng ta sẽ nhận được một đầu ra khác, như trong Hình 5.
Hình 5: Gọi một phương pháp kế thừa từ một lớp mở rộng
Ghi đè một phương pháp
Một lớp có thể ghi đè một phương thức được kế thừa từ một lớp mở rộng bằng cách cung cấp định nghĩa phương thức của riêng nó. Tạo một lớp D khai báo một trường tên và một phương thức hello () .
class D{ String name="Michael"; void hello(){System.out.println("Hello "+name);} }
Khai báo một lớp C mở rộng lớp D và ghi đè hello () phương pháp. Lớp C cũng ẩn trường name .
class C extends D{ String name="John"; void hello(){System.out.println("Hello "+name); }
Tạo một phiên bản của lớp C và gọi phương thức hello () .
new C().hello()
hello () phương thức từ lớp C được gọi vì nó ghi đè phương thức từ lớp D . Trường tên trong lớp C ẩn trường name trong lớp D . Đầu ra thông báo được hiển thị trong Hình 6.
Hình 6: Ghi đè một phương pháp
Nếu lớp C không ẩn trường tên từ lớp D , tên trường trong lớp D được sử dụng, như trong Hình 7.
Hình 7: Truy cập Trường từ Lớp mở rộng
Một lớp C đối tượng là một thể hiện của lớp D vì nó mở rộng lớp D . Chạy câu lệnh sau để tìm xem một bản sao của lớp C cũng là một thể hiện của lớp D .
new C() instanceof D
Giá trị true xác minh một bản sao của lớp C cũng là một thể hiện của lớp D , như trong Hình 8.
Hình 8: Xác minh xem một Bản sao của Lớp C cũng là một bản sao của Lớp D
Bởi vì một thể hiện của lớp C cũng là một thể hiện của lớp D , nó có thể được chuyển thành D như sau:
D d=(D)(new C());
Sau đó, truy cập trường tên cho đối tượng d thuộc loại D .
d.name;
Và gọi phương thức hello () cho đối tượng d thuộc loại D .
d.hello();
Giá trị đầu ra của trường là từ lớp D bởi vì d là một đối tượng kiểu D , như trong Hình 9. Phương thức hello () được gọi là từ lớp C .
Hình 9: Truyền một đối tượng loại C sang D
Sử dụng giao diện
Trong phần này, chúng ta sẽ chạy một số đoạn mã cho các giao diện trong JShell. Một lớp hiện có có thể được sửa đổi để triển khai một giao diện. Tạo lớp C .
[1]-> class C { } | created class C
Tạo giao diện I xác định một phương thức hello () .
[2]-> interface I { String hello(); } | created interface I
Khai báo lại lớp C để triển khai giao diện I . Lớp C cung cấp triển khai cho phương thức hello () .
[3]-> class C implements I{ public String hello(){ return "Hello JShell"; } } | replaced class C
Tạo một phiên bản của lớp C .
[4]-> new C() | $1 ==> [email protected]
Sử dụng biến cá thể lớp, gọi phương thức hello () và đầu ra của phương thức được hiển thị.
[5]-> $1.hello() | $2 ==> "Hello JShell" [6]->
Bởi vì các phương thức trong giao diện là công khai hoàn toàn trong khi các phương thức trong một lớp không phải là một phương thức, việc triển khai trong lớp C phải được khai báo với public công cụ sửa đổi truy cập. Nếu không được khai báo public , một thông báo lỗi được xuất ra vì không chỉ định public công cụ sửa đổi truy cập mặc định thành công cụ sửa đổi truy cập yếu hơn, điều này không được phép khi triển khai giao diện.
[3]-> class C implements I{ String hello(){ return "Hello JShell"; } } | Error: | hello() in C cannot implement hello() in I | attempting to assign weaker access privileges; was public | String hello(){ | ^--------------...
Sử dụng Triển khai Mặc định cho một Phương pháp
Kể từ Java 8, một phương thức giao diện có thể cung cấp một triển khai mặc định cho một phương thức bằng cách sử dụng từ khóa default . Khai báo giao diện cung cấp triển khai mặc định cho phương thức hello () sử dụng mặc định từ khóa.
[1]-> interface I { default String hello(){ return "Hello JShell"; } } | created interface I
Khai báo một lớp C triển khai giao diện I .
[2]-> class C implements I{ } | created class C
Tạo một phiên bản của lớp C và gọi phương thức hello () . Phương thức từ triển khai mặc định trong giao diện I nhận được đầu ra.
[3]-> new C().hello(); | $1 ==> "Hello JShell"
Khai báo một phương thức giao diện là tĩnh
Kể từ Java 8, các phương thức Giao diện có thể được khai báo static . Tạo giao diện I khai báo một static phương pháp.
[1]-> interface I { static String hello(){ return "Hello JShell"; } } | created interface I
Gọi phương thức tĩnh bằng cách sử dụng giao diện I .
[2]-> I.hello() | $1 ==> "Hello JShell"
Một lớp không thể được khai báo là cuối cùng và nếu cuối cùng bổ ngữ được sử dụng, nó bị bỏ qua.
[5]-> [1]-> final class C{} | Warning: | Modifier 'final' not permitted in top-level declarations, | ignored | final class C{} | ^---^ | created class C
Sử dụng Mảng
Trong phần này, chúng ta sẽ chạy một số đoạn mã cho các mảng. Khai báo, khởi tạo và truy cập mảng không khác gì trong một ứng dụng dựa trên tệp mã nguồn Java. Ví dụ, khai báo một mảng kiểu String [] . Mảng được khởi tạo thành null .
[1]-> String[] strArray; | strArray ==> null
Cấp phát bộ nhớ cho mảng. Kích thước mảng, sau khi đã đặt, không thể sửa đổi. Các phần tử của mảng được khởi tạo thành null .
[2]-> strArray =new String[3]; | strArray ==> String[3] { null, null, null }
Khởi tạo các phần tử mảng bằng cách sử dụng các chỉ số mảng.
[3]-> strArray[0]="A"; strArray[1]="B"; strArray[2]="C"; | $4 ==> "A" | $5 ==> "B" | $6 ==> "C"
Xuất ra độ dài mảng và phần tử ở chỉ mục 1.
[6]-> strArray.length; strArray[1]; | $9 ==> 3 | $10 ==> "B"
Độ dài mảng được xuất là 3. Phần tử ở chỉ mục 1 là “B”. Một mảng có thể được khởi tạo khi được khai báo như sau.
[1]-> String[] strArray={"A","B","C"}; | strArray ==> String[3] { "A", "B", "C" }
Xuất ra độ dài mảng.
[2]-> strArray.length; | $1 ==> 3
Xuất phần tử ở chỉ mục 0.
[3]-> strArray[0]; | $4 ==> "A" [4]->
Một mảng nhiều chiều có thể được khai báo giống như trong ứng dụng Java. Tạo mảng ba chiều kiểu String [] [] [] và khởi tạo mảng.
[1]-> String[][][] strArray={{{"A","B","C"},{"AA","AB","AC"}}, {{"B","C","A"},{"BB","BC","BA"}},{{"C","A","B"}, {"CC","CA","CB"}}}; | strArray ==> String[3][][] { String[2][] { String[3] | { "A", "B", "C" }, String[3] { "AA", ...
Xuất ra độ dài mảng.
[2]-> strArray.length; | $1 ==> 3
Xuất ra độ dài của mảng ở chỉ số 0.
[3]-> strArray[0].length; | $4 ==> 2
Xuất ra độ dài của mảng ở chỉ số 1 trong mảng ở chỉ số 0.
[4]-> strArray[0][1].length; | $6 ==> 3
Xuất mảng ở chỉ số 0.
[5]-> strArray[0] | $10 ==> String[2][] { String[3] { "A", "B", "C" }, | String[3] { "AA", "AB", "AC" } }
Xuất mảng ở chỉ mục 1 trong mảng ở chỉ mục 0.
strArray[0][1] | $11 ==> String[3] { "AA", "AB", "AC" }
Xuất phần tử ở chỉ số 0 trong mảng ở chỉ mục 1 trong mảng ở chỉ số 0.
strArray[0][1][0] | $12 ==> "AA" [8]->
Sử dụng các Ngoại lệ Bỏ chọn
JShell ném ra các ngoại lệ không được kiểm tra trong thời gian chạy. Ví dụ, nếu một biến kiểu String đã được khởi tạo thành giá trị mặc định của nó null được truy cập. java.lang.NullPointerException được ném.
[1]-> String str; | str ==> null [2]-> str.length(); | java.lang.NullPointerException thrown: | at (#2:1) [3]->
Ví dụ khác, nếu chỉ mục mảng bên ngoài kích thước của mảng được truy cập, java.lang.ArrayIndexOutOfBoundsException được ném.
[4]-> String[] str={"A","B","C"}; | str ==> String[3] { "A", "B", "C" } [5]-> str[3]; | java.lang.ArrayIndexOutOfBoundsException thrown: 3 | at (
Nếu một phương thức xác định phép chia cho 0 được gọi, java.lang.ArithmeticException được ném.
[1]-> int average(int i,int j){ return (i+j)/0; } | created method average(int,int) [2]-> average(2,4) | java.lang.ArithmeticException thrown: / by zero | at average (#1:2) | at (#2:1) [3]->
Kết luận
Trong bốn bài đầu tiên này, chúng ta đã thảo luận về việc chạy các đoạn mã cho các biến, câu lệnh, phương thức, lớp, giao diện và mảng. JShell được thiết kế để chỉ chạy các đoạn mã và do đó một số tính năng khác với khi chạy một ứng dụng Java hoàn chỉnh từ một tệp mã nguồn. Trong hai bài viết nữa, chúng ta sẽ khám phá một số tính năng khác của JShell.