【Java】JSPでタグライブラリを使う(JSTL)
こんにちは。エンジニアの新田です!ここでは、システムエンジニアとして働いている私が、システム開発手法や開発言語について紹介していこうと思います。今回は、JSPの標準タグライブラリ「JSTL」について紹介します。Javaについて勉強している方、Webアプリケーションを構築したいと思っている方の参考になれば幸いです!関連記事リンク: 【Java】JSPの基本的な構文/【Java】JSPのアクションタグ
Workteria(ワークテリア)では難易度の高いものから低いものまで、スキルや経験に合わせた案件を多数揃えています。会員登録は無料ですので、ぜひ会員登録してご希望の案件を探してみてください!
フリーランス/正社員のエンジニアとして活躍するには、ご自身のスキルや経験に合わせた仕事を選ぶことが大切です。ご希望の案件がみつからない場合はお気軽にお問い合わせください!ユーザ満足度の高いキャリアコンサルタントが在籍していますので、希望条件や悩み事などなんでもご相談ください。ご希望にピッタリの案件をご紹介させていただきます。
こんにちは。新人エンジニアのサトウです。
システムエンジニアとして駆け出したばかりですが、
初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。
プログラム初心者✅にも、プログラムに興味がある人✨も、
短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!
Javaでインスタンスをコピーするには
ディープコピー(深いコピー)
シャローコピー(浅いコピー)
の二つの方法を検討する必要があります。
配列のコピーについては【Java】配列のコピーで紹介しています。
シャローコピーは、実体のコピーを行わずにインスタンスをコピーする方法です。
コピーしたインスタンス自体は、元のインスタンスとは別の扱いであるものの、参照先は同じになります。
ですのでインスタンスのメンバ変数を変更した場合は、もう一方のインスタンスにも影響が及びます。
「=演算子」を使ってインスタンスを代入する事で、シャローコピーを行う事ができます。
シャローコピーを下記のサンプルコードで確認しましょう。
サンプルコード
import java.util.ArrayList;
//インスタンス用クラス
class DuplicateObject {
public int value = 0;
public String source = "あいさつ";
public ArrayList<Integer> list = new ArrayList<>();
//出力メソッドの定義
public void dump(String name) {
System.out.println("----[" + name + "]----");
System.out.println("value:" + value);
System.out.println("source:" + source);
System.out.println("list:" + list.toString());
}
}
public class Test {
public static void main(String[] args) {
//インスタンスを生成
DuplicateObject origin = new DuplicateObject();
origin.value = 1;
origin.source = "おはよう";
origin.list.add(10);
//インスタンスのシャローコピー
DuplicateObject copy = origin;
copy.value = 2;
copy.source = "おやすみ";
copy.list.add(20);
//出力メソッド実行
origin.dump("コピー元");
copy.dump("コピー先");
}
}
出力結果
----[コピー元]----
value:2
source:おやすみ
list:[10, 20]
----[コピー先]----
value:2
source:おやすみ
list:[10, 20]
copyのフィールドを変更しただけですが、出力結果ではoriginのフィールドも変更されています。
これが同じ実体(データ)を参照しているということです。
ディープコピーとは、実体も含めてインスタンスをコピーする方法です。
参照先の実体も含めてコピーし新しいインスタンスを生成するので、
一方に変更を加えても、もう一方に影響を与えません。
ディープコピーを行うには、
cloneメソッドを利用した方法とシリアライズオブジェクトを使った方法の二通りの仕方があります。
次の項で確認していきましょう!
cloneメソッドはオブジェクト(インスタンス)のコピー(クローン)を作るメソッドとしてObjectクラスに実装されています。
protected Object clone()
Object.cloneの特徴
・protected修飾子が付いている
・戻り値がObject型である
・インスタンスをコピーする際はClonableインターフェイスを実装する必要がある
⇒Clonableインターフェイスは、マーカーインターフェイスであり、複製可能ということを表しています。
cloneメソッドを使ってディープコピーする場合は、対象のクラスでcloneメソッドが適切に実装されている必要があります。
cloneメソッドを使ったディープコピーのサンプルコードを確認しましょう。
サンプルコード
import java.util.ArrayList;
/*
* CloneableObjectクラス:説明用のためsetter/getter を省略
*/
class CloneableObject implements Cloneable {
public int value = 0;
public String source = "あいさつ";
public ArrayList<Integer> list = new ArrayList<>();
/*
* cloneメソッドの定義
* public修飾子、自分自身の型を返り値とする
* Objectクラスのcloneメソッドが、
* CloneNotSupportedExceptionを投げる可能性を考慮する
*/
public CloneableObject clone() throws CloneNotSupportedException {
CloneableObject o = (CloneableObject)super.clone();
/* "super.clone()"の戻り値はObject型なので継承クラスの型に変更
* ⇒(CloneableObject)を付ける!
*/
return o;
}
//出力メソッドの定義
public void dump(String name) {
System.out.println("----[" + name + "]----");
System.out.println("value:" + value);
System.out.println("source:" + source);
System.out.println("list:" + list.toString());
}
}
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
//インスタンスを生成
CloneableObject origin = new CloneableObject();
origin.value = 1;
origin.source = "おはよう";
origin.list.add(10);
//インスタンスのディープコピー
CloneableObject copy = origin.clone();
copy.value = 2;
copy.source = "おやすみ";
copy.list.add(20);
//出力メソッド実行
origin.dump("コピー元");
copy.dump("コピー先");
}
}
出力結果
----[コピー元]----
value:1
source:おはよう
list:[10, 20]
----[コピー先]----
value:2
source:おやすみ
list:[10, 20]
※listだけがシャローコピー
前項のcloneメソッドを使用したサンプルコードでの出力結果で、おかしいなと思ったところがあったと思います。
◆前項の出力結果
----[コピー元]----
value:1 source:おはよう list:[10, 20]
----[コピー先]----
value:2 source:おやすみ list:[10, 20]
前項の実装ではArrayList型(参照型)の変数がディープコピーされていません。
実はインスタンス元のクラスにcloneメソッドを定義しただけでは、
参照型変数はシャローコピーされてしまいます。
colonメソッドで参照型変数をディープコピーするには、個別実装が必要になります。
※プリミティブ型、イミュータブルオブジェクト(String,Number)は個別実装不要
インスタンス元クラスのcloneメソッド内に以下のような個別実装を行い、ディープコピーをします。
- 参照型変数それぞれにcloneメソッドを実装する
// cloneメソッドの定義
public CloneableObject clone() throws CloneNotSupportedException {
CloneableObject o = (CloneableObject)super.clone();
//個別実装
o.list = (ArrayList<Integer>)list.clone();
return o;
}
上記の個別実装を前項のサンプルコードに含めれば、参照型の変数もディープコピーすることができるようになります。
◆個別実装後の出力結果
----[コピー元]----
value:1
source:おはよう
list:[10]
----[コピー先]----
value:2
source:おやすみ
list:[10, 20]
シリアライズの概要については以下の記事で紹介しています。
シリアライズ化した後、オブジェクトを再定義することでディープコピーができます。
以下のサンプルコードでシリアライズ後に変更を加えたメンバ変数を確認してみましょう。
サンプルコード
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
class SerializeObject implements Serializable {
public int value = 0;
public String source = "あいさつ";
public ArrayList<Integer> list = new ArrayList<>();
//出力メソッドの定義
public void dump(String name) {
System.out.println("----[" + name + "]----");
System.out.println("value:" + value);
System.out.println("source:" + source);
System.out.println("list:" + list.toString());
}
}
public class Test {
public static void main(String[] args) throws Exception {
// シリアライズ対象クラスをインスタンス化
SerializeObject o1 = new SerializeObject();
o1.value = 1;
o1.source = "おはよう";
o1.list.add(10);
// ObjectOutputStream でシリアライズ
ByteArrayOutputStream stream= new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(stream);
out.writeObject(o1);
//ObjectInputStream でデシリアライズ
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(stream.toByteArray()));
//メンバ変数を変更
SerializeObject o2 = (SerializeObject) in.readObject();
o2.value = 2;
o2.source = "おやすみ";
o2.list.add(20);
//出力メソッド実行
o1.dump("シリアライズ実行前");
o2.dump("シリアライズ実行後");
}
}
出力結果
----[シリアライズ実行前]----
value:1
source:おはよう
list:[10]
----[シリアライズ実行後]----
value:2
source:おやすみ
list:[10, 20]
シリアライズ化することで、ディープコピーをすることが出来ました。
【著者】
読者を始め私自身も知りたい!と思うような知って得するプログラミング知識やIT情報を日々発信中です。
教養のあるカッコいい大人になれるよう、プログラミングを始め興味関心を持ったことを毎日勉強しております !!
そのような方はぜひ、Workteriaサイトをご利用ください!
定期的にご本人に合う高額案件を紹介
リモートワークなど自由な働き方ができる案件多数
専属エージェントが契約や請求をトータルサポート
こんにちは。エンジニアの新田です!ここでは、システムエンジニアとして働いている私が、システム開発手法や開発言語について紹介していこうと思います。今回は、JSPの標準タグライブラリ「JSTL」について紹介します。Javaについて勉強している方、Webアプリケーションを構築したいと思っている方の参考になれば幸いです!関連記事リンク: 【Java】JSPの基本的な構文/【Java】JSPのアクションタグ
こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!そもそもStringとは何?『 String 』... Java言語において文字列のデータ型を指します。基本デ
こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!Stringクラスformatメソッドの文字列整形【java.utilパッケージ】Formatterクラスfo
こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者にも✅、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!文字列を扱う3つのクラス【java.langパッケージ】java.langパッケージの文字列を扱うクラスにはS
こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!プリミティブ型と参照型プログラム開発では型を持った変数を使ってデータのやり取りをしますが、データ型によって仕様