メソッドのオーバーロード

以下のように、Javaでは同名のメソッドを同一クラス内で定義できる。

public class HelloWorld
{
    private static String plus(int x, int y)
    {
        String result = Integer.toString(x + y);
        return "合計は「" + result + "」です";
    }
    private static String plus(String str1, String str2)
    {
        return "文字列をつなげると「" + str1 + str2 + "」です";
    }
    public static void main(String[] args)
    {
        System.out.println(plus(3, 5));
        System.out.println(plus("Hello, ", "World"));
    }
}
/*
合計は「8」です
文字列をつなげると「Hello, World」です
*/

上述のように引数の型の異なったメソッドが存在する場合は、各々が別のメソッドとして処理される。但し、同名で引数の型も数も全く同じメソッドはオーバーロードできない。

Javaの演算子

■文字列の結合

以下のようにして文字列を結合することができる。

public class HelloWorld
{
    public static void main(String[] args)
    {
        System.out.println("Hello" + "World" + "!");
    }
}
// HelloWorld!

意外だが以下のように、数値を文字列として結合することもできる。

public class HelloWorld
{
    public static void main(String[] args)
    {
        System.out.println("Hello " + 1192 + " World" + "!");
    }
}
// Hello 1192 World!

その他の演算子は他のプログラミング言語と大体同じだから適宜まとめることにする。

Javaの配列

■宣言

以下のようにして配列を宣言することができる。

public class HelloWorld
{
    public static void main(String[] args)
    {
        int ary[] = new int[3];
        ary[0] = 3;
        ary[1] = 1;
        ary[2] = 4;
        for(int i = 0; i < ary.length; i++){
            System.out.println(Integer.toString(ary[i]));
        }
    }
}

上述では、長さ3のint型の配列が生成されている。また、lengthプロパティに配列の長さが格納されている。

文字列の場合

以下のように、上述と全く変わらない。

public class HelloWorld
{
    public static void main(String[] args)
    {
        String ary[] = new String[3];
        ary[0] = "hoge";
        ary[1] = "fuga";
        ary[2] = "piyo";
        for(int i = 0; i < ary.length; i++){
            System.out.println(ary[i]);
        }
    }
}

二次元配列

以下のようにして二次元配列を生成することができる。

public class HelloWorld
{
    public static void main(String[] args)
    {
        String ary[][] = new String[2][2];
        ary[0][0] = "hoge";
        ary[0][1] = "fuga";
        ary[1][0] = "piyo";
        ary[1][1] = "baca";
        for(int i = 0; i < ary.length; i++){
            for(int i2 = 0; i2 < ary[i].length; i2++){
                System.out.println(ary[i][i2]);
            }
        }
    }
}

ちなみに以下のように配列はクローンが作られるわけではないので注意すること!

public class HelloWorld
{
    private static String[][] convert(String ary[][])
    {
        for(int i = 0; i < ary.length; i++){
            for(int i2 = 0; i2 < ary[i].length; i2++){
                if(ary[i][i2] == "hoge"){
                    ary[i][i2] = "aho";
                }
            }
        }
        return ary;
    }
    
    public static void main(String[] args)
    {
        String ary[][] = new String[2][2];
        ary[0][0] = "hoge";
        ary[0][1] = "fuga";
        ary[1][0] = "piyo";
        ary[1][1] = "baca";
        String ary1[][] = convert(ary);
        for(int i = 0; i < ary.length; i++){
            for(int i2 = 0; i2 < ary[i].length; i2++){
                System.out.println(ary[i][i2]);
            }
        }
        for(int i = 0; i < ary1.length; i++){
            for(int i2 = 0; i2 < ary1[i].length; i2++){
                System.out.println(ary1[i][i2]);
            }
        }
    }
}
/*
aho
fuga
piyo
baca
aho
fuga
piyo
baca
*/

Javaの変数

■宣言

Javaでは変数を使用する前に、以下のように型を指定して宣言する必要がある。

public class HelloWorld
{
    public static void main(String[] args)
    {
        String greeting = "Hello World";
        System.out.println(greeting);
        greeting = 1;// error
    }
}

上述のように、指定した型以外の型の値を代入することはできない。

また、以下のように何も入っていない変数を使用することはできない。

public class HelloWorld
{
    public static void main(String[] args)
    {
        String greeting;
        System.out.println(greeting);// error
    }
}

■スコープ

Javaにはブロックスコープが存在する。従って以下のように{}で区切られた箇所にスコープが生成される。

public class HelloWorld
{
    public static void main(String[] args)
    {
        {
            String greeting1 = "Hello World";
            {
                String greeting2 = "Hello World";
            }
            System.out.println(greeting1);
            System.out.println(greeting2);// error
            System.out.println(greeting3);// error
            String greeting3 = "Hello World";
        }
        System.out.println(greeting3);// error
    }
}

■型変換

以下のように、Javaでは型変換することができる。

public class HelloWorld
{
    public static void main(String[] args)
    {
        double pi = 3.1415;// double型で宣言
        int x = (int) pi;// double型をint型に変換...(a)
        String number = Integer.toString(x);// int型をString型に変換
        System.out.println(number);
    }
}

上述(a)を見るとPHPと同様であるように思える。しかし、以下のようにする事はできない。

public class HelloWorld
{
    public static void main(String[] args)
    {
        int x = (int)"1192";// error
        System.out.println(x);
    }
}

以下のようにすることで、上述の操作を達成することができる。

public class HelloWorld
{
    public static void main(String[] args)
    {
        int x = Integer.parseInt("1192");
        System.out.println(x);
    }
}

■定数

以下のように、finalを使用して定数を宣言することができる。

public class HelloWorld
{
    private static final String GREETING = "Hello World";
    public static void main(String[] args)
    {
        System.out.println(GREETING);
    }
}

定数なので当然、代入はできない。

public class HelloWorld
{
    private static final String GREETING = "Hello World";
    public static void main(String[] args)
    {
        GREETING = "";// error
        System.out.println(GREETING);
    }
}

■列挙型

public class HelloWorld
{
    enum Week {
        Monday,
        Tuesday,
        Wednesday,
        Thursday,
        Friday,
        Saturday,
        Sunday,
    }
    public static void main(String[] args)
    {
        System.out.println(Week.Monday);// Monday
    }
}

MySQLとかであるようなやつだね。

Javaの基本

■Hello World

なんだかんだでHello Worldからまとめてみる。

public class HelloWorld
{
    /**
     * @param args
     */
    public static void main(String[] args)
    {
        System.out.println("Hello World");
    }
}

■コメント

コメントは以下の2種類が存在する。#はコメントとして扱われない。

public class HelloWorld
{
    public static void main(String[] args)
    {
        // this is a comment
        /* this is a comment */
        System.out.println("Hello World");
    }
}

■文末

セミコロンが必須である。PHPに近くてJavaScriptやPythonとは違う。

public class HelloWorld
{
    public static void main(String[] args)
    {
        System.out.println("Hello World");// OK
        System.out.println("Hello World")// NG
    }
}

■命名規則

以下のように関数名やクラス名に日本語を使用することができる。

public class HelloWorld
{
    public static void main(String[] args)
    {
        System.out.println(げっと文字列());
    }
    
    private static String げっと文字列()
    {
        return "Hello World";
    }
}

はっきり言ってダサいし見づらいので日本語は使用しないこと。

  • アルファベット、数字、アンダースコア、$を使用できるが、数字で始めることはできない。
  • 長さに制限はない
  • 大文字と小文字は区別される。

Cookieを使って別サイトの閲覧履歴を取る

自社サイトを訪れたユーザが他サイトAを訪れたか調べたい。他サイトAに対してビーコンを貼れることを条件に、これが可能となる。

■他サイト側(http://sample.jp/index.html)

imgタグでビーコンを貼り付けてあげれば良い。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>ドキュメント</title>
</head>
<body>
<p><img src="http://sample.org/spacer.php" width="1" height="1" /></p>
</body>
</html>

■自社(サイト)ドメイン側実装

他サイトに貼り付けたビーコンを準備してあげる。

ビーコン用のイメージ(http://sample.org/spacer.php)

クッキーをセットしたいのでphpで書く。

<?php
header('Content-Type: image/gif');
setcookie('sample', 'see');
print(file_get_contents('spacer.gif'));

検証ページ(http://sample.org/index.php)

このページを訪問したユーザが、他サイトAを訪問したか調べられる。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>検証ページ</title>
</head>
<body>
<?php
if($_COOKIE['sample'] === 'see'){
    print('<p>you have already seen http://sample.jp</p>');
}
else{
    print('<p>Nice to meet you!</p>');
}
?>
</body>
</html>

基本的にはユーザの行動収集はこの原理で行う。iframeとJavaScriptを使用することで、さらに多くの情報を取得することができる。

eclipseでJSP・Servletの開発環境を構築する

■ダウンロード

eclipse

Eclipse DownloadsからEclipse IDE for Java EE Developersを選択しダウンロードする。

日本語化については、以前の記事を参考にセットアップする。

サーバー

Apache+MySQLについてはxamppをインストールして使用する。

但し、MySQLにはJavaから接続することになるので、以前の記事を参考にしてMySQL用JDBCドライバをインストールする。

xamppのアドオンのTomcatについて

eclipseとの連携で失敗するので、xamppのアドオン版のTomcatは使用しないこと。

JRE

eclipseの実行に必要になるので、ダウンロードしてインストールする。

JDK

Java SE Development Kit 6u23をダウンロードし、インストールする。

インストールすると環境変数の設定が必要になる。Windows 7の場合、「スタート > コントロールパネル > システム > システムの詳細設定 > 詳細設定 > 環境変数」で、「システム環境変数」の変数Pathに「;C:\Program Files\Java\jdk1.6.0_23\bin」とJDKがインストールされたパスを追記する。

■設定

「ウィンドウ > 設定」をクリックする。

文字コード

「一般 > ワークスペース > テキスト・ファイルのエンコード」で「その他 > UTF-8」を選択する。

さらに、「Web > JSPファイル > エンコード」で「UTF-8」を選択する。

Tomcat

「サーバー > ランタイム環境 > 追加」で、「Tomcat6」を追加し「次に」をクリックした後、「ダウンロードしてインストール」をクリックし、「C:\tomcat6」にインストールする。インストールが終わったら、以下のように入力する。

名前
Apache Tomcat v6.0
Tomcatインストール・ディレクトリ
C:\tomcat6

Shadowboxでショートカットキーを使えなくする

Shadowboxでは「x」や「w」のキーを押すとウィンドが閉じる。しかし、入力欄などがShadowbox内に存在していた場合、この挙動が不具合を生じさせる。そこで以下のようにenableKeysオプションをfalseにする。

Shadowbox.init({
    "language" : 'ja',
    "players"  : ['img', 'html', 'iframe', 'qt', 'wmp', 'swf', 'flv'],
    "enableKeys" : false
});

tinyMCEはjQueryのcloneで複製できない

jQueryのtinyMCEプラグインを使用する。

■cloneメソッド

そっくりそのままコピーができるが、コピーされたtinyMCEは機能しないはずだ。この不具合は、tinyMCEをsortable要素にした時にも生じる。恐らく、tinyMCEが内部的にiframeを使用していることに起因するのではないだろうか。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>無題ドキュメント</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.js"></script>
<script type="text/javascript" src="tiny_mce/tiny_mce.js"></script>
<script type="text/javascript" src="tiny_mce/jquery.tinymce.js"></script>
<script type="text/javascript">
$(function(){
	$('textarea.tinymce').tinymce({
		theme : "advanced",
		plugins : "safari,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template",
		theme_advanced_buttons1 : "save,newdocument,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,styleselect,formatselect,fontselect,fontsizeselect",
		theme_advanced_buttons2 : "cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,insertdate,inserttime,preview,|,forecolor,backcolor",
		theme_advanced_buttons3 : "tablecontrols,|,hr,removeformat,visualaid,|,sub,sup,|,charmap,emotions,iespell,media,advhr,|,print,|,ltr,rtl,|,fullscreen",
		theme_advanced_toolbar_location   : "top",
		theme_advanced_toolbar_align      : "left",
		theme_advanced_statusbar_location : "bottom",
		theme_advanced_resizing : true,
		init_instance_callback : function(){
			var clone = $('div.parts').clone(true);
			$('div.parts').after(clone);
		}
	});
});
</script>
</head>
<body>
<div class="parts">
<form method="post" action="">
<textarea class="tinymce" name="" rows="15" cols="60"></textarea>
</form>
</div>
</body>
</html>

■解決策

document.createElementでtextareaから生成したtextareaに対して、tinymce()する。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>無題ドキュメント</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.js"></script>
<script type="text/javascript" src="tiny_mce/tiny_mce.js"></script>
<script type="text/javascript" src="tiny_mce/jquery.tinymce.js"></script>
<script type="text/javascript">
$(function(){
	$('textarea.tinymce').tinymce({
		theme : "advanced",
		plugins : "safari,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template",
		theme_advanced_buttons1 : "save,newdocument,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,styleselect,formatselect,fontselect,fontsizeselect",
		theme_advanced_buttons2 : "cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,insertdate,inserttime,preview,|,forecolor,backcolor",
		theme_advanced_buttons3 : "tablecontrols,|,hr,removeformat,visualaid,|,sub,sup,|,charmap,emotions,iespell,media,advhr,|,print,|,ltr,rtl,|,fullscreen",
		theme_advanced_toolbar_location   : "top",
		theme_advanced_toolbar_align      : "left",
		theme_advanced_statusbar_location : "bottom",
		theme_advanced_resizing : true,
		init_instance_callback : function(){
			var div      = document.createElement('div');
			var form     = document.createElement('form');
			var textarea = document.createElement('textarea');
			$(div).attr('class', 'parts');
			$(div).append(form);
			$(form).append(textarea);
			$(textarea).attr('class', 'tinymce');
			$(textarea).attr('rows', '15');
			$(textarea).attr('cols', '60');
			$('div.parts:last').append(div);
			$(textarea).tinymce({
				theme : "advanced",
				plugins : "safari,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template",
				theme_advanced_buttons1 : "save,newdocument,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,styleselect,formatselect,fontselect,fontsizeselect",
				theme_advanced_buttons2 : "cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,insertdate,inserttime,preview,|,forecolor,backcolor",
				theme_advanced_buttons3 : "tablecontrols,|,hr,removeformat,visualaid,|,sub,sup,|,charmap,emotions,iespell,media,advhr,|,print,|,ltr,rtl,|,fullscreen",
				theme_advanced_toolbar_location   : "top",
				theme_advanced_toolbar_align      : "left",
				theme_advanced_statusbar_location : "bottom",
				theme_advanced_resizing : true
			});
		}
	});
});
</script>
</head>
<body>
<div class="parts">
<form method="post" action="">
<textarea class="tinymce" name="" rows="15" cols="60"></textarea>
</form>
</div>
</body>
</html>

しっかり機能するtinyMCEが生成されるはずだ。

init_instance_callback

エディタが完成するとコールされる。tinymce()から完成までは時間がかかり、気をつけなくてはいけないのは、その間にscript処理が止まらない。従って、完成した(直後の)エディタに対してscriptからアクセスする場合は、init_instance_callbackを使用する必要がある。

Yahooひらがな変換API

ドキュメントの文字コードはutf-8である。

<?php
$str = urlencode('庭には二羽鶏がいる。');
$url = "http://jlp.yahooapis.jp/FuriganaService/V1/furigana?appid=<apikey>&sentence={$str}";
$xml = new SimpleXmlElement($url, null, true);
var_dump($xml);
/*
object(SimpleXMLElement)#1 (1) {
  ["Result"]=>
  object(SimpleXMLElement)#2 (1) {
    ["WordList"]=>
    object(SimpleXMLElement)#3 (1) {
      ["Word"]=>
      array(8) {
        [0]=>
        object(SimpleXMLElement)#4 (3) {
          ["Surface"]=>
          string(3) "庭"
          ["Furigana"]=>
          string(6) "にわ"
          ["Roman"]=>
          string(4) "niwa"
        }
        [1]=>
        object(SimpleXMLElement)#5 (3) {
          ["Surface"]=>
          string(3) "に"
          ["Furigana"]=>
          string(3) "に"
          ["Roman"]=>
          string(2) "ni"
        }
        [2]=>
        object(SimpleXMLElement)#6 (3) {
          ["Surface"]=>
          string(3) "は"
          ["Furigana"]=>
          string(3) "は"
          ["Roman"]=>
          string(2) "ha"
        }
        [3]=>
        object(SimpleXMLElement)#7 (3) {
          ["Surface"]=>
          string(6) "二羽"
          ["Furigana"]=>
          string(6) "にわ"
          ["Roman"]=>
          string(4) "niwa"
        }
        [4]=>
        object(SimpleXMLElement)#8 (3) {
          ["Surface"]=>
          string(3) "鶏"
          ["Furigana"]=>
          string(12) "にわとり"
          ["Roman"]=>
          string(8) "niwatori"
        }
        [5]=>
        object(SimpleXMLElement)#9 (3) {
          ["Surface"]=>
          string(3) "が"
          ["Furigana"]=>
          string(3) "が"
          ["Roman"]=>
          string(2) "ga"
        }
        [6]=>
        object(SimpleXMLElement)#10 (3) {
          ["Surface"]=>
          string(6) "いる"
          ["Furigana"]=>
          string(6) "いる"
          ["Roman"]=>
          string(3) "iru"
        }
        [7]=>
        object(SimpleXMLElement)#11 (1) {
          ["Surface"]=>
          string(3) "。"
        }
      }
    }
  }
}
*/
foreach($xml->Result->WordList->Word as $word){
    print($word->Furigana);
}
//にわにはにわにわとりがいる

文字コードがshift-jisの場合は以下のようになる。

$str = urlencode(mb_convert_encoding('庭には二羽鶏がいる。', 'utf-8', 'sjis'));
$url = "http://jlp.yahooapis.jp/FuriganaService/V1/furigana?appid=<apikey>&sentence={$str}";
$xml = new SimpleXmlElement($url, null, true);
foreach($xml->Result->WordList->Word as $word){
    print($word->Furigana);
}

API