JShellは、コードスニペットの実行を容易にするJava9の新機能です。 JShellコードスニペットは、アプリケーションのファイル内のJavaソースコードとまったく同じです。以前の記事「NetBeans9.0のJava9でのJShellの使用、パート3」で説明したように、JShellでは、ソースコードファイルでサポートされているデフォルト、アクセス、同期、パブリック、プライベート、保護などのいくつかの修飾子は許可されていません。 。 JShellは、主にJavaコードのテストとデバッグ用に設計されており、完全なアプリケーションを実行するためのものではありません。この続きの記事では、クラス、インターフェイス、および配列のスニペットを実行します。以前の記事と同様に、NetBeans9を使用しました。未チェックの例外についても説明します。この記事には次のセクションがあります:
- クラスの使用
- クラスの変更
- クラスの一覧表示
- クラスコンストラクターの使用
- クラスの拡張
- メソッドのオーバーライド
- インターフェースの使用
- メソッドのデフォルト実装の使用
- インターフェイスメソッドを静的であると宣言する
- 配列の使用
- チェックされていない例外の使用
- 結論
クラスの使用
このセクションでは、クラスのコードスニペットの実行について説明します。単純なクラスCを宣言します 次のように。
[1]-> class C { } | created class C
クラスC 作成されます。直接呼び出すことができるメソッドとは異なり、クラスは最初に次のようにインスタンス化する必要があります。
[3]-> new C() | $1 ==> [email protected]
クラスC、$ 1の新しいインスタンス 作成されます。メソッド宣言と同様に、クラス宣言はクラスを再宣言することで変更できます。クラスは、implementsを使用してインターフェースを実装できます。 。例として、インターフェース Iを宣言します 。
[1]-> interface I{} | created interface I
クラスCを作成します インターフェイスIを実装する 。
[3]-> class C implements I{} | replaced class C [4]->を置き換えました
クラスC 、以前に作成されたものが置き換えられます。
JShellのクラス宣言には、ファイルで宣言されたJavaクラスのようなアプリケーションの概念がありません。 public static void main(String [] argv)を含むファイル内のJavaクラス メソッドはJavaアプリケーションです。 public static void main(String [] argv) メソッドはJShellに追加できますが、これは単なる別のコードスニペットです。クラスを作成するこんにちは これには、メソッド 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(String []) メソッドは静的です メソッドであり、クラスのインスタンスではなく、クラスに対して定義されます。 String []を作成します main(String [])に提供する配列 メソッド。
String[] strArray={"Hello"," JShell"};
main(String [])を呼び出します String []を使用するメソッド 引数として。
Hello.main(strArray)
図1に示すように、HelloJShellメッセージが出力されます。
図1: クラスで静的メソッドを呼び出す
クラスの変更
クラスは、そのメソッド宣言のいずれかを変更または削除するか、新しいメソッドを追加することにより、必要に応じて変更できます。クラスを再宣言するこんにちは main(String [])なし メソッドとクラスが置き換えられます。
[4]-> class Hello{ } | replaced class Hello [5]->を置き換えました
main(String [])を再度追加します メソッドですが、 System.out.printlnが少し異なります。 声明。クラスこんにちは 再び交換されます。
[5]-> class Hello{ public static void main(String[] argv) {System.out.println(argv[0]);} } | replaced class Hello [5]->を置き換えました
静的を呼び出す メソッドmain(String []) Hello.main(strArray)を使用 図2に示すように、別の出力の場合。
図2: メソッドメインのバリエーションを呼び出す
クラスを置き換えるためのプロビジョニングは、クラスを開発するときに役立ちます。一度に1つのメソッドを追加して、クラスをテストできます。例として、2番目のメソッド hello(String)を追加します 。繰り返しますが、クラスこんにちは 交換されます。
[9]-> class Hello{ void main(String[] argv){System.out.println(argv[0]);} String hello(String name){return name;} } | replaced class Hello
メソッドhello(String) 追加された、インスタンスメソッドであるため、呼び出すにはクラスインスタンスが必要です。クラスインスタンスを作成します。
[10]-> new Hello() | $2 ==> [email protected]
メソッドhello(String)を呼び出します クラスインスタンスを使用する$2 。
[11]-> $2.hello("John") | $6 ==> "John"
クラスの一覧表示
Javaクラスは型です。インターフェイスもタイプです。 JShellセッションで定義されたすべてのタイプは、 / typesでリストされます。 指図。いくつかのクラスとインターフェースを定義します。
[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
/ typesを実行します コマンドとすべてのクラスとインターフェイスが一覧表示されます。
[6]-> /types | class C | class D | class B | interface I | interface J
クラスコンストラクタの使用
no-argクラスは、argsでコンストラクターを定義しない場合、クラスで暗黙的に定義されます。以前にクラスCをインスタンス化しました new C()で明示的にコンストラクターを宣言しなかった 。引数なしのコンストラクターは明示的に定義できます。
次に、クラス Helloを作成します クラスコンストラクターを宣言します。コンストラクターには、タイプ Stringのパラメーターが1つあります。 。コンストラクターはpublicで宣言できます 修飾子であり、暗黙的に public publicに設定されていない場合 。
[6]-> class Hello{ String name; public Hello(String name){this.name=name;} void hello(){System.out.println("Hello "+name);} }
クラスHelloのインスタンスを作成します 。
Hello hello=new Hello("John")
インスタンスメソッドhello()を呼び出します 図3に示すように、メッセージを出力します。
図3: コンストラクターでのクラスの使用
クラスの拡張
クラスは、Javaソースコードファイルの場合と同様に、extendsを使用して拡張できます。例として、クラス Dを作成します tt> String型の変数名、引数なしのコンストラクター、およびメソッド hello(String)を宣言します。 。 hello(String) メソッドは"Hello"を出力します 名前を使用したメッセージ 引数が提供されました。
class D{ String name="Michael"; public D(){} void hello(String name){System.out.println("Hello "+name);} }
クラスCを作成します クラスCを拡張します hello()を宣言します クラスDをオーバーライドしないメソッド のhello(String) メソッドとパラメータが異なります。 hello() メソッドは、クラス Dから継承されたフィールド名を呼び出します 。
class C extends D{ void hello(){System.out.println("Hello "+name);} }
クラスCをインスタンス化します hello()を呼び出します メソッド。
new C().hello()
図4に示すように、「Hello」メッセージが出力されます。 name クラスDに設定されたフィールド値 使用されます。
図4: クラスの拡張
hello(String)を呼び出した場合 クラスCのメソッド クラスDから継承 、図5に示すように、異なる出力が得られます。
図5: 拡張クラスからの継承メソッドの呼び出し
メソッドのオーバーライド
クラスは、独自のメソッド定義を提供することにより、拡張クラスから継承されたメソッドをオーバーライドできます。クラスを作成するD フィールドnameを宣言します およびメソッドhello() 。
class D{ String name="Michael"; void hello(){System.out.println("Hello "+name);} }
クラスを宣言するC クラスDを拡張します hello()をオーバーライドします 方法。クラスC フィールドnameも非表示にします 。
class C extends D{ String name="John"; void hello(){System.out.println("Hello "+name); }
クラスCのインスタンスを作成します メソッドhello()を呼び出します 。
new C().hello()
hello() クラスCのメソッド クラスDのメソッドをオーバーライドするために呼び出されます 。フィールドname クラスC フィールドnameを非表示にします クラスD 。メッセージ出力を図6に示します。
図6: メソッドのオーバーライド
クラスCの場合 フィールドnameを非表示にしません クラスDから 、名前 クラスDのフィールド 図7に示すように、が使用されます。
図7: 拡張クラスからフィールドにアクセスする
クラスC オブジェクトはクラスDのインスタンスです クラスDを拡張するため 。次のステートメントを実行して、クラス Cのインスタンスかどうかを確認します。 クラスDのインスタンスでもあります 。
new C() instanceof D
trueの値 クラスCのインスタンスを検証します クラスDのインスタンスでもあります 、図8に示すように。
図8: クラスCのインスタンスがクラスDのインスタンスでもあるかどうかの確認
クラスCのインスタンスであるため クラスDのインスタンスでもあります 、 Dにキャストできます 次のように:
D d=(D)(new C());
続いて、フィールド nameにアクセスします オブジェクトdの場合 タイプD 。
d.name;
そして、メソッド hello()を呼び出します オブジェクトdの場合 タイプD 。
d.hello();
フィールド値の出力は、クラス Dからのものです。 d タイプDのオブジェクトです 、図9に示すように。メソッド hello() 呼び出されるのはクラスCからです 。
図9: タイプCのオブジェクトをDにキャストする
インターフェースの使用
このセクションでは、JShellのインターフェース用にいくつかのスニペットを実行します。既存のクラスを変更して、インターフェースを実装することができます。クラスCを作成します 。
[1]-> class C { } | created class C
インターフェイスを作成するI メソッドhello()を定義します 。
[2]-> interface I { String hello(); } | created interface I
クラスCを再宣言します インターフェイスIを実装する 。クラスC メソッドhello()の実装を提供します 。
[3]-> class C implements I{ public String hello(){ return "Hello JShell"; } } | replaced class C
クラスCのインスタンスを作成します 。
[4]-> new C() | $1 ==> [email protected]
クラスインスタンス変数を使用して、メソッド hello()を呼び出します メソッドの出力が表示されます。
[5]-> $1.hello() | $2 ==> "Hello JShell" [6]->
インターフェイスのメソッドは暗黙的にpublicであるため クラス内のメソッドはメソッドではありませんが、クラス Cでの実装 publicで宣言する必要があります アクセス修飾子。 publicと宣言されていない場合 、 public を指定していないため、エラーメッセージが出力されます アクセス修飾子はデフォルトで弱いアクセス修飾子に設定されていますが、これはインターフェースの実装時には許可されていません。
[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(){ | ^--------------...
メソッドのデフォルト実装の使用
Java 8以降、インターフェースメソッドは、キーワード default を使用して、メソッドのデフォルト実装を提供する場合があります。 。メソッドhello()のデフォルトの実装を提供するインターフェースを宣言します デフォルトを使用する キーワード。
[1]-> interface I { default String hello(){ return "Hello JShell"; } } | created interface I
クラスを宣言するC インターフェイスIを実装します 。
[2]-> class C implements I{ } | created class C
クラスCのインスタンスを作成します メソッドhello()を呼び出します 。インターフェイスIのデフォルト実装のメソッド 出力を取得します。
[3]-> new C().hello(); | $1 ==> "Hello JShell"
インターフェイスメソッドを静的であると宣言する
Java 8以降、Interfaceメソッドは staticとして宣言される可能性があります 。インターフェイスを作成するI 静的を宣言します メソッド。
[1]-> interface I { static String hello(){ return "Hello JShell"; } } | created interface I
インターフェイスIを使用して静的メソッドを呼び出します 。
[2]-> I.hello() | $1 ==> "Hello JShell"
クラスをfinalとして宣言することはできません。また、 final の場合、 修飾子が使用され、無視されます。
[5]-> [1]-> final class C{} | Warning: | Modifier 'final' not permitted in top-level declarations, | ignored | final class C{} | ^---^ | created class C
配列の使用
このセクションでは、配列のコードスニペットをいくつか実行します。配列の宣言、インスタンス化、およびアクセスは、Javaソースコードファイルベースのアプリケーションと同じです。例として、タイプ String []の配列を宣言します 。配列はnullに初期化されます 。
[1]-> String[] strArray; | strArray ==> null
アレイにメモリを割り当てます。配列サイズは、一度設定すると変更できません。配列要素はnullに初期化されます 。
[2]-> strArray =new String[3]; | strArray ==> String[3] { null, null, null }
配列インデックスを使用して配列要素を初期化します。
[3]-> strArray[0]="A"; strArray[1]="B"; strArray[2]="C"; | $4 ==> "A" | $5 ==> "B" | $6 ==> "C"
配列の長さとインデックス1の要素を出力します。
[6]-> strArray.length; strArray[1]; | $9 ==> 3 | $10 ==> "B"
配列の長さは3として出力されます。インデックス1の要素は「B」です。配列は、次のように宣言すると初期化できます。
[1]-> String[] strArray={"A","B","C"}; | strArray ==> String[3] { "A", "B", "C" }
配列の長さを出力します。
[2]-> strArray.length; | $1 ==> 3
インデックス0の要素を出力します。
[3]-> strArray[0]; | $4 ==> "A" [4]->
多次元配列は、Javaアプリケーションの場合と同じように宣言できます。タイプString[] [] []の3次元配列を作成します アレイを初期化します。
[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", ...
配列の長さを出力します。
[2]-> strArray.length; | $1 ==> 3
インデックス0の配列の長さを出力します。
[3]-> strArray[0].length; | $4 ==> 2
インデックス0の配列内のインデックス1の配列の長さを出力します。
[4]-> strArray[0][1].length; | $6 ==> 3
インデックス0の配列を出力します。
[5]-> strArray[0] | $10 ==> String[2][] { String[3] { "A", "B", "C" }, | String[3] { "AA", "AB", "AC" } }
インデックス0の配列内のインデックス1の配列を出力します。
strArray[0][1] | $11 ==> String[3] { "AA", "AB", "AC" }
インデックス0の配列内のインデックス1の配列のインデックス0の要素を出力します。
strArray[0][1][0] | $12 ==> "AA" [8]->
チェックされていない例外の使用
JShellは、実行時にチェックされていない例外をスローします。例として、タイプ Stringの変数の場合 デフォルト値nullに初期化されています アクセスされます。 java.lang.NullPointerException スローされます。
[1]-> String str; | str ==> null [2]-> str.length(); | java.lang.NullPointerException thrown: | at (#2:1) [3]->
別の例として、配列のサイズ外の配列インデックスにアクセスした場合、 java.lang.ArrayIndexOutOfBoundsException スローされます。
[4]-> String[] str={"A","B","C"}; | str ==> String[3] { "A", "B", "C" } [5]-> str[3]; | java.lang.ArrayIndexOutOfBoundsException thrown: 3 | at (
ゼロ除算を定義するメソッドが呼び出された場合、 java.lang.ArithmeticException スローされます。
[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]->
結論
これらの最初の4つの記事では、変数、ステートメント、メソッド、クラス、インターフェイス、および配列のコードスニペットの実行について説明しました。 JShellは、コードスニペットのみを実行するように設計されているため、一部の機能は、ソースコードファイルから完全なJavaアプリケーションを実行する場合とは異なります。さらに2つの記事で、JShellの他の機能について説明します。