アクセス修飾子

Javaのアクセス修飾子には最もアクセス制限の緩いpublicから制限の厳しいprivateまで、以下の4種類があります。

修飾子 UMLの可視性 説明
public + すべてのクラスからアクセス可能
protected # 同じパックージ内のクラス、もしくはパッケージ外のサブクラスからアクセス可能
パケージプライベート(指定なし) ~ 同じパックージ内のクラスからのみアクセス可能
private 同一クラス内からのみアクセス可能

アクセス修飾子はクラス、インターフェース、フィールド、メソッド、コンストラクタに指定して、それぞれに対するアクセス制御を行います。
但し、クラス、インターフェースには、publicとパケージプライベートの2種類です。
これはprotectedでクラスを修飾すれば、同一パケージ内かそのサブクラスからしかアクセスできない事になり、クラスの利用範囲が著しく狭くなります。またprivateでは外部から利用できない事になるからです。但し、例外的に内部(インナー)クラスの宣言時に限ってprivateは指定可能です。
これに対しフィールドやメソッドには、4種類の修飾子全てが指定可能です。

それでは、parentパッケージにpublic指定したParentクラスを作り、そのクラスにpublic、protected、指定なし(パケージプライベート)の3種類の指定をしたメソッドを作り、それらメソッドをパッケージ外に作るChildクラスから呼んでアクセス制限がどのようにかかるか見てみましょう。

parentパッケージにスパークラス(親クラス)としてParent.javaを作り、オーバーロードしたメソッドを三つ作って、それぞれに異なるアクセス修飾子を指定します。

package parent;

public class Parent {
        private String msg;
        public void setmsg(String msg) {
                this.msg = msg;
        }
        public void getmsg() {
                System.out.println(msg);
        }
        protected void getmsg(String msg) {
                System.out.println(msg);
        }
        void getmsg(String nashi, String msg) {
                System.out.println(msg);
        }
}

次にparentパケージ外にParentのサブクラス(子クラス)として作るChild.java

import parent.Parent;

public class Child extends Parent {
        public Child() {
                super.setmsg("子から親のpublicメソッドは呼べる");
                super.getmsg();
                super.getmsg("子から親のprotectedメソッドも呼べる");
                super.getmsg("アクセス修飾子なし", "子から親のアクセス修飾子なしメソッドは呼べない");
        }
}

Childクラスをコンパイルすると、以下のようにChild.javaの8行目、親クラスの「アクセス修飾子なし」のメソッドを呼んでいる所で「メソッドにアクセス出来ない」というコンパイルエラーが出ます。

\>javac Child.java
Child.java:8: エラー: Parentのgetmsg(String,String)はpublicではありません。パッケージ外からはアクセスできません
         super.getmsg(“アクセス修飾子なし”, “子から親のアクセス修飾子なしメソッドは呼べない”);
            ^
エラー1個

>

つまり、 アクセス修飾子なし指定の親クラスのメソッドはパケージ外の子クラスからはアクセスできません

一方、Child.javaの8行目をコメントアウトして再度コンパイルすると、エラーは出ずクラスファイルが出来るので、Childクラスのインスタンスを作るメインクラスChild_Main.javaを作り、実行します。
すると public及びprotectedを指定したメソッドはパケージ外の子クラスからでもアクセスできる ことが分かります。

public class Child_Main {
	public static void main(String args[]) {
		Child cd = new Child();
	}
}
>java Child_Main
子から親のpublicメソッドは呼べる
子から親のprotectedメソッドも呼べる

>

それでは、最後にアクセス修飾なし指定でアクセス可能な場合を調べてみましょう。
アクセス修飾なし指定されたメソッドは同じパッケージ内の別クラスからはアクセスできるはずなので、Parent.Javaと同じparentパケージ内にParent_Main.javaを作り、実行してみます。

package parent;

public class Parent_Main {
	public static void main(String args[]) {
		Parent cd = new Parent();
		cd.setmsg("同じパケージのpublicメソッドは呼べる");
		cd.getmsg();
		cd.getmsg("同じパケージのprotectedメソッドは親子関係がなくても呼べる");
		cd.getmsg("アクセス修飾子なし", "同じパケージのアクセス修飾子なしメソッドは呼べる");
	}
}
>java parent.Parent_Main
同じパケージのpublicメソッドは呼べる
同じパケージのprotectedメソッドは親子関係がなくても呼べる
同じパケージのアクセス修飾子なしメソッドは呼べる

>

このように、4つのアクセス修飾子のうち、 区別が付きにくいのはprotectedとパケージプライベートの違い です。
整理しておくと、protectedなフィールドやメソッドは、パッケージ外のサブクラスからでもアクセスできるのに対し、ぺケージプライベート、つまりアクセス修飾子を指定しなかった場合は、パッケージ外のサブクラスからはアクセスできず、同一パケージ内のクラスからのみアクセスできます。

次に、アクセス修飾子の中でprotectedは他の修飾子と異なり「サブクラスからのアクセスを許す」パケージとは関係のない条件が設定されています。ここで、間違えやすいのはクラスとインスタンスを同列に考えてしまうことです。

例を見てましょう。
親クラスにprotectedで修飾したメソッドを定義し、別パケージに子クラスを作り、メインクラスで子クラスのインスタンスを作って、そのインスタンス経由で親クラスで定義されたメソッドを利用します。

親クラス

package there;

public class Book {
	private String bookNum;
	public void setbookNum (String bookNum) {
		this.bookNum = bookNum;
	}	
	protected void printlnfo() {
		System.out.println(bookNum);
	}
}

子クラス

package here;
import there.Book;

public class Books extends Book{

}

メインクラス

package here;

public class Main {
	public static void main(String[] args) {
		Books favorite = new Books();

		favorite.bookNum("123-4-567-89012-3");
		favorite.printlnfo();
	}
}

コンパイル結果

>javac here\Main.java
here\Main.java:8: エラー: printlnfo()はBookでprotectedアクセスされます
                favorite.printlnfo();
                        ^
エラー1個

>

親クラス、子クラスのコンパイルは通りますがメインクラスのコンパイルで上記のエラーが出ます。
これはメインメソッドの中で子クラスのインスタンス経由メインクラスのprotected修飾されたメソッドにアクセスしているからです。勘違いしやすいのはprotected修飾子は子クラスに対してアクセスを許すのであって、子クラスのインスタンスにアクセスを許しているわけではない点です。
ここが、パッケージに対するアクセス制御ではないprotected修飾子を指定する上での注意です。

では、本来のprotected修飾子の利用法はどうなるのでしょうか、いくつかの例が考えられます。

例1:
親クラスは変えずに、子クラスの中でメソッドをオーバーロードして、そのメソッドを同じパケージに置いたメインメソッドの中でアクセスします。

子クラス

package here;
import there.Book;

public class Books4All extends Book{
	
	protected void printInfo(String str) {
		System.out.print(str);
		printlnfo();
	}
}

メインクラス

package here;
import there.Book;

public class Main4All{
	public static void main(String[] args) {

		Books4All bk4all = new Books4All();
		bk4all.setbookNum("123-4-567-89012-3");
		bk4all.printInfo("ISBN:");
	}
}

実行結果
メインクラスは同じパケージにあるクラスのprotected修飾されたメソッドにアクセスするので、実行することが出来ます。

>java here.Main4All
ISBN:123-4-567-89012-3

>

例2:
親クラスは変えずに、子クラスは例1と同じようにメソッドをオーバーロードして、今度は子クラスとは別のパケージに置いたメインメソッドの中でアクセスします。

メインクラス

package there;
import here.Books4All;

public class Main4All {
	public static void main(String[] args) {

		Books4All bk4all = new Books4All();
		bk4all.setbookNum("123-4-567-89012-3");
		bk4all.printInfo("ISBN:");
	}
}

コンパイル結果
protected修飾されたメソッドをインスタンスの中でアクセスするので最初と同じコンパイルエラーが出ます。

>javac there\Main4All.java
there\Main4All.java:9: エラー: printInfo(String)はBooks4Allでprotectedアクセスされます
                bk4all.printInfo("ISBN:");
                      ^
エラー1個

>

例3:
例2のコンパイルエラーを無くすためには、子クラスのメソッドのアクセス修飾子をpublicに変更します。

package here;
import there.Book;

public class Books4All extends Book{
	
	public void printInfo(String str) {
		System.out.print(str);
		printlnfo();
	}
}

実行結果

>java there.Main4All
ISBN:123-4-567-89012-3

>

以上の事から、アクセス修飾子でアクセス制御できるのはクラスであってインスタンスではありません。
インスタンスからアクセス出来るメソッドは、同一クラス内を除けばpublic修飾されたクラスのpublicメソッドか、同じパッケージならデフォルト(パケージプライベート)修飾されたメソッドのみという事が分かります。

カプセル化に戻る

パケージ

パッケージの役割は数多くのプログラムをある単位でまとめ、プログラム群を区分けするため、と一般には説明されています。
確かにパケージは、

特定のOSに依存しない名前空間を提供し、実行時の名前の衝突を避ける
Javaファイル、classファイルの分類を可能にする。

という機能があります。

しかしそれだけではなく、

アクセス修飾子と組む合わせてアクセス制御機能を提供する。

役割も果たしています。

アクセス修飾子はクラスファイルを他のクラスファイルからアクセス可能にするか否かを提供しますが、
アクセス修飾子だけでは、

すべてのクラスからアクセス可能。
同一クラス内からのみアクセス可能(自分以外のクラス外からはアクセス禁止)。

の2者択一しか設定できません。

しかし、アクセス修飾子をパッケージと組み合わせることにより、さらに
同じパックージ内のクラスからアクセス可能(別パケージからはアクセス禁止)。
という設定が可能になります。

同一パケージ内のクラス群は、一般的には同一目的で同一時期に開発されるプログラム群(=プログラム部品)と考えられるので、この設定は同一目的のプログラム間ではアクセス可能で、同一目的を持たないプログラム群からはアクセスできないという事になります。
つまり、プログラム部品をブラックボックス化するため、アクセスを目的が同じプログラム部品を構成する同一パッケージ内のクラスに制限することが出来ます。

カプセル化に戻る

setterとgetter

一般的に、classのフィールドのアクセス修飾子設定はprivateにし、フィールドは外部に対し隠蔽すべきとされています。
これは、C言語などで変数が簡単に外部のプログラムによって値を壊されてしまう経験から推奨されていることです。

しかし、フィールドのアクセス修飾子をprivateに設定したからといって、同じクラスからはアクセスできるので完全に安全というわけではありません。不注意で自分自身が変数の値を壊してしまうことは起こりえることだからです。

そこで、アクセス修飾子だけに頼るのではなく、プログラム的に値の変更の正当性、妥当性をチェックして設計時の意図に反する値の変更を避けることが出来るように、setter、getterメソッドを経由してのみフィールドにアクセスするのが熟練の技、ベストプラクティスです。

setterは名前の通りフィールドの値を設定するメソッドで、getterはフィールドの値を取出すメソッドです。
通常はsetterもgetterもアクセス修飾子はpublicで設定し、全てのクラスからアクセス可能にしますが、フィールドの値変更を特定のクラスのみに限りたい場合は、getterのみpublicに設定し、setterをデフォルト又はprotectedに設定する場合もあります。

なお、フィールドの変数の数が多くなるとsetterとgetterのコーディング自体が面倒だったり、タイプミスをしたりします。
これらの対策としてEclipseでは、メンバ変数をカーソルで選択し[ソース]-[getterおよびsetterの生成]で自動的にsetter、getterのコードを生成する事が出来ます。

カプセル化に戻る

Mapインターフェース

コレクションフレームワークに属するMapインターフェースはListインターフェースと違い、0から始まるインデックスではなくキーとバリューを一対にして要素を管理します。mapインスタンスの宣言はジェネリックの< >の中にキーとバリューの型をカンマ区切りで指定し、要素の登録はputメソッド、取り出しはgetメソッドで行います。
要素の登録では同じキーの複数登録はできませんが、キーが違えば同じバリューの複数登録は可能です。

要素を連続して取り出すには、keySetメソッドでキーの一覧をSetオブジェクトに取り出し、Setオブジェクトから拡張for文でキーを順次取り出しながら、getメソッドでバリューを取出します。下記HashMapを使ったサンプルの15行目から18行目及び21行目から24行目を参照)

Mapインターフェースの実装の一つがHashMapです。
HashMapはハッシュを使って、要素の保存場所を決定するので、要素の追加・削除・変更という操作が、要素の数に関わらず一定の時間で実行可能です。

import java.util.Map;
import java.util.Set;
import java.util.HashMap;

public class HashMapSample {
	public static void main(String[] args) {

		Map<Integer, String> map=new HashMap<>( ); 
		System.out.println(map.size());
		System.out.println("---------------");
		map.put(1, "Bach");
		map.put(10, "Chopin");
		map.put(100, "Anonymous");
		
		Set<Integer> keys = map.keySet();
		for(int key: keys) {
			System.out.println("key:" + key + " value:" + map.get(key));
		}
		System.out.println("---------------");
		map.put(101, "Anonymous");
		keys = map.keySet();
		for(int key: keys) {
			System.out.println("key:" + key + " value:" + map.get(key));
		}
		System.out.println("---------------");
		System.out.println("Map contains key:10 (\"Chopin\"):" + map.containsKey(10));
		map.remove(100, "Anonymous");
		System.out.println(map.size());
		System.out.println(map);
	}
}

実行結果
>java HashMapSample
0
—————
key:1 value:Bach
key:100 value:Anonymous
key:10 value:Chopin
—————
key:1 value:Bach
key:100 value:Anonymous
key:101 value:Anonymous
key:10 value:Chopin
—————
Map contains key:10 (“Chopin”):true
3
{1=Bach, 101=Anonymous, 10=Chopin}

>

また、別の実装としてTreeMapクラスがあります。
基本的な仕様はHashMapと変わりませんが、要素を辞書順にソートして管理します。
実行結果の最後のmap内の要素の呼び出し結果をHashMapのそれと比較してください。

import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class TreeMapSample {
	public static void main(String[] args) {

		Map<Integer, String> map=new TreeMap<>( ); 
		System.out.println(map.size());
		System.out.println("---------------");
		map.put(1, "Bach");
		map.put(10, "Chopin");
		map.put(100, "Anonymous");
		
		Set<Integer> keys = map.keySet();
		for(int key: keys) {
			System.out.println("key:" + key + " value:" + map.get(key));
		}
		System.out.println("---------------");
		map.put(101, "Anonymous");
		keys = map.keySet();
		for(int key: keys) {
			System.out.println("key:" + key + " value:" + map.get(key));
		}
		System.out.println("---------------");
		System.out.println("Map contains key:10 (\"Chopin\"):" + map.containsKey(10));
		map.remove(100, "Anonymous");
		System.out.println(map.size());
		System.out.println(map);
	}
}

実行結果
>java TreeMapSample
0
—————
key:1 value:Bach
key:10 value:Chopin
key:100 value:Anonymous
—————
key:1 value:Bach
key:10 value:Chopin
key:100 value:Anonymous
key:101 value:Anonymous
—————
Map contains key:10 (“Chopin”):true
3
{1=Bach, 10=Chopin, 101=Anonymous}

>

コレクション に戻る

Setインターフェース

コレクションフレームワークに属するSetインターフェースはListインターフェースと違い、要素を追加した順番を管理しません。また、同じ値のオブジェクトはセットの中に複数追加できません
指定の要素が集合の中にあるか否かを素早く確認するなどに有効です。
0から始まるインデックスを持たないため、要素の取り出しには拡張for文、またはiteratorだけが使用できます。

Listインターフェースの実装にはHashSetとTreeSetがあります。

まずHashSetクラスですが、これはハッシュを使って、要素の保存場所を決定するので、要素の追加・削除が、要素の数に関わらず一定の時間で実行できます。

import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;

public class HashSetSample {
	public static void main(String[] args) {

		Set<String> set=new HashSet<>( ); 
		System.out.println(set.size());
		System.out.println("---------------");
		set.add("Bach");
		set.add("Chopin");
		set.add("Anonymous");
		for(String str: set) {
			System.out.println(str);
		}
		System.out.println("---------------");
		set.add("Anonymous");
		for(Iterator<String> it = set.iterator(); it.hasNext();) {
			System.out.println(it.next());
		}
		System.out.println("---------------");
		System.out.println("Set contains \"Chopin\":" + set.contains("Chopin"));
		set.remove("Anonymous");
		System.out.println(set);
	}
}

実行結果です。
0
—————
Chopin
Bach
Anonymous
—————
Chopin
Bach
Anonymous
—————
Set contains “Chopin”:true
[Chopin, Bach]

>

次はTreeSet
基本的な仕様はHashSetと変わりませんが、要素を辞書順にソートして管理します。

import java.util.Set;
import java.util.TreeSet;
import java.util.Iterator;

public class TreeSetSample {
	public static void main(String[] args) {

		Set<String> set=new TreeSet<>( ); 
		System.out.println(set.size());
		System.out.println("---------------");
		set.add("Bach");
		set.add("Chopin");
		set.add("Anonymous");
		for(String str: set) {
			System.out.println(str);
		}
		System.out.println("---------------");
		set.add("Anonymous");
		for(Iterator<String> it = set.iterator(); it.hasNext();) {
			System.out.println(it.next());
		}
		System.out.println("---------------");
		System.out.println("Set contains \"Chopin\":" + set.contains("Chopin"));
		set.remove("Anonymous");
		System.out.println(set);
	}
}

実行結果です。
>java SetSample
0
—————
Anonymous
Bach
Chopin
—————
Anonymous
Bach
Chopin
—————
Set contains “Chopin”:true
[Bach, Chopin]

>

コレクション に戻る

コレクション フレームワーク

通常、複数のオブジェクトを管理するために配列を使います。しかし、配列は事前に配列の次元や要素の数を決めなければいけないなど、オブジェクトの動的な管理には適しません

これに対し、コレクションには配列にない、いくつかの特徴があります

初期化で要素数を指定する必要がない。
要素の追加・削除・挿入がメソッドを呼ぶことにより自由に行える。
要素のソーティングや検索がメソッドで可能。
コレクションはいくつかのインターフェースで仕様が決められているので、利用するクラスが異なっても同じ仕様のメソッドを利用して要素を管理することが出来る。
ただし、管理できるのは参照型のオブジェクトだけで基本型のデータは扱えない。必要な場合はラッパークラスとして定義し、AutoBoxingで自動変換して扱う。
コレクションフレームワークは性質の若干異なるList、Set、Mapなどにより構成され、それぞれにインターフェースが定義され、それぞれを実装したクラスが用意されているので、実際の課題ごとに適切はクラスを選択して使います。

コレクションフレームワークの構造

それぞれの特徴、利用法は下記を参照してください。
Listインターフェース
Setインターフェース
Mapインターフェース

以上でコレクションフレームワークの仕様と基本的な利用法は理解できたと思いますが、コレクションは「参照型のオブジェクト」を管理する仕組み、という実際の利用効果を見てみましょう。
参照型のオブジェクトとは簡単に言えばクラスですから、クラスのインスタンスを集めて管理できるという事です。さらに、クラスが継承関係を持っていれば、スーパクラスと合わせてサブクラスのインスタンスも合わせて一括管理が出来るという事です。
それでは、電話番号を管理するPhoneクラスを作り、継承によって電話番号と合わせてEmailアドレスも管理するmobileクラスを作って、それらのインスタンスをListArrayに入れて一括管理し、Phoneとmobileを使い分けながら利用するところを見てみましょう。
まず、Phoneクラス

public class Phone {
	private String no;
	
	public Phone(String myNo) {
		this.no = myNo;
	}
	
	public String getNo() {
		return no;
	}
	public void setNo(String no) {
		this.no = no;
	}
	
	public void call(String to) {
		System.out.println("電話番号" + no + "番から、電話番号" + to + "番に電話しました。");
	}
}

次に、Phoneクラスを継承したMobileクラス

public class Mobile extends Phone {
	private String emAdd;
	
	public Mobile(String no, String myEmAdd) {
		super(no);
		this.emAdd = myEmAdd;
	}
	
	public String getEmAdd() {
		return emAdd;
	}
	public void setEmAdd(String emAdd) {
		this.emAdd = emAdd;
	}
	
	public void mobileInfo() {
		System.out.println("私の携帯の電話番号は" + super.getNo() + "番で、メールアドレスは" + emAdd + "です。");
	}
	public void send(String to) {
		System.out.println("メールを" + emAdd + "から、" + to + "に送信しました。");
	}
}

さらに、PhoneクラスとMobileクラスを一括管理して使う処理です。

import java.util.*;

public class MyPhones {
	public static void main(String[] args) {
		List<Phone> pList = new ArrayList<>();
		
		pList.add(new Phone("0123-45-6789"));
		pList.add(new Mobile("090-8765-4321", "abcd@efgh.ijk.lm"));
		pList.add(new Phone("0234-56-7890"));
		
		System.out.println(pList);
		
		for(Phone use : pList) {
			use.call("0120-333-4444");
		}
		System.out.println("-----------------------");
		Mobile mbl = (Mobile)pList.get(1);
		mbl.mobileInfo();
		mbl.send("opqr@stu.vw.xyz");
	}
}

実行結果

>java MyPhones
[Phone@15db9742, Mobile@6d06d69c, Phone@7852e922]
電話番号0123-45-6789番から、電話番号0120-333-4444番に電話しました。
電話番号090-8765-4321番から、電話番号0120-333-4444番に電話しました。
電話番号0234-56-7890番から、電話番号0120-333-4444番に電話しました。
-----------------------
私の携帯の電話番号は090-8765-4321番で、メールアドレスはabcd@efgh.ijk.lmです。
メールをabcd@efgh.ijk.lmから、opqr@stu.vw.xyzに送信しました。

>
以上が、クラスのインスタンスを集めて管理し、一括されたそれらの情報を利用する、配列とは違ったコレクションの利点です。

コレクション に戻る

Listインターフェース

コレクションフレームワークに属するListインターフェースは配列と同じように0からのインデックスで要素の集まりを扱います。
配列との大きな差は配列は要素の追加が出来ないのに対し、Listインターフェースは要素の追加・削除が可能なことです。
Listインターフェースのメソッドのうち、addメソッドは指定された要素をリストの最後に追加し、clearメソッドは指定された全ての要素をリストから削除し、removeメソッドは指定された要素をリストの先頭から探し、最初に見つかった同じ要素をリストから削除し、setメソッドはリスト内の指定された位置にある要素を、指定された要素に置き換えます。なお、addメソッドにはリスト内の指定された位置に、指定された要素を挿入するメソッド、removeメソッドには指定された位置にある要素を削除するメソッドもあります。
Listインターフェースの実装クラスで良く用いられるのはArrayListクラスです。
なお、ArrayListの宣言では扱う要素の型をジェネリックとして< >の中に記述し、それ以外の型のオブジェクトが追加されないようコンパイラーにチェックさせます。
また、要素の取り出しにはfor文、拡張for文、iteratorを使用します。
Listの実装クラスにArrayListを利用した例

import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;

public class ListSample {
	public static void main(String[] args) {

		List<String> list=new ArrayList<>( ); 
		System.out.println(list.size());
		System.out.println("---------------");
		list.add("B");
		list.add("C");
		list.add(0, "A");
		for(int i=0; i<list.size(); i++) {
			System.out.println(list.get(i));
		} 
		System.out.println("---------------");
		list.add("A");
		for(String str: list) {
			System.out.println(str);
		}
		System.out.println("---------------");
		list.set(3, "D");
		for(Iterator<String> it = list.iterator(); it.hasNext();) {
			System.out.println(it.next());
		}
		System.out.println("---------------");
		list.remove(0);
		System.out.println(list);
	}
}

実行結果

>java ListSample
0
---------------
A
B
C
---------------
A
B
C
A
---------------
A
B
C
D
---------------
[B, C, D]

>

Listインターフェースを実装したクラスには、ArrayListのように要素を連続的に並べるのではなくリンク情報で関連付けたLinkedListがあります。LinkedListの機能はArrayListと変わりませんがリンク情報の書き換えで要素の挿入、削除が行えるのでArrayListよりもそれらの処理が早く行えます。しかし、逆に、連続的に要素を扱う読出しや書き込みはArrayListよりも処理が遅くなります。

Listの実装クラスにLinkedListを利用した例

import java.util.List;
import java.util.LinkedList;
import java.util.Iterator;

public class LinkedListSample {
	public static void main(String[] args) {

		List<String> list=new LinkedList<>( ); 
		System.out.println(list.size());
		System.out.println("---------------");
		list.add("B");
		list.add("C");
		list.add(0, "A");
		for(int i=0; i<list.size(); i++) {
			System.out.println(list.get(i));
		} 
		System.out.println("---------------");
		list.add("A");
		for(String str: list) {
			System.out.println(str);
		}
		System.out.println("---------------");
		list.set(3, "D");
		for(Iterator<String> it = list.iterator(); it.hasNext();) {
			System.out.println(it.next());
		}
		System.out.println("---------------");
		list.remove(0);
		System.out.println(list);
	}
}

実行結果
同じインターフェースを実装しているので実行結果に違いはありません。

>java ListSample
0
---------------
A
B
C
---------------
A
B
C
A
---------------
A
B
C
D
---------------
[B, C, D]

>

コレクション に戻る

Kichu - Proudly powered by WordPress