javaまとめ
メッセージのUS化
- 日本語だとコンパイルエラーメッセージが化けるので
-Duser.language=en
メモリー・リークの予防
http://www.ibm.com/developerworks/jp/java/library/j-leaks/ メモリー・リークは、いくつかの一般的な問題に注意することにより防ぐことができます。 しばしばメモリー・リークの原因となるのは、ハッシュ・テーブルやベクトルなどのコレクション・クラスです。 そのクラスが static と宣言されていて、アプリケーションの存続期間全体にわたって存在する場合、その可能性が特に大きくなります。 よくある別の問題は、あるクラスをイベント・リスナーとして登録しておきながら、そのクラスがもう使用されなくなった時点で登録削除するのを忘れている場合です。 また、クラスのメンバー変数が別のクラスを指す場合、適当なタイミングでその変数をヌルにセットする必要があります。
自作CRUDアプリ
createメソッド実装時に下記の例外でハマる
java.lang.reflect.InvocationTargetException
commons-configurationではまる。
JavaDB
javaDBのスタンドアロン版では、ijを起動中、サーブレットアプリからアクセスできないので注意。
connect 'jdbc:derby:c:\Temp\dbname;create=true';
create table articles (
id integer primary key generated by default as identity,
title varchar(256),
body long varchar,
updated_at timestamp
);
insert into articles values (default, 'title1', 'body1', current_timestamp);
tomcat
context.xml
<Context reloadable="true">
<Resurce name="jdbc/crud" auth="container" type="javax.sql.DataSource"
driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
url="jdbc:derby:c:\Temp\dbname"/>
</Context>
web.xml
<resource-ref>
<res-ref-name>jdbc/crud</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
Servlet
private DataSource ds;
@Override
public void init() throws ServletException {
try {
ds = (DataSource) (new InitialContext()).lookup("java:comp/env/jdbc/crud");
} catch (NamingException e) {
throw new ServletException(e);
}
}
Connection conn = ds.getConnection();
Statement stmt = conn.createStatement();
String sql = "SELECT title, body FROM articles ORDER BY updated_at DESC";
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
String title = rs.getString("title");
String body = rs.getString("body");
}
JSTL
http://tomcat.apache.org/taglibs/index.html
Version | JSTL version | Requirements | Tomcat |
Standard 1.2 | JSTL 1.2 (not yet JCP approved) | Servlet 2.5, JavaServer Pages 2.1 | |
Standard 1.1 | JSTL 1.1 | Servlet 2.4, JavaServer Pages 2.0 | Tomcat 5.x(JSP 2.0) |
Standard 1.0 | JSTL 1.0 | Servlet 2.3, JavaServer Pages 1.2 | Tomcat 4.x(JSP 1.2) |
タグライブラリ
タグハンドラ形式 | Jsp1.1から |
タグファイル形式 | Jsp 2.0から |
Resin
Resin3.0 | JavaServlet2.4 | Jsp2.0 | JSTL 1.01 | |
Resin3.1 | JavaServlet2.5 | Jsp2.1 | JSTL 1.01 | |
Resin4.0 | JavaServlet3.0 | Jsp2.2 | JSTL 1.2 | EL1.2 |
jsp-configは、jsp2.0から使用できる。
.tagファイルでは、pageContextではなく、jspContextでアクセスする。 jspContextは、JSP2.0から導入されている模様
外部プロセス起動
1.4まではRuntimeクラスだったが、1.5以降はProcessBuilderを使用する。
/**
* ファイルのグループと属性を変更する。
*/
private void changGroup(String file)
{
ProcessBuilder pb = new ProcessBuilder();
try {
pb.command("chgrp", "-R", "hoge", file);
Process p = pb.start();
} catch (Exception ex) {
Logger.error("can't execute chgrp:"+file);
}
try {
pb.command("chmod", "-R", "664", file);
Process p = pb.start();
} catch (Exception ex) {
Logger.error("can't execute chmod:"+file);
}
}
タグファイルについて
tagディレクティブ
タグファイルでは、pageディレティブの代わりに tagディレクティブを使用する。
<%@ tag
language="java"
pageEncoding="UTF-8"
body-content="scriptless"
%><%@ attribute name="href"
%><%@ attribute name="id"
%>perfect.java
javaのクラスをインポートする場合
<%@ tag
language="java"
pageEncoding="UTF-8"
body-content="scriptless"
import="java.util.Map"
%><%@ attribute name="href"
%><%@ attribute name="id"
%>perfect.java
pageディレクティブと同様に複数指定することもできる。
<%@ tag
language="java"
pageEncoding="UTF-8"
body-content="scriptless"
import="java.util.Map"
import="java.util.List"
%><%@ attribute name="href"
%><%@ attribute name="id"
%>perfect.java
body-content属性
tagディレクティブにある body-content
属性の意味は下記のとおり
body-contentは、タグを利用したときの本体部分のことである。
<hoge>本体</hoge>
scriptless
タグ本体に、スクリプト式、スクリプトレットを使用できない。
<%-- 下記はng --%>
<hoge>
<%= test %>
<% out.print("test"); %>
</hoge>
<%-- 下記はok --%>
<hoge>
${test}
test
</hoge>
empty
タグ本体そのものを記述できない
<%-- 下記はNG --%>
<hoge>test</hoge>
<%-- 下記はok --%>
<hoge></hoge>
<hoge />
tagdependet
よくわかってない。
多分、本体で記述した内容は 評価されずにそのまま表示される?
<hoge>${1 + 1}</hoge>
<%-- 下記のように評価されず表示される --%>
<hoge>${1 + 1}</hoge>
スクリプティング要素は使用できない。
動的属性
動的属性を指定すると、属性の定義を省略できる。 属性の種類が多い場合に有効。 たとえば、a.tagというオリジナルのタグを用意し、 以下のようにアクセスした場合、
jsp側
//hoge.jsp
<my:a href="hoge.com" />hoge</my:a>
属性がMap形式で格納されるで、以下のようにアクセスできる。
// a.tag
<%@ tag pageEncoding="UTF-8"
body-content="scriptless"
dynamic-attributes="attrs"
%>
<a href="${attrs.href}"><jsp:doBody/></a>
jspと改行について
jspは、= %> = が出現するとそこに「改行」が入ってしまうので注意が必要である。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="pj" tagdir="/WEB-INF/tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
test
</body>
</html>
この場合、 = %> = が3回登場しているので「改行」も3回入る。
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
test
</body>
</html>
これを回避するには、下記のように = %> = を行頭に置き、 かつ次行を繋げることである。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"
%><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"
%><%@ taglib prefix="pj" tagdir="/WEB-INF/tags"
%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
test
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
test
</body>
</html>
java5以降で環境変数の取得
こんな感じ System.getenv().get("LANG");
javaの拡張for文
map
Mapの場合、Map#keySet()でkeyだけ、Map#values()でvalueだけ、 は簡単に取れるけど拡張for文(for-each)でループさせてkey/valueのペアを取得する方法。
for(Map.Entry<String, String> e : map.entrySet()) { System.out.println(e.getKey() + " : " + e.getValue()); }
なるほど、Map.Entryというinterfaceが定義されてて、そのSetが返ってくるんですな。
コレクション(List, Set)を配列化する。
Collection#toArray
配列の中身を表示する。
java.util.Arrays.deepToString(array)
テキストファイルの読込
public String loadData(String filename) {
BufferedReader br = null;
StringBuilder out = new StringBuilder();
try{
InputStream is = getClass().getClassLoader().getResourceAsStream(filename);
br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
String buf = null;
while((buf = br.readLine()) != null){
out.append(buf.trim());
}
} catch (IOException e){
e.printStackTrace();
} finally {
try {
if (br == null) br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return out.toString();
}
日付書式文字列
当日の日付を(YYYY/MM/DD)で取得したいとき。
String today = String.format("%1$tY/%1$tm/%1$td", new Date());
もしくは
Date date = new Date();
String today = String.format("%tY/$tm/$td", date, date, date);
この場合「%1$,3d」が書式になる。 %1$tY
- %は書式の開始を示す。
- 1$は引数のインデックスを示す。ひとつの引数を使い回すときなどに必要。今回の場合はひとつなので無くても良い。
- tは日付変換を指定する。
- t以降の文字は、APIマニュアル参照(Ymd)
Thread
wait,notify,notifyAll
ウェイトセット
- インスタンスごとに用意されているスレッドの待合室
javaの継承時のアクセス制御
パッケージプライベートなアクセスクラスでインターフェイスを使いたい
- インタフェイスを使っているが、パッケージプライベートなので
実装クラスの各メソッドのアクセスもパッケージプライベートにしたいという要件
-
まずクラスのアクセス指定子とクラスメンバーの指定子は別物らしい(パーフェクトJava:P143)
- publicとパッケージプライベートの2種類しかない
-
継承時のクラスはスーパクラスにあるメッソドよりアクセス指定子のスコープを広めることはできても緩めることはできない。
- これはコンパイルの挙動で確認。言語仕様などの裏どりはとれていない。
- インタフェイスはpublicしか指定できないので、上記の仕様により常にパブリックメソッドになる。
現時点でわかってないのは、クラスのアクセススコープがパッケージプライベートのときに メソッドをパブリックにしたときの実質的なアクセススコープはどうなるかということ。