Download presentation
Presentation is loading. Please wait.
1
J2SE 5.0(Tiger)の新機能 言語編 Ariel Networks 開発部 中山 淳
2
J2SE 5.0(Tiger)の新機能 より単純に、より安全に Generics 拡張for文 Autoboxing
Static import 可変長引数 Enumerations Annotation
3
Generics 型安全なプログラミング
4
所々でtype-castが必要になるため、 型に関して安全とは言えない
今までのJava List list = new ArrayList(); list.add(new Integer(0)); Integer i0 = (Integer)list.get(0); // type-castが必要 list.add(new Long(0)); Integer i1 = (Integer)list.get(1); // ClassCastExceptionが発生 所々でtype-castが必要になるため、 型に関して安全とは言えない
5
compilerが型を知っているのでtype-castが不要になる
Tigerなら List<Integer> list = new ArrayList<Integer>(); // 新しい構文 list.add(new Integer(0)); Integer i = list.get(0); // type-castが不要 list.add(new Long(0)); // Integerしか入れられないので、compile error! compilerが型を知っているのでtype-castが不要になる
6
compilerに型を教える新構文 List<Integer> list = new ArrayList<Integer>(); Genericsをサポートしているclass/interfaceに対して 「型名<型パラメータ>」の形で使う ArrayList<Integer>は、Integer型の要素からなるArrayList型 (class) Map<String, Date>は、String型のkeyとDate型のvalueからなるMap型 (interface) Set<Map<String, Date>>は、String型のkeyとDate型のvalueからなるMapのSet
7
自分でGenericなclass/interfaceを書くこともできる
例えば、任意の型の変数の組を 保持するclass Pairを書いてみる
8
今までのJava class Pair { private Object first; private Object second;
public Pair(Object first, Object second) { this.first = first; this.second = second; } public Object getFirst() {return first;} public Object getSecond() {return second;} public static void main() { Pair pair = new Pair("now", new Date()); String key = (String)pair.getFirst() Date value = (Date)pair.getSecond()
9
Tiger class Pair<F, S> { private F first; private S second;
public Pair(F first, S second) { this.first = first; this.second = second; } public F getFirst() {return first;} public S getSecond() {return second;} public static void main() { Pair<String, Date> pair = new Pair<String, Date>("now", new Date()); String key = pair.getFirst() Date value = pair.getSecond()
10
Genericsで何が嬉しいか 実行時エラー(ClassCastException)が減る コードの見通しがよくなる
IDE(Eclipse等)による自動補完の精度が上がる
11
Genericsの原理 型パラメータはコンパイル時にのみ使われ、byte codeには残らない
Pair<String, Date> pair = new Pair<String, Date>("now", new Date()); String key = pair.getFirst() Date value = pair.getSecond() は、次のコードと等価になるよう、コンパイルされる。 Pair pair = new Pair("now", new Date()); String key = (String)pair.getFirst() Date value = (Date)pair.getSecond() コンパイル時のtype-checkによって、type-castの正しさが 保証されるところがミソ。
12
既存のコードとの相互運用性 原理から分かるように、型パラメータを取るclass/interfaceは
void foo(List list) {/* etc. */} void bar(Pair pair) {/* etc. */} Genericsを使ったコード void baz() { List<Integer> list = new ArrayList<Integer>(); foo(list); // 正しいコード (warningは出る) Pair<String, Date> pair = new Pair<String, Date>("now", new Date()); bar(pair); // Pair<F, S>はPair classとしてコンパイルされるので、これも可 }
13
Genericsの制限 1. 型パラメータに組込型を指定できない
List<int>と書くことはできない (List<Integer>は可) 2. 型パラメータで指定された型をnewできない (配列も含む) public S getSecond() {return new S();} や public S[] getSecond() {return new S[1];}は不可 3. byte codeになったときにmethodの型が同じになるようなmethodは記述できない void set(F first) と void set(Object o) を同じclass/interfaceに書くのは不可 4. 型パラメータをstatic memberに適用できない static List<F> commons = new List<F>(); といった記述はできない
14
オブジェクトを列挙するforループを同一の構文で書ける
15
今までのJava int[] intArray = new int[]{4004, 8008, 8080, 80, 6502, 6809};
for (int i = 0; i < intArray.length; i++) { int elem = intArray[i]; } List<Integer> intList = new ArrayList<Integer>(); // etc. for (Iterator i = intList.iterator(); i.hashNext(); ) { Integer elem = i.next();
16
Tiger int[] intArray = new int[]{4004, 8008, 8080, 80, 6502, 6809};
for (int elem : intArray) { } List<Integer> intList = new ArrayList<Integer>(); // etc. for (Integer elem : intList) {
17
拡張for文に渡せるコンテナ 配列 java.lang.Iterableをimplementsしたclassのオブジェクト (Java.util.Collection等)
18
拡張for文の実装 byte codeには、普通のfor文と同じようにコンパイルされる
for (int elem : intArray) { } は、 for (int #i = 0; i < intArray.length; #i++) { int elem = intArray[#i]; とコンパイルされる Iterableなものに関しても、同じようにiteratorを変数として コンパイルされる
19
int等の基本型とInteger等の wrapper型の自動変換を行い、 記述を単純にする
Autoboxing/unboxing int等の基本型とInteger等の wrapper型の自動変換を行い、 記述を単純にする
20
Autoboxing/unboxingを使わないと
void handleInt(int i); void handleInteger(Integer i); List<Integer> list = new ArrayList<Integer>(); list.add(new Integer(1)); // Integer objectを生成 handleInteger(new Integer(1)); int i = list.get(0).intValue(); // Integer objectを取り出して、intValue() methodを呼び出す handleInt(list.get(0).intValue());
21
Autoboxing/unboxingを使うと
void handleInt(int i); void handleInteger(Integer i); List<Integer> list = new ArrayList<Integer>(); list.add(1); // 自動的にInteger objectを生成 (boxing) handleInt(list.get(0)); // method呼び出しにも適用できる int i = list.get(0); // Integer objectを取り出して、自動的に // intValue() methodを呼び出す (unboxing) handleInteger(1); // method呼び出しにも適用できる
22
class/interfaceのstaticメンバを 直接importする
23
1.4までのJavaでは、import できるのはパッケージだけ
class/interfaceのstaticメンバを参照するときは、TypeName.MemberNameの形式で記述する必要があった
24
import java.util.Arrays; Arrays.sort(fooArray);
25
Tiger import static java.util.Arrays.sort; sort(fooArray);
// static importによってArraysを // 省略できる
26
定数interface idiomからの脱却
今までは、interfaceにstatic finalで定数を書き、それをimplementsすることで定数を手軽に使えるようにする手法がよく使われていた static importによって不要に
27
今までのJava package foo; public interface Barable {
static final int BarConstant = 0; } public Bar implements foo.Barable { public static void main() { System.out.println(BarConstant);
28
Tiger package foo; public class BarUtil {
public static final int BarConstant = 0; } import static foo.BarUtil.*; public Bar { public static void main() { System.out.println(BarConstant);
29
可変長引数 printf()が使えるようになった
30
使用例 System.out.printf("%d = %s", 256, "0x100");
宣言 System.out.printf(String formt, Object ... args); 使用例 System.out.printf("%d = %s", 256, "0x100");
31
可変長引数を取るmethodの例 void foo(Object ... vargs) { for (Object o : vargs) {
System.out.println(o.toString()); } static void main() { foo(1, "abc", new Date()); foo("abc", new Date(), "def", 89);
32
可変長引数の実装 void foo(Object ... vargs) は、byte code上は
→ 1. foo(new Object[]{1, “abc”, new Date()}) と foo(1, “abc”, new Date())は同じbyte codeになる 2. void foo(Object ... vargs) と void foo(Object[] vargs) のoverloadingはできない
33
配列を可変長引数methodの 一引数として渡すには?
引数の型(foo()の場合はObject)にtype-castする foo("this array ", (Object)(new Object[]{1, "abc", new Date()}), "is one of parameters");
34
C/C++でおなじみの列挙型 型安全な定数を手軽に使えるように なった (type safe enum idiomが不要に)
Enumerations C/C++でおなじみの列挙型 型安全な定数を手軽に使えるように なった (type safe enum idiomが不要に)
35
今までのJava package foo; public class DayOfWeek {
static final int SUNDAY = 0; static final int MONDAY = 1; /* 略 */ static final int SATURDAY = 6; } void foo(int dayOfWeek) { switch (dayOfWeek) { case DayOfWeek.SUNDAY: /* 略 */ break; case DayOfWeek.MONDAY: default: assert false; }
36
Tiger public enum DayOfWeek { SUNDAY = 0, MONDAY = 1, /* 略 */
SATURDAY = 6, } void bar(DayOfWeek dayOfWeek) { if (dayOfWeek == DayOfWeek.SUNDAY) { // 通常の記法 void foo(DayOfWeek dayOfWeek) { switch (dayOfWeek) { case SUNDAY:// switch文の特例 /* 略 */ break; case SUNDAY: default: assert false; }
37
enumの実装 定義 byte code public enum DayOfWeek {
SUNDAY, MONDAY, /* 略 */ , SATURDAY, } byte code public final class DayOfWeek extends java.lang.Enum { public static final DayOfWeek SUNDAY = new DayOfWeek(); public static final DayOfWeek MONDAY = new DayOfWeek(); /* 略 */ public static final DayOfWeek SATURDAY = new DayOfWeek(); public static final DayOfWeek[] values(); public static final DayOfWeek valueOf(String name); static {
38
enum定数のinstanceは一つであることが保証されている (==演算子や!=演算子で比較できる)
→ そのためにいくつかの制限が発生 enum型にfinalやabstractといった宣言を行えない enum型のinstanceをnewで生成できない Reflection APIを使ってenum型のinstanceを 生成できない
39
便利なmethod String name() enum定数の名前を文字列で得る
static T Enum.valueOf(String name) 文字列で渡された名前をenum定数に変換する static T[] Enum.values() enum定数を列挙する
40
コードの動的な振る舞いに 影響しないmeta dataを付加する
Annotation コードの動的な振る舞いに 影響しないmeta dataを付加する
41
標準のannotation @Override methodに対して付与し、そのmethodがsuper classのmethodをoverrideしていることを宣言する 現状の実装ではjavacが処理を行い、overrideされていないケースで警告を出す public void foo(String name) { /* 略 */} @Deprecated method/classに対して付与し、そのmethod/classが非推奨であることを宣言する 現状の実装ではjavacが処理を行い、deprecatedされたmethodが使用された箇所で警告を出す public void bar(String name) { /* 略 */}
42
独自annotationの使用例 Spring Framework 2.0 代表的なDI(Dependence Injection) コンテナ 2.0ではannotationでbeanを定義できる JUnit 4 単体テストのフレームワーク テストメソッドの指定などにannotationを使用できる Aspect J 1.5.x JavaでAOP(Aspect Oriented Programming)を行うための言語 無設定Struts Annotationと命名規約によって、Strutsの定義ファイルを不要にする
43
J2SE1.4のJVMでTigerの機能を使うには
今までの説明から分かるとおり、Tigerのbyte codeは1.4とほぼ同じ しかし、Tigerのclassファイルは1.4では実行できない → WebSphere 6.0 (1.4ベース) で困る
44
Tigerのclassファイルを1.4で実行できる形式に変換するツールがある
Retroweaver Retrotranslator ArielではRetrotranslatorを使って実際に運用しているが、今まで問題が出たことはない
Similar presentations
© 2024 slidesplayer.net Inc.
All rights reserved.