- PR -

req.getParameters("パラメーター名")で取得した値の操作に関して

投稿者投稿内容
遊説家
会議室デビュー日: 2003/10/22
投稿数: 15
お住まい・勤務地: 奈良県
投稿日時: 2004-08-27 10:36
お世話になります(なりっぱなしです)
遊説家@奈良です。Tomcat5.0+J2EE1.3.1環境でサーブレットを作成しています。
皆様のお知恵をお借しください。
サーブレットでのパラメーター取得後のデータ操作なのですが、下記ソース中、
コメントA、B部分で同じパラメーターを別の変数に格納しているつもりです。(wk1,wk2)
サーブレットキックのHTMLソースはこれでやってみました
============================================================================
http://(サーバ名):8080/(サーブレット名)/servlet/svl001?_hoge="[7]123456"
============================================================================
その際、取得した値の1つを操作(下記例では、]文字以降を抽出) するともう一方の
値にも影響が出てしまいます。期待している動作は wk11は 123456 で wk12 は[7]123456
なのですが、いっしょになってしまいます。
まるで、wk1,wk2が同じポインターで操作されているような.....
何か根本的に間違っているのでしょうか?
皆様、お知恵を、何卒!お知恵を....

/*
* svl001.java
* Created on 2004/08/26
*/
import java.io.PrintWriter;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//
public class svl001 extends HttpServlet {
//
protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
this.doPost(req, res);
}
//
public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
//
res.setContentType("text/html; charset=Shift_JIS");
PrintWriter writer = res.getWriter();
//
writer.println("<html>");
// ヘッダー部
writer.println("<head>");
writer.println("<meta http-equiv=\\"Content-Type\\" content=\\"text/html; charset=iso-2022-jp\\">");
writer.println("<title>");
writer.println("Servlet Sample2");
writer.println("</title>");
writer.println("</head>");
// ボディー部
writer.println("<body><h1>");
writer.println("<center>");
//
String[] wk1 = null;
String[] wk2 = null;
// A
wk1 = req.getParameterValues("_hoge");
// B
wk2 = req.getParameterValues("_hoge");
//
// wk1だけ、']'よりあとの文字を抽出しているつもり
// この時点で、wk1,wk2 は内容が異なるはず。
wk1[0] = wk1[0].substring(wk1[0].lastIndexOf(']') + 1);
//
// 念のため、shift-jis に再変換
String wk11 = new String(wk1[0].getBytes("8859_1"), "Shift_JIS");
String wk12 = new String(wk2[0].getBytes("8859_1"), "Shift_JIS");
System.out.println("wk11>" + wk11);
System.out.println("wk12>" + wk12);
//
// wk11,wk12 は異なるはずなのにいっしょになってしまう....
writer.println("1度目の日本語[" + wk11 + "]");
writer.println("2度目の日本語[" + wk12 + "]");
writer.println("</center>");
writer.println("</h1></body>");
writer.println("<html>");
//
}
}
今川 美保(夏椰)
ぬし
会議室デビュー日: 2004/06/10
投稿数: 363
お住まい・勤務地: 神奈川県茅ヶ崎市
投稿日時: 2004-08-27 11:47
---------------------------------------------------------
コード:
// A 
wk1 = req.getParameterValues("_hoge"); 
// B 
wk2 = req.getParameterValues("_hoge"); 
// 


---------------------------------------------------------
この時点でwk1とwk2は同じString配列を指していますよね。

---------------------------------------------------------
コード:
wk1[0] = wk1[0].substring(wk1[0].lastIndexOf(']') + 1); 


---------------------------------------------------------
ここでwk1が指している配列の箱の0番目が参照している先を変えていますよね。
wk1とwk2は同じ配列を指しているんだから、wk2の0番目の参照先も変えたってことじゃないですか?
遊説家
会議室デビュー日: 2003/10/22
投稿数: 15
お住まい・勤務地: 奈良県
投稿日時: 2004-08-27 12:25
夏椰さんどうもありがとうございます
教えていただきたいのですが、ご指摘の内容は
public class test2 {
public static void main(String[] args) {
//
String[] wk1 = new String[1];
String[] wk2 = new String[1];
//
wk1[0] = "12345";
wk2[0] = wk1[0];
//
wk1[0] = wk1[0].substring(2);
System.out.println( wk1[0]);
System.out.println( wk2[0]);
}
}
で、結果が
345
12345
となることとは関係ないのでしょうか?
wk2[0] = wk1[0];
で、先の例の
wk1 = req.getParameters("hoge");
wk2 = req.getParameters("hoge");
と同じなのでは?って思ってしまいましたが、なんか私の大歩危があるのでしょうね

今川 美保(夏椰)
ぬし
会議室デビュー日: 2004/06/10
投稿数: 363
お住まい・勤務地: 神奈川県茅ヶ崎市
投稿日時: 2004-08-27 12:33
説明不足でしたね。すみません。

2つ目のソースでは
String[] wk1 = new String[1];
String[] wk2 = new String[1];
と記述されていてwk1とwk2は別々の配列を見ています。

1つ目のソースでは
wk1 = req.getParameterValues("_hoge");
wk2 = req.getParameterValues("_hoge");
と記述されていてwk1とwk2は同じ配列を見ています。

だから動作に違いがでているんですよ。
H2
ぬし
会議室デビュー日: 2001/09/06
投稿数: 586
お住まい・勤務地: 港
投稿日時: 2004-08-27 12:42
コード:

wk1 = req.getParameterValues("_hoge");
wk2 = req.getParameterValues("_hoge");


この時点で、wk1とwk2は同じString配列オブジェクトへの参照を持っています。これはおそらく、getParameterValuesメソッドが内部に持っている配列の参照を渡すからだと思います。(JavaDocにはそういうことは書いてなかった)

なお、下記のコードで、wk1とwk2が同じ参照をもっていて、さらにwk1の中身を変えるとreq.getParameterValues("_hoge"); が返す値が変わることが分かります。
コード:

wk1 = req.getParameterValues("_hoge");
wk2 = req.getParameterValues("_hoge");
System.out.println("wk1 == wk2 " + (wk1==wk2)); //trueならばwk1とwk2は同じ参照をしている
System.out.println("Wk1 " + wk1 + " " + w1[0]);
System.out.println("Wk2 " + wk2 + " " + w2[0]);
wk1[0] = "Changed"; //wk1はreqの中の配列の内容を変えた。
String[] w = req.getParameterValues("_hoge");
System.out.println("W " + w + " " + w[0]); // w[0]は"Changed"になっている。



なお、
String[] wk1 = new String[1];
String[] wk2 = new String[1];
とすると、wk1とwk2にそれぞれ別の配列オブジェクトを生成するため wk1!=wk2 となります。つまり、wk1を変えても、wk2は変わりません。


[ メッセージ編集済み 編集者: H2 編集日時 2004-08-27 12:46 ]
ちょま吉
大ベテラン
会議室デビュー日: 2004/08/04
投稿数: 112
投稿日時: 2004-08-27 13:05
Javaを使う上で知っておいてもらいたいのは、
「基本的にJavaはオブジェクト参照だ」ということです。

intやbooleanのようなプリミティブ型、それからString、その他にもあるかもしれませんが、これら以外のオブジェクトはオブジェクト参照です。
(Stringについては、特別です。)

ですので、Stringの配列はオブジェクト参照で、値を変えることによってもう一方に影響します。
しかし、単にStringの値を変更した場合は、オブジェクト参照ではありませんので、他方には影響ありません。
# String[]とStringでは、値の参照の仕方が違います。

説明で間違っていたらご指摘ください。

[ メッセージ編集済み 編集者: ちょま吉 編集日時 2004-08-27 13:07 ]
MINE
会議室デビュー日: 2003/07/02
投稿数: 17
投稿日時: 2004-08-27 13:51
どうも MINEです。
プリミティブ以外はオブジェクトへの参照ですよね
Stringはデータの変更が許されていないから
一方を変更することで他方も変わってしまうという
ことは起こりませんけど
遊説家
会議室デビュー日: 2003/10/22
投稿数: 15
お住まい・勤務地: 奈良県
投稿日時: 2004-08-27 14:09
H2殿、ちょま吉殿、夏椰殿ありがとうございました

>ちょま吉殿
=================================================
# String[]とStringでは、値の参照の仕方が違います
=================================================
自分なりに、値渡しか、ポインタ渡しの違いと理解するようにします。
 違います?
 ともかく、ありがとうございました、です。

>H2殿
 =============================================================================
 getParameterValuesメソッドが内部に持っている配列の参照を渡すからだと思います
=============================================================================
  ポインタがwk1,wk2で共通になっているとの予想はあったのですが、なんか仕様上
 へんな感じがしますね。
 ありがとうございました。
  配列の参照を渡されては困るので、結局、getParameters("_hoge") で
 String で受け取った値の操作をするようにしました。
 このソースではないのですが本番のものも問題が解決しました。
   
/*
* svl001.java
* Created on 2001/06/28, 14:03
*/
import java.io.PrintWriter;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//
public class svl001 extends HttpServlet {
//
protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
this.doPost(req, res);
}
//
public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
//
res.setContentType("text/html; charset=Shift_JIS");
PrintWriter writer = res.getWriter();
//
writer.println("<html>");
// ヘッダー部
writer.println("<head>");
writer.println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-2022-jp\">");
writer.println("<title>");
writer.println("Servlet Sample2");
writer.println("</title>");
writer.println("</head>");
// ボディー部
writer.println("<body><h1>");
writer.println("<center>");
//
// String[]を止めて、String にしました
String wk1 = null;
String wk2 = null;
// Sgtringを返却する getParameter("_hoge")にしました
wk1 = req.getParameter("_hoge");
wk2 = req.getParameter("_hoge");
//
// wk1だけ、']'よりあとの文字を抽出しているつもり
// この時点で、wk1,wk2 は内容が異なるはず。
// → 異なるようになりました
wk1 = wk1.substring(wk1.lastIndexOf(']') + 1);
//
// 念のため、shift-jis に再変換
String wk11 = new String(wk1.getBytes("8859_1"), "Shift_JIS");
String wk12 = new String(wk2.getBytes("8859_1"), "Shift_JIS");
System.out.println("wk11>" + wk11);
System.out.println("wk12>" + wk12);
//
// wk11,wk12 は異なるはずなのにいっしょになってしまう....
// →異なるようになりました
writer.println("1度目の日本語[" + wk11 + "]");
writer.println("2度目の日本語[" + wk12 + "]");
writer.println("</center>");
writer.println("</h1></body>");
writer.println("<html>");
//
}
}

 

スキルアップ/キャリアアップ(JOB@IT)