Java Silver への道 配列の作成と使用編
配列
配列とは複数の値の集合をまとめて扱うための「インスタンス」である。
配列を使用するときはnewキーワードを使って配列のインスタンスを生成しなければいけない。またこのときは整数値(小数点は不可)で要素数を指定する必要があり、要素名は変えることができない。
~配列インスタンスの生成~
new int[3];
配列は変数に格納した参照を用いて扱う
~配列型変数の宣言~
int[] array;
配列型変数には配列インスタンスへの参照(リンク先)を代入する。
変数内に要素が直接入るわけではない。
また配列型変数には参照を入れるだけであるため、要素数を指定することはできない。
int array[];
配列を表す大かっこ「[]」は変数名の後ろに記述することもできる
~サンプルコード~
public static void main(String[] args) { // 要素数3の配列インスタンスを生成し、整数のint型の配列型変数arrayにインスタンスの居場所を参照 int[] array = new int[3]; // 配列インスタンスの0番目の箱に1を代入 array[0] = 1; // 要素数3の配列インスタンスを生成し、オブジェクト型の配列型変数scoresに参照 Object[] scores = new Object[3]; // 変数arrayの参照先インスタンスにはStringクラスがないため、ObjectクラスのtoStringメソッドが呼び出されて、ハッシュコードが出る System.out.println(array); // 要素の値を出したいときは参照先の要素数まで指定 System.out.println(array[0]); // 整数型のデフォルト値は0 System.out.println(array[1]); // オブジェクト型のデフォルト値はnull System.out.println(scores[0]); } }
結果
[I@15db9742
1
0
null
初期演算子
配列インスタンスの生成と同時に要素の値を入れたい場合に用いる
int[] array = {10,20,30};
int[] array = new int[]{10,20,30};
どちらも同じ意味を持つが、後者の場合要素数を指定するとコンパイルエラーが起きる。
なぜなら初期演算子は自動的に要素数を計算してくれるからだ。
多次元配列
配列の特徴には以下の2点が挙げられる
- 配列は参照を通して扱う
- 複数の参照をひとまとめに扱うことができる
このことから、参照先の配列がさらに複数の参照を持っていることを「多次元配列」という。
~2次元配列~
int[][] array = new int[2][3];
このとき、変数とインスタンスの間で次元数を一致させる必要がある
~nullが含まれている多次元配列~
要素の値にnullが入ると何も参照しないという意味になる。
またnullにはlengthは存在しない。
サンプルコード(nullがない場合)
public class Main { public static void main(String[] args) { String[][] array = { { "A", "B" }, { "C", "D", "E" } }; int total = 0; for (String[] tmp : array) { total += tmp.length; } System.out.println(total); } }
結果
5
String[][] array = { { "A", "B" }, { "C", "D", "E" } };
arrayの1つ目の要素には"A"“B"の参照、2つ目の要素には"C”“D”“E"の参照が代入されている
for (String[] tmp : array) {
arrayの要素を1つずつtmpに代入、要素数は2なので2回ループ。
このときtmpはString型なので参照先の"A"“B"は一つずつtmpの要素に入る
total += tmp.length;
1回目はtmpに"A"“B"2つの要素数が入るのでlengthは2:total = 0 + 2
2回目は"C”“D”“E"3つが入るのでlengthは3:total = 2 + 3
サンプルコード(nullがある場合)
public class Main { public static void main(String[] args) { String[][] array = { { "A", "B" }, null,{ "C", "D", "E" } }; int total = 0; for (String[] tmp : array) { total += tmp.length; } System.out.println(total); } }
String[][] array = { { "A", "B" }, null,{ "C", "D", "E" } };
2つ目の要素にnullが入る、nullが入った要素は何も参照しない
for (String[] tmp : array) {
total += tmp.length;
}
処理を実行中、nullにはlengthがないため、ここでNullPointerExceptionが発生する
配列と継承関係
クラスが継承関係にあるとき、スーパークラス型の配列変数で、サブクラスのインスタンスの集合を扱える
Object[] obj = {"A","B","C"};
Object型しか扱わない配列型変数objとString型しか扱わない配列インスタンスは、扱う型が異なるが、StringクラスはObjectクラスを継承しているためコンパイル・実行ができる。
つまり全ての配列型変数は、Object型に暗黙的に型変換できるということだ。
~サンプルコード~
public interface A {} public abstract class B implements A {} public class C extends B {} public class D extends C {}
このコードは以下のような仕組みを表している
public class Main { public static void main(String[] args) { A[] arrray = {new C(),null,new D()}; Object[] objArray = array; } }
CクラスとDクラスはAインターフェースを実装しているBクラスを継承している。そのため変数型配列AはC型とD型の配列インスタンスを扱える。
また全ての配列型変数はObject型を継承しているため、型を暗黙的に変換してくれる。
ここで、nullが入っているarrayやobjarrayを使う処理があれば、NullpointerExpectionが生じる。
配列のコピー
~cloneメソッド~
cloneメソッドを使うと、同じ値を持った配列インスタンスが複製される。
public static void main(String[] args) { int[] arrayA = { 1, 2, 3, 4 }; //arrayAと同じ値を持った配列インスタンスを作成 int[] arrayB = arrayA.clone(); //値は複製だがインスタンスは異なるため結果はfalseに System.out.println(arrayA == arrayB); //arrayAの値がコピーされているので出力される for (int i : arrayB) { System.out.println(i); } } }
結果
false
1
2
3
4
~arraycopyメソッド~
Systemクラスのarraycopyメソッドは、配列の一部をコピーしたいときに使用する
引数 | 説明 |
---|---|
第1引数 | コピー元となる配列 |
第2引数 | コピー元のどの位置からコピーを開始するか(0始まり) |
第3引数 | コピー先の配列 |
第4引数 | コピー先のどの位置からコピーを開始するか(0始まり) |
第5引数 | 第2引数を含んでいくつの要素をコピーするか |
サンプルコード
System.out.println(ArrayA,1,arrayB,0,4);
「arrayAの1番目から合計4つの要素をarrayBの0番目にコピーする」という意味である
Java Silver への道 演算子と判定構造の使用編
代入演算子
値を変数に代入するための演算子のこと
public class Sample { public static void main(String[] args) { int a = 5; int b = a += 5; // 演算によってaに代入された値は受け継がれる int c = a -= 3; int d = a *= 5; int e = a /= 5; System.out.println(b); System.out.println(c); System.out.println(d); System.out.println(e); } }
結果
10
7
35
7
*=(イコール)を記述しないと、aは初期値の「5」として演算される
数値演算のときの型について
数値を演算するとき、演算子の両側のオペランドは同じ型でなければいけない。
もしオペランドの型が異なる場合、小さいほうの型は大きいほうの型に自動変換される。
public class Sample { public static void main(String[] args) { int a = 10; short b = 10; //bはint型に変換される //a+bはint型のため、short型で記述するとコンパイルエラーが生じる int c = a + b; } }
インクリメント
インクリメント演算子「++」とデクリメント演算子「–」は、変数の値に1 を加算したり減算したりするための演算子である。
~前置インクリメント「++a」と後置インクリメント「a++」~
前置インクリメントは、先に加算し、その値をaに代入する。
後置インクリメントは、aは前の値を引き継ぎ、その後加算し、aに代入する。
public class Sample { public static void main(String[] args) { int a = 10; //()のタイミングでインクリメントされ、代入された値は引き継がれる // 10(11)+(12)12+(13)13 int b = a++ + ++a + ++a; System.out.println(b); } }
結果
35
同一性と同値性
同一性:同じインスタンスを参照している
同値性:違うインスタンスではあるけれども、同じ値である
同一性は「==」演算子で表す。戻り値はbooleanであるため、左右のオペランドのインスタンスが合致していた場合「true」が返ってくる。
同値性を確認するためのメソッドはequalsである。ただし、Objectクラスに定義されているメソッドは同一性を確認する実装になっている。そのため、設計者が自ら、どの値の一致を確認するのかequalsメソッドをオーバーライドしなければならない。
public class Sample { // フィールドの設定 private int num; private String name; // コンストラクタの設定 public Sample(int num, String name) { this.num = num; this.name = name; } public boolean equals(Object obj) { // 同一性の確認 if (obj == null) { return false; } // オーバーライドして同値性の確認 if (obj instanceof Sample) { Sample sample = (Sample) obj; return sample.num == this.num; } return false; } }
public class Main{ public static void main(String[] args) { //Sample型のインスタンスを作成 Sample a = new Sample(10, "a"); //Sample型のインスタンスを作成 Sample b = new Sample(10, "b"); //Sample型aのequalsメソッドの引数にsample型のbを入れる System.out.println(a.equals(b)); }
処理の流れ
public class Sample { private int num; private String name; public Sample(int num, String name) { this.num = num; this.name = name; } //暗黙的にSample型はObject型に変換される(Object型の方が大きいため) public boolean equals(Object obj) { // 同一性の確認 if (obj == null) { return false; } //objに入っているbがSampleと同じクラスかインスタンスであることが条件 if (obj instanceof Sample) { //Object型であるobjをSample型にキャストして変数sampleに代入(numはObjectではなくSample型に定義されたフィールドであるため) Sample sample = (Sample) obj; //sampleのnumとaに入っているnumの値を確認 return sample.num == this.num; } return false; } }
結果
true
オーバーロード
オーバーライドと似ている言葉にオーバーロードがある。
オーバーロードとは、同じメソッドでも異なる引数を定義することで、違う結果を導くというものだ。
public class Main { public static void main(String[] args) { Sample a = new Sample(10, "a"); Sample b = new Sample(10, "b"); //bはSample型である System.out.println(a.equals(b)); } }
public class Sample { private int num; private String name; public Sample(int num, String name) { this.num = num; this.name = name; } public boolean equals(Object obj) { if (obj == null) { return false; } if (obj instanceof Sample) { Sample sample = (Sample) obj; return sample.num == this.num; } return false; } //同じメソッドだが、引数をSample型にしてオーバーロードしている public boolean equals(Sample s) { return s.name == this.name; } }
結果
false
コンスタントプール
文字列リテラルは、インスタンスの生成が使いまわしされる。そのため、同じ参照となる。
public class Main { public static void main(String[] args) { String a = "sample"; // 使いまわしされる String b = "sample"; System.out.println(a == b); } }
結果
true
*ただし、new演算子を使って明示的に新しいインスタンスを生成した場合は異なる参照となる
if文・if-else文・if-else if文
- if文中の{}は省略可能で、その場合は次の1文だけが条件に合致した場合の処理として実行される
public class Main { public static void main(String[] args) { if (false) System.out.println("A"); //この部分はif文に含まれていない処理となる System.out.println("B"); } }
結果
B
- if-else文
if (条件式){ //条件に合致した時の処理 }else{ //条件に合致しなかったときの処理 }
public class Main { public static void main(String[] args) { int num = 10; if (num < 10) { // 条件に合致した時の処理 System.out.println("A"); } else { // 条件に合致しなかった時の処理 System.out.println("B"); } //2つ目のif文も実行される if (num == 10) { // 条件に合致した時の処理 System.out.println("C"); } } }
結果
B
C
- if-else if文は、複数の分岐条件を一度に記述することができる。elseとifの間で改行することができず、2つ目のif文はelse文の中にある分岐として解釈される。
public class Main { public static void main(String[] args) { int num = 10; if (num == 100) // 条件Aに合致した時の処理 System.out.println("A"); else if (10 < num) // 条件Bに合致しなかった時の処理 System.out.println("B"); else //上記の条件に合致しなかったとき //else内で分岐 if (num == 10) // 条件に合致した時の処理 System.out.println("C"); else//上記の条件に合致しなかったとき //すでに条件合致しているため以降の処理は実行されない if (num == 10) { System.out.println("D"); } } }
結果
C
三項演算子
条件に合致するかどうかで、戻す値を変更する演算子である。
真偽値 ? trueの場合に評価する式 : falseの場合に評価する式
public class Main { public static void main(String[] args) { String a = "A"; String b = "B"; //AとBの同値性を確かめtrueであればno、falseであればyes String c = a.equals(b) ? "no" : "yes"; System.out.println(c); } }
結果
yes
switch文
条件によって分岐するif文に対してswitch文は値によって処理を分岐する。
case値にマッチする処理が実行され、処理が終わればbrakeを使ってswitch文を抜けるようにする。一致するものがなかったときはdefault文以降が実行される。
switch (条件文) { case 値: 処理 break; case 値: 処理 break; default:処理 break; }
~条件式のルール~
条件式が戻せる値の型には制限があり、以下のような種類がある
種類 | 値名 |
---|---|
int型以下の整数型とそのラッパークラス | int/Integer/short/Short/byte/Byte |
文字と文字列 | char/Character/String |
列挙型 | enum |
~case値のルール~
- 条件式が戻す型と同じ型か互換性があること
- 定数であるか、コンパイル時に値を決めることができること
- nullでないこと
「定数であること」…final宣言された変数かもしくはリテラルを表す
~breakを記述しなかった場合~
条件に合致したあと以降に現れるすべてのcase式の処理がbreakが現れるまで実行される。
そのときdefault式も対象となる。
public static void main(String[] args) { int num = 10; switch (num) { case 9: System.out.println("yeah"); case 10:// 条件に合致したため処理を実行 System.out.println("A"); // breakが記述されていないため以降の処理がすべて実行される case 11: System.out.println("B"); case 12: System.out.println("C"); default:// default式も対象となる System.out.println("D"); } } }
結果
A
B
C
D
Java Silver への道 データ型(参照型)編
参照型
参照型は簡単に言えば基本データ型以外の型のことである。
具体的に参照型には、オブジェクト型、列挙型、配列型がある。
String,Date,Integer,ArrayListなど
参照型を使用する際には基本的にインスタンスを生成する。
(static修飾されているメソッドや変数を使用するときはインスタンスの生成は不要)
*参照型の中でもString型は特別で、基本データと同じような宣言が可能。
参照型の変数
参照型の変数は、オブジェクトへの参照*1を保持しているか、保持していないかのどちらかしか表現できない。
参照を保持していないことを表現するためのリテラルが「null」である。
public class Main { public static void main(String[] args) { Object obj = null; System.out.println(obj); } }
シグニチャ
シグニチャとは、メソッド名と引数のセットのことを指す。
javaにはオーバーロードという仕組みがあるため、メソッドを見分けるためには引数も加える必要がある。
// helloメソッドと引数"pochi"のシグニチャ s.hello("pochi");
ガーベッジコレクション
ガーベッジコレクションとは、不要なインスタンスを探し、破棄することを指す。ガーベッジコレクションが起こるタイミングはプログラマーが制御することはできず、JVMが決める。
ガーベッジコレクションの対象となるのは、「どこからも参照されなくなったインスタンス」である。代表的なタイミングとしては、nullを代入したときである。
JavaSilver取得への道 基本編メモ
パッケージ
パッケージを使用する目的は以下のようにまとめられる。
- 名前空間を提供し、名前の衝突を避ける
- アクセス修飾子と組み合わせてアクセス制御機能を提供する
- クラスの分類を可能にする
1.名前空間を提供し、名前の衝突を避ける
例えば、パッケージ名を"tsujimari"とする。すると、tsujimariパッケージ内で作られたクラスは"tsujimari.クラス名"という完全修飾クラス名で表すことができる。
このようにしてクラス名が重複しても区別することができる。
ちなみに、パッケージ名にはドメイン名を逆にしたものを使用するのが慣習である。
2.アクセス修飾子と組み合わせてアクセス制御機能を提供する
アクセス修飾子 | 内容 |
---|---|
private | 同じクラス内からしか呼び出せない |
省略 | 同じパッケージ内からしか呼び出せない |
protected | 同じパッケージ内か、そのサブクラスから呼び出せる |
public | どこからでも呼び出せる |
アクセル修飾子を使用することで、パッケージ内のクラスを”公開するクラス”と”非公開にするクラス”に分けることができる。
3.クラスの分類を可能にする
パッケージはディレクトリ機能とマッピングされるため、管理が簡単になる。
パッケージのインポート宣言
①明示的にパッケージ宣言したクラスから無名パッケージに属するクラスにアクセスしようとするとコンパイルエラーが起きる
//無名パッケージに属するSampleクラス public class Sample { public static int num = 10; }
package example; //exampleという明示的に宣言したパッケージに属するSampleImpleクラス //無名パッケージに属するSampleクラスは同じ無名パッケージに属するクラスからしかアクセスできないため、Sample/numでエラーがでる。 public class SampleImple extends Sample{ public static void main(String[] args) { System.out.println(num); } }
この場合、Sampleクラスをexampleパッケージ内に作成すれば解決する。
②異なるパッケージのクラスにアクセスするときはインポートを宣言する
package sample2; //sample2という明示的に宣言したパッケージに属するSampleクラス public class Sample { public static int num = 10; }
package example; //sample2パッケージのSampleクラスをインポートする宣言 import sample2.Sample; public class SampleImple extends Sample{ public static void main(String[] args) { System.out.println(num); } }
インポート宣言は、省略表記のために用いるだけであり、インポートしたフィールドやメソッドがコピーされる訳ではない。よって以下のような書き方でも可。
package example; //完全修飾クラス名で表記 public class SampleImple extends sample2.Sample{ public static void main(String[] args) { System.out.println(num); } }
sample2に属するクラス全てをインポートしたい場合はアスタリスクを使用する
import sample2.*;
staticインポート
staticとは
staticとは、クラスに属するものであり、インスタンスを生成しなくても実行することができる。
そのため、staticメソッドから非staticなメンバ(インスタンス変数)にアクセスすることはできない。
なぜなら、インスタンスの有無に関係ないstaticメソッドから呼び出しても、どのインスタンス変数にアクセスしていいのか分からないからである。
staticインポートの書き方
staticなフィールドはメソッドはクラスに属しているため、”クラス名.フィールド名”や”クラス名.メソッド名”とどのクラスに定義されているものか明示しなければいけない。
//sampleクラスのstaticなprintメソッドをインポート import static sample.print
メソッドがオーバーロードされたメソッドが複数あった場合は引数によって呼び出されるメソッドが決まるため、インポート宣言で引数を指定する必要はない
エントリーポイント
複数あるメソッドの中でも、最初に処理を始めるメソッドのことで、mainメソッドを指す。
エントリーポイントの定義は以下のように決められている。
public static void main(String[] args) { //}
変更可能なのは引数名である”args”の部分だけである。
ちなみに引数にはString配列型だけではなく、可変長引数のString型を受け取ることもできる。
Javaコマンド
javaコマンドで、mainメソッドに渡す引数のことを”起動パラメータ”や”コマンドライン引数”という。
javaの構文は以下のようになる。
参考文献:「java se8 silver 問題集」
セッション
セッションとは
ブラウザとサーバーの一連のやりとりのこと。
例えばあるwebサイトにアクセスして、そのサイトから出て行くかブラウザを閉じるまでが1セッションとなる。
セッション管理を用いると、ショッピングサイトなどで異なるページを開いても同一クライアントの情報を管理することができる。
多くの場合ページの閲覧時間が何分か開くと新しいセッションとしてカウントされる。サイトでよく見かける”セッションタイムアウトになりました”というのがこれを意味する。
HttpSessionインタフェースを使用するとサーブレットコンテナがセッション管理を容易に行ってくれる。
セッション管理サンプルコード
package example; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; @WebServlet("/count") public class CountServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { HttpSession session = req.getSession(); Integer count = (Integer) session.getAttribute("count"); if (count == null) { count = 0; } count++; session.setAttribute("count", count); resp.setContentType("text/html;charset=UTF-8"); PrintWriter out = resp.getWriter(); out.println("<html>"); out.println("<head><title>Count</title></head>"); out.println("<body>"); out.println("<h1>Count: " + count + "</h1>"); out.println("<a href=\"count\" >count</a>"); out.println("</body>"); out.println("</html>"); } }
HttpSession session = req.getSession();
doGetメソッドでは、HttpServletRequestオブジェクトに対してgetSessionメソッドを呼び出し、HttpSessionオブジェクトを取得している。
この時引数を指定していないので、初回アクセス時などセッションが存在していない場合は新しいセッションが作成される。
Integer count = (Integer) session.getAttribute("count");
HttpSessionオブジェクトのgetAttributeメソッドを呼び出し、"count"という名前で保存されたデータの値を取得している。この時データがなければnullで返却される。
また、getAttributeはオブジェクト型で返却され、基本データ型は扱えない。そのため今回はIntegerにキャストして変数countをint型として扱っている。
if (count == null) { count = 0; } count++; session.setAttribute("count", count);
変数countがnullでないことを確認し、countをカウントアップしている。そしてその後HttpsSessionオブジェクトに対しsetAttributeメソッドを呼び出し、"count"という名前をつけcountオブジェクトをセッションに保存している。
サーブレット入門
サーブレット入門
私たちががwebサイトを見るとき、実は内部では以下のような過程が行われている。
クライアントであるwebブラウザはwebサーバーにhttpリクエストを送る。そしてそのリクエストをもとにサーバーからデータを収集し、レスポンスを返しているのである。
仕組みを図解すると以下のようになる。
サーブレット
サーブレットとはアプリケーションサーバー内で動くjavaクラスのことである。サーブレット単独で動くことはできず制御する実行環境上(サーブレットコンテナ)で動く。
ユーザーが作るサーブレットは、servletインタフェースを直接は実装せずHttp.Servletクラスを継承する形をとる。
httpリクエスト
httpリクエストは、クライアントからサーバー側に送られる要求のことである。httpリクエストは以下のような構成になっている。
1行目はリクエストラインである。サーバーに要求する情報で、メソッド、リクエストURL、プロトコルバージョンで構成されている。
GET / HTTP/1.1
httpのバージョン1.1で通信を行い、/というURLに対して情報を取得(GET)したいという要求である。
GETとPOST
GETとPOSTはクライアントからサーバーに情報を送信したりするときに使用するメソッドである。HttpServletクラスにあるdoPost()・doGet()メソッドをオーバーライドしてサーブレットから呼び出す。 両者の違いは以下のようなところにある。
GETを使用して情報を送信:URLに付与する形でリクエストパラメータを送信する。URLの後ろに?を付け、名前=値の順番で記述する。
またクライアントがwebページの情報をサーバーに要求するだけの場合は基本的にGETを用いる。
POSTを使用して情報を送信:入力フォームを使用して送信する。
サーブレット側に送信されたリクエストパラメーターを取得するときはgetParameter(String name)メソッドを使用する。
httpレスポンス
HttpServletResponseオブジェクトはhttpレスポンスを表現しており、httpレスポンスは以下のような構成になっている。
レスポンスでhtmlを返却する場合はボディ部にhtmlが格納される。
setContentType(String type)メソッドを使用することで返却するレスポンスのコンテントタイプを指定することができる。
コンテントタイプの指定
package sample; import java.io.IOException; import java.io.PrintWriter; import java.util.Arrays; import java.util.List; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.ws.RespectBinding; @WebServlet("/names") public class NameSarvlet extends HttpServlet { @Override protected void doGet(HttpSevletRequest req,HttpServletResponse resp)throws ServletException, IOException{ List<String> names = Arrays.asList("John","Paul","George","Ringo"); resp.setContentType("text/html; charset=UTF-8"); PrintWriter out = resp.getWriter(); out.println("<html>"); out.println("<head><title>Names</title></head>"); out.println("<body>"); out.println("<ul>"); for(String name : names){ out.println(<"li"> + name + </li"">); } out.println("</ul>"); out.println("</body>"); out.println("</html>"); } }
@WebServlet("/names") public class NameSarvlet extends HttpServlet {
1行目ではnamesという名前のサーブレットを作成するということを表している。この名前はURLに関連した名前である。
2行目でNameSarvletクラスはHttpServletクラスを継承している。
@Override protected void doGet(HttpSevletRequest req,HttpServletResponse resp)throws ServletException, IOException{
HttpServletクラスのdoGet();メソッドをオーバーライドしている。
doGetメソッドでは、サーブレットがクライアントに返すレスポンス内容を含むHttpServletResponseオブジェクトを生成している。
resp.setContentType("text/html; charset=UTF-8");
setContentTypeの引数には文字列でテキストタイプを指定する。
PrintWriter out = resp.getWriter();
レスポンスのボディ部にテキストデータを出力するためにgetWriter();メソッドからPrintWriterオブジェクトを取得する。
out.println("<html>"); out.println("<head><title>Names</title></head>"); out.println("<body>"); out.println("<ul>"); :
PrintWriterオブジェクトに対してHTMLを出力している。結果としてHTMLがレスポンスボディに格納されることになる。
JDBC(Java Database Connectivity)
JDBCとは
Java言語でデータベースにアクセスするためのインターフェース(API)のこと。
あくまで仕様であり、実装されていないため中身はない 。
中身の実装はDB製品の種類に応じてDBを提供している各ベンダーのJDBCドライバが行う。
JDBC API
Javaプログラムで使用し、JDBCドライバとの接続を行うための標準インターフェースである。機能は以下のようになっている。
- データベースへ接続する
- SQL文を発行する
- データベースが処理した結果を取り出す
- データベースの情報や処理結果に関する情報を取り出す
JDBC DriverManager
java.sqlパッケージのクラスであり、JavaプログラムとJDBCドライバの間に位置する。複数のJDBCドライバを管理することができる。
JDBCドライバ
データベースに直接アクセスするためのに使用する、JDBCインターフェースの具象クラスのこと。