Java:リフレクションの使い方

Javaのリフレクションは、実行時に、文字列(変数名や関数名)を通して、変数の読み書きや関数の呼び出しを行うための機能です。

 

arithmetics.java

class Arithmetics {
  public String attribute;
  public double add(double x, double y) {
    return x + y;
  }
}
 

 

main.java

import java.lang.reflect.Field;
import java.lang.reflect.Method;

class Main {
  public static void main(String... args) {
    try {
      String stringClass = "Arithmetics";
      String stringField = "attribute";
      String stringMethod = "add";

      Class<?> clazz = Class.forName(stringClass);
      Object object = clazz.newInstance();

      Field field = clazz.getField(stringField);
      field.set(object, "Hello!");
      System.out.println(field.get(object));

      Method method = clazz.getMethod(stringMethod, double.class, double.class);
      System.out.println(method.invoke(object, 1, 1));
    }
    catch (ReflectiveOperationException e) {
      e.printStackTrace();
    }
  }
}
 



〈実行結果〉

Hello!
2.0


Javaのリフレクションを使うとアノテーション情報を取得することもできます。

 

InfoAnnotation.java

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
public @interface InfoAnnotation {
  String info() default "";
}
 

 

arithmetics.java

class Arithmetics {
  @InfoAnnotation(info = "field")
  public String attribute;

  @InfoAnnotation(info = "method")
  public double add(double x, double y) {
    return x + y;
  }
}
 

 

main.java

import java.lang.reflect.Field;
import java.lang.reflect.Method;

class Main {
  public static void main(String... args) {
    try {
      Field field = Arithmetics.class.getField("attribute");
      InfoAnnotation fieldAnnotation = field.getAnnotation(InfoAnnotation.class);
      System.out.println(fieldAnnotation.info());

      Method method = Arithmetics.class.getMethod("add", double.class, double.class);
      InfoAnnotation methodAnnotation = method.getAnnotation(InfoAnnotation.class);
      System.out.println(methodAnnotation.info());
    }
    catch (ReflectiveOperationException e) {
      e.printStackTrace();
    }
  }
}
 



〈実行結果〉

field
method


参考サイト

 

Java:JARライブラリの作成と使用

1.JARライブラリの作成

 

D:\jar\pkg1\pkg2\pkg3\Arithmetics.java

package pkg1.pkg2.pkg3;

public class Arithmetics {
  public static double add(double x, double y) {
    return x + y;
  }
}
 

 

〈フォルダpkg1の中にあるファイルを全てアーカイブする場合〉

D:\jar\jar0.bat(ファイル名をjar.batにすると暴走します)

set JAVA_HOME=D:\sdk\jdk
set path=%path%;%JAVA_HOME%\bin
javac pkg1/pkg2/pkg3/*.java
jar cfv hoge.jar pkg1

 

〈フォルダpkg1/pkg2/pkg3の中にあるclassファイルを全てアーカイブする場合〉

D:\jar\jar1.bat(ファイル名をjar.batにすると暴走します)

set JAVA_HOME=D:\sdk\jdk
set path=%path%;%JAVA_HOME%\bin
javac pkg1/pkg2/pkg3/*.java
jar cfv hoge.jar pkg1/pkg2/pkg3/*.class


2.JARライブラリの使用

 

D:\src\main.java

import pkg1.pkg2.pkg3.Arithmetics;

class Main {
  public static void main(String... args) {
    System.out.println(Arithmetics.add(1, 1));
  }
}
 

 

Mainクラスのコンパイル

D:\src\javac0.bat(ファイル名をjavac.batにすると暴走します)

set JAVA_HOME=D:\sdk\jdk
set path=%path%;%JAVA_HOME%\bin
javac -cp .;D:\jar\hoge.jar main.java

 

Mainクラスの実行

D:\src\java0.bat(ファイル名をjava.batにすると暴走します)

set JAVA_HOME=D:\sdk\jdk
set path=%path%;%JAVA_HOME%\bin
java -cp .;D:\jar\hoge.jar Main
pause


参考サイト

 

C++:vectorを使った多次元配列の動的確保

下記の vector.cpp は、std::vector を使って多次元配列を動的に確保するためのプログラムです。

 

vector.cpp

#include <iostream>
#include <vector>
using namespace std;

void showVectorSize(vector<double>& v1) {
  cout << v1.size() << endl;
}

void showVectorSize(vector<vector<double>>& v2) {
  cout << v2.size() << "," << v2.front().size() << endl;
}

void showVectorSize(vector<vector<vector<double>>>& v3) {
  cout << v3.size() << "," << v3.front().size() << "," << v3.front().front().size() << endl;
}

int main() {
  int n1 = 10;
  int n2 = 20;
  int n3 = 30;

  vector<double> v1;
  v1 = vector<double>(n1, 0);
  cout << v1[1] << endl;
  showVectorSize(v1);

  vector<vector<double>> v2;
  v2 = vector<vector<double>>(n1, vector<double>(n2, 0));
  cout << v2[1][2] << endl;
  showVectorSize(v2);

  vector<vector<vector<double>>> v3;
  v3 = vector<vector<vector<double>>>(n1, vector<vector<double>>(n2, vector<double>(n3, 0)));
  cout << v3[1][2][3] << endl;
  showVectorSize(v3);
}
 

 

注)コンパイルする時は、オプション -std=c++11 を付けて下さい。付けない場合は、入れ子になったテンプレート引数において、
  vector<vector<double> >
のように、>> の間に空白を入れる必要があります。


g++ -std=c++11 -O2 vector.cpp -o vector.exe


参考サイト

 

AjaxとServletの連携

AjaxServlet を連携するやり方について紹介します。サーブレットコンテナは Jetty を用いています。

注)Jetty は、サーブレットコンテナとして機能だけではなく、 Webサーバの機能も備えています。


ファイルの配置

まず、Jetty のzipファイルをダウンロードし、適当な場所(ここでは D:\sdk)で解凍します。 次に webappsフォルダの直下に好きな名前のフォルダ(ここでは webapp)を作成し、更にその下にWEB-INFフォルダを作成し、その中に web.xml を入れて下さい。

  D:\sdk\jetty\webapps\webapp\SampleAjax.htm
  D:\sdk\jetty\webapps\webapp\WEB-INF\web.xml
  D:\sdk\jetty\webapps\webapp\WEB-INF\classes\SampleServlet.class

注)web.xml、SampleAjax.htm は、UTF-8 で保存してください!


 

D:\sdk\jetty\webapps\webapp\WEB-INF\web.xml

<web-app>
  <servlet>
    <servlet-name>sampleservlet</servlet-name>
    <servlet-class>SampleServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>sampleservlet</servlet-name>
    <url-pattern>sampleservlet</url-pattern>
  </servlet-mapping>
</web-app>
 

注)SampleServlet1.class、SampleServlet2.class のように、サーブレットが複数ある場合は、<web-app>・・・</web-app>の中に複数記述してください。


1.Ajaxのみのサンプル(Servletなし)

 

D:\sdk\jetty\webapps\webapp\SampleAjax.htm

<html>
<body>

<form name="io">
  <input type="button" value="実行" onClick="get()">
  <textarea id="output" cols="50" rows="5"></textarea>
</form>

<script>
function get() {
  xhr = new XMLHttpRequest();
  xhr.onload = setResponseText;
  xhr.open("GET", "/webapp/hello.txt", true);
  xhr.send();
}
</script>

<script>
function setResponseText() {
  document.getElementById("output").innerHTML = xhr.responseText;
}
</script>

</body>
</html>
 

 

D:\sdk\jetty\webapps\webapp\hello.txt

Hello Ajax!
Hello Ajax!
Hello Ajax!
Hello Ajax!
Hello Ajax!
 

2.AjaxServletを使ったサンプル(XMLHttpRequest版)

 

D:\sdk\jetty\webapps\webapp\SampleAjax.htm

<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Ajax</title>
</head>
<body>

<form name="io">
  <input type="button" name="execute" value="実行">
  <input type="text" name="input1">
  <input type="text" name="input2">
  <input type="text" name="input3">
  <output name="output"></output>
</form>

<script>
document.io.execute.addEventListener("click", function () {
  var url = "/webapp/sampleservlet";
  var value1 = document.io.input1.value;
  var value2 = document.io.input2.value;
  var value3 = document.io.input3.value;
  var request = "input1" + "=" + value1 + "&" + "input2" + "=" + value2 + "&" + "input3" + "=" + value3;
  var callback = function (response) {document.io.output.innerHTML = response["key1"] + "," + response["key2"] + "," + response["key3"];};
  $post(url, request, callback);
});
</script>

<script>
function $post(url, request, callback) {
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function () {
    if (this.readyState == 4 && this.status == 200) {
      callback(JSON.parse(this.responseText));
    }
  };
  xhr.open("post", url, true);
  xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  xhr.send(request);
}
</script>

</body>
</html>
 

3.AjaxServletを使ったサンプル(jQuery版)

 

D:\sdk\jetty\webapps\webapp\SampleAjax.htm

<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Ajax</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-3.3.1.min.js"></script>
</head>
<body>

<form>
  <input type="button" id="execute" value="実行">
  <input type="text" id="input1">
  <input type="text" id="input2">
  <input type="text" id="input3">
  <output id="output"></output>
</form>

<script>
$("#execute").on("click", function () {
  var url = "/webapp/sampleservlet";
  var request = {};
  request["input1"] = $("#input1").val();
  request["input2"] = $("#input2").val();
  request["input3"] = $("#input3").val();
  var callback = function (response) {$("#output").text(response["key1"] + "," + response["key2"] + "," + response["key3"]);};
  $.post(url, request, callback);
});
</script>

</body>
</html>
 

4.Servletのサンプル(共通)

上記のXMLHttpRequest版及びjQuery版に共通のServletサンプルです。
尚、SampleServlet.java において、サーブレットからクライアントに送信するデータ形式(setContentType)を application/json にしています。

 

D:\sdk\jetty\webapps\webapp\WEB-INF\src\SampleServlet.java

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;

public class SampleServlet extends HttpServlet {
  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
    response.setContentType("application/json");
    String parameter1 = request.getParameter("input1");
    String parameter2 = request.getParameter("input2");
    String parameter3 = request.getParameter("input3");
    PrintWriter out = response.getWriter();
    out.println("{" + "\"key1\"" + ":" + "\"" + parameter1 + "\"" + "," + "\"key2\"" + ":" + "\"" + parameter2 + "\"" + "," + "\"key3\"" + ":" + "\"" + parameter3 + "\"" + "}");
  }
}
 

 

Servletコンパイル方法

下記のバッチファイルをダブルクリックして SampleServlet.javaコンパイルします。

javac0.bat(ファイル名をjavac.batにすると暴走します)

set JAVA_HOME=D:\sdk\jdk
set path=%JAVA_HOME%\bin
javac -cp D:\sdk\jetty\lib\servlet-api-3.1.jar *.java
pause
 


コンパイルしたファイル(SampleServlet.class)を下記のフォルダに入れてください。

D:\sdk\jetty\webapps\webapp\WEB-INF\classes

 


Webサーバの起動方法

下記のバッチファイルをダブルクリックすると Jetty が起動します。

jetty.bat

set JAVA_HOME=D:\sdk\jdk
set path=%JAVA_HOME%\bin
cd /d D:\sdk\jetty
java -jar start.jar


Webサーバへのアクセス方法

WebブラウザのURLに以下のように入力すれば、Webサーバにアクセスすることができます。


http://localhost:8080/webapp/SampleAjax.htm


参考サイト