slide1 n.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
Reflection & Generics in JDK1.5 PowerPoint Presentation
Download Presentation
Reflection & Generics in JDK1.5

Loading in 2 Seconds...

play fullscreen
1 / 63

Reflection & Generics in JDK1.5 - PowerPoint PPT Presentation


  • 110 Views
  • Uploaded on

Reflection & Generics in JDK1.5. 侯捷 / J.J. Hou 資訊教育 / 專欄執筆 / 大學教師 jjhou@jjhou.com, http://www.jjhou.com. Generics. 講題提要. Generics. 自JDK1.3起, Generics 技術以各種 外掛 方式進入Java。JDK1.5正式 內建 此一技術,對 Java 及其 Library 帶來全面的影響與改寫。本講題追蹤該技術全面進入 JDK1.5 的狀況。. Reflection. 講題提要. Reflection.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Reflection & Generics in JDK1.5' - karma


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
slide1

Reflection & Generics in JDK1.5

侯捷 / J.J. Hou資訊教育 / 專欄執筆 / 大學教師jjhou@jjhou.com, http://www.jjhou.com

generics

Generics

講題提要.Generics

自JDK1.3起,Generics技術以各種外掛方式進入Java。JDK1.5正式內建此一技術,對 Java 及其 Library 帶來全面的影響與改寫。本講題追蹤該技術全面進入 JDK1.5 的狀況。

reflection

Reflection

講題提要.Reflection

Reflection 為 Java 帶入靜態語言難以企及的動態應用,廣為人知者便是Component-based programming(例如Javabean)開發環境, deSerialization,以及RMI(Remote Method Invocation)。本講題說明 Reflection 基本觀念及 APIs 運用。

homogenous heterogenous

Generics

同質(homogenous)容器與異質(heterogenous) 容器

同質容器:元素型別必須相同。

C++ STL 的容器都是同質容器。

list<int> myList;myList.push_back(3);

異質容器:元素型別可以不同。

Java Collections 都是異質容器。

LinkedList myList = new LinkedList();

myList.add(new Double(4.4));myList.add(new String("jjhou"));

編譯器建立 int版-list

元素型別是Object

in java

Generics

同質容器 in Java

Java 借鑑 C++ 語彙符號 "< >",建立同質容器,是謂 Generics in Java:

LinkedList<Integer> myList =

new LinkedList<Integer>();

myList.add(new Integer(4));myList.add(new Integer(7));

myList.add(new String("hello")); //Error!

polymorphism

Generics

同質容器與多型(Polymorphism)應用

Java Collections 原就充份運用多型:

相當於LinkedList

LinkedList<Object> myList

= new LinkedList<Object>();

Object

5

11

55

Stroke

Rect

Circle

18

22

66

2b

w:Integeria:ArrayList <Integer>

l:Integert:Integerw:Integerh:Integer

x:Integery:Integerr:Integer

33

77

Circle

18

44

2c

Rect

18

2c

Stroke

polymorphism1

Generics

同質容器與多型(Polymorphism)應用

為更好地運用多型,可這麼寫:

LinkedList<Shape> myList

= new LinkedList<Shape>();

Object

Shape

5

11

55

18

22

66

2b

33

77

Circle

Stroke

Rect

Circle

18

44

2c

w:Integeria:ArrayList <Integer>

l:Integert:Integerw:Integerh:Integer

x:Integery:Integerr:Integer

Rect

18

2c

Stroke

g enerics

Generics

加入 Generics 之前

Java 為保持語言的簡單性,強迫程式員在使用 Collections 時必須記住所擁有的元素型別;取出元素並進一步處理前,必須先轉型,從 Object轉為實際型別。

LinkedList myList = new LinkedList();

myList.add(new Integer(0));

myList.add(new Integer(1));

Integer tempi = (Integer)myList.iterator().next();

g enerics1

Generics

加入 Generics 之後

如果以generic types擴充 Java 語言,就能以更直接的方式表現 collection 的相關資訊,於是編譯器可追蹤記錄實際的元素型別,您也就不再需要轉型。有助於程式的開發與除錯。

LinkedList<Integer> iList = new LinkedList<Integer>();

iList.add(new Integer(0));

iList.add(new Integer(1));

Integer tempi = iList.iterator().next();

java c

Generics

Java/C++泛型技術的根本差異

C++

list

class list; // int版本

.exe

template <typename T,...>

class list { ... };

class list; // string版本

膨脹法

class list; // double版本

#include <list>

list<int> li;

list<string> ls;

list<double> ld;

list<int> li;

list<string> ls;

list<double> ld;

Java

java.util.LinkedList.java

public class LinkedList<E>

{ ... };

public class LinkedList

{ ... };

.class

擦拭法

import java.util.*

LinkedList<Integer> ...;

LinkedList<String> ...;

LinkedList<Double> ...;

import java.util.*

LinkedList ...;

LinkedList ...;

LinkedList ...;

.class

g enerics java

Generics

Generics Java技術發展歷程

GJ安裝後的路徑

  • JDK1.3 + GJ(a Generic Java language extension)以預處理器(%GJClasses%\gjc.Main)+翻新的Collections(%GJClasses%\*.class)提供GP。
  • JDK1.4+JSR14(Adding Generics to Java Language)以編譯器套件(%JSR14DISTR%\javac.jar)+翻新的Collections(%JSR14DISTR%\collect.jar)提供GP。
  • JDK1.5內建所有必要的GP服務。Java Library全面翻新。

JSR14安裝後的路徑

java g enerics

Generics

學習與觀察Java Generics
  • 運用Generic Classes

例如 java.util (collections)

  • 運用Generic Algorithms (methods)

例如 methods in java.util.Collection

  • 撰寫Generic Classes
  • 撰寫Generic Algorithms (methods)
jdk1 5 g eneric classes algorithms

Generics

在JDK1.5中運用Generic Classes/Algorithms

ArrayList<String> strList =

new ArrayList<String>();

strList.add("zero");

strList.add("one");

strList.add("two");

strList.add("five");

System.out.println(strList);

// [zero, one, two, five]

String str = Collections.max(strList);

Collections.sort(strList);

static methods

boxing unboxing

Generics

Boxing & UnBoxing 的影響

容器元素必須是 object(不可為純數值)

LinkedList<Integer> iList =

new LinkedList<Integer>();

iList.add(new Integer(0));

iList.add(new Integer(1));

iList.add(new Integer(5));

iList.add(new Integer(2));

LinkedList<Integer> iList =

new LinkedList<Integer>();

iList.add(0); //boxing

iList.add(1);

iList.add(5);

iList.add(2);

int i = iList.get(2); //un-boxing

jdk1 5 java util map

Generics

觀摩 JDK1.5, java.util.Map

public interface Map<K,V> {

V get(Object key);

V put(K key, V value);

V remove(Object key);

void putAll(Map<? extends K, ? extends V> t);

interface Entry<K,V> { … }

...

}

jdk1 4 java util map

Generics

觀摩 JDK1.4, java.util.Map

public interface Map {

Object get(Object key);

Object put(Object key, Object value);

Object remove(Object key);

void putAll(Map t);

interface Entry { … }

...

}

jdk1 5 java util arraylist

Generics

觀摩 JDK1.5, java.util.ArrayList

public class ArrayList<E>

extends AbstractList<E>

implements List<E>, RandomAccess, Cloneable,

java.io.Serializable

{

private transient E[] elementData;

private int size;

public ArrayList(Collection<? extends E> c) {

size = c.size();

// Allow 10% room for growth

elementData = (E[])new Object[

(int)Math.min((size*110L)/100,

Integer.MAX_VALUE)];

c.toArray(elementData);

}

...

jdk1 4 java util arraylist

Generics

觀摩 JDK1.4, java.util.ArrayList

public class ArrayList

extends AbstractList

implements List, RandomAccess, Cloneable,

java.io.Serializable

{

private transient Object elementData[];

private int size;

public ArrayList(Collection c) {

size = c.size();

// Allow 10% room for growth

elementData = new Object[

(int)Math.min((size*110L)/100,

Integer.MAX_VALUE)];

c.toArray(elementData);

}

...

jdk1 5 g eneric classes

Generics

在JDK1.5中撰寫Generic Classes

LinkedList<Shape> sList = new LinkedList<Shape>();

sList.add(new Stroke<Integer,Integer>(…));

sList.add(new Rect<Integer>(…));

sList.add(new Circle<Integer>(…));

Object

LinkedList<Shape> sList

= new LinkedList<Shape>();

Shape

draw() len() compareTo()

5

11

55

18

22

66

2b

W,T

T

T

33

77

Circle<Integer>

Stroke

Rect

Circle

18

44

2c

w:T a:ArrayList<T>

l:T t:T w:T h:T

x:T y:T r:T

Rect<Integer>

18

2c

Stroke<Integer,Integer>

jdk1 5 g eneric classes1

Generics

在JDK1.5中撰寫Generic Classes

類似設計是 public final class Integer

extends Number implements Comparable<Integer>

為了可用於 max()

public abstract class Shape implements Comparable<Shape>{

public abstract void draw();

public abstract double len();

public int compareTo(Shape o) {

return (this.len() < o.len() ?

-1 : (this.len() == o.len() ? 0 : 1));

}

}

典型的Template Method

只要class名稱加上 <>

即成為 generic class

public class Stroke<W,T>

extends Shape

implements Serializable {

W width;

ArrayList<T> a;

public double len() { ... }

public void draw() { ... }

}

實際計算長度時,

恐怕會遭遇麻煩 !

jdk1 5 g eneric classes2

Generics

在 JDK1.5 中撰寫 Generic Classes

只要class名稱之後加上 <>,即成為 generic class

類似的設計是 Class<T>

public class Rect<T>

extends Shape

implements Serializable {

T l,t,w,h;

public void draw() { ... }

public double len() { ... }

}

public class Circle<T>

extends Shape

implements Serializable {

T x,y,r;

public double len() { ... }

public void draw() { ... }

}

實際計算長度時,

恐怕會遭遇麻煩 !

jdk1 5 g eneric algorithms

Generics

在 JDK1.5 中撰寫 Generic Algorithms

只要method名稱之前加上 <>,

即成為 generic method

形式 (1)

// in someone class

public static <T>

TgMethod (List<T> list) { ... }

"bounded type parameter"

"受到更多約束" 的型別參數

public static <T extends Comparable<T>>

TgMethod (List<T> list) { ... }

形式 (2)

JDK 1.5允許「不被method真正用到」

的型別參數以符號 '?' 表示

public static List<?>gMethod (List<?> list)

{

return list; // (本例)原封不動地傳回

}

形式 (3)

jdk1 4 java util collections max

Generics

觀摩 JDK1.4, java.util.Collections.max()

#001 public class Collections {

#002 ...

#003 public static

#004 //這裡刻意空一行,以利與JDK1.5源碼比較

#005 Objectmax(Collection coll) {

#006 Iterator i = coll.iterator();

#007 Comparable candidate = (Comparable)(i.next());

#008

#009 while(i.hasNext()) {

#010 Comparable next = (Comparable)(i.next());

#011 if (next.compareTo(candidate) > 0)

#012 candidate = next;

#013 }

#014 return candidate;

#015 }

#016 ...

#017 } // of Collections

jdk1 5 java util collections max

Generics

觀摩 JDK1.5, java.util.Collections.max()

#001 public class Collections {

#002 ...

#003 public static

#004 <T extends Object & Comparable<? super T>>

#005 Tmax(Collection<? extends T> coll) {

#006 Iterator<? extends T> i = coll.iterator();

#007 T candidate = i.next();

#008

#009 while(i.hasNext()) {

#010 T next = i.next();

#011 if (next.compareTo(candidate) > 0)

#012 candidate = next;

#013 }

#014 return candidate;

#015 }

#016 ...

#017 } // of Collections

jdk1 5 java util collections max1

Generics

觀摩 JDK1.5, java.util.Collections.max()

3

4

5

6

1

2

1. max() 將接收一個 Collection object

2. 該 Collection object 所含元素必須是 T-derived object

3. T 必須繼承自Object(這倒不必明說。Java必定如此)

4. T 必須實作 Comparable

5. Comparable 所比較的型別必須是 supertype of T

6. max() 傳回 T object

i ntrospection

Reflection

所謂 Introspection (內省, 內觀, 反省)

看透("look inside")classes 的能力,我們稱之為 introspection。或說 "the ability of the program to examine itself"

Java有兩個作法可以進行 introspection:

(1) Static Introspection : .class file inspection

(2) Dynamic Introspection : Reflection API

reflection1

Reflection

所謂 Reflection

Reflection 是 Java 被視為動態(或準動態)語言的關鍵,允許程式於執行期透過 Reflection APIs 取得任何已知名稱之 class的內部資訊,包括 package、type parameters、superclass、implementedinterfaces、inner classes, outer class, fields、constructors、methods、modifiers,並可於執行期生成instances、變更 fields 內容或喚起 methods。

reflection2

Reflection

所謂 Reflection

對於每一個class,JRE都會維護一個對應的不可改動的(immutable)Class object,其中內含該class資訊. Reflection APIs 便是從中取得資訊

virtual machine environment

dynamic loading

by class loader (a ClassLoader object)

Test class definition(Class object for Testclass)

Test.class

disk

reflection api s

Reflection

Reflection APIs

有了Reflection API,我們可以:

  • 決定(判斷)某個 object 所屬的 class.
  • 取得 class 的 modifiers, fields, methods, constructors, 和 superclasses 的相關資訊.
  • 找出 interface 中的constants 和 method declarations.
  • 為一個執行期才得知名稱的 class 產生實體(物件).
  • 取得及設定 object's field 值, 即使執行前對它一無所知.
  • 喚起(invoke)object'method,即使執行期才得知它.
  • 產生一個新的 array, 其大小和元素型別 (component type) 在執行之前未知。並可更動 array 的元素.
reflection api s1

Reflection

Reflection APIs

Core Reflection API 容納兩類應用。第一類應用需要找出並使用某個 object 的 run-time class 的所有public members。這些應用要求能夠於執行期存取該 object 的所有 public fields, methods, constructors。例如 Java Beans 提供的 services,以及 lightweight tools 如 object inspectors。這些應用程式統是使用 Class所提供的 methods: getField, getMethod, getConstructor, getFields, getMethods, getConstructors來獲得 classes Field, Method, Constructor的 instances。

第二類應用很精巧,需要找出並使用被某個 class 宣告的 members。它們需要能夠於執行期存取「由 class file 供應之 class 實作層級」。例如 development tools 如 interpreters, inspectors, 以及 class browsers, 以及 run-time services 如 Java Object Serialization。這些應用使用 Class所提供的 methods: getDeclaredField, getDeclaredMethod, getDeclaredConstructor, getDeclaredFields, getDeclaredMethods, getDeclaredConstructors來獲得 classes Field, Method, Constructor的 instances。

reflection api s2

Reflection

Reflection APIs

Reflection API 由java.lang.Class和 java.lang.reflect classes: (1)Field,(2)Method,(3)Constructor,(4)Array, (5)Modifier組成。前三者表現 classes /interfaces 的相應 (corresponding) 成員。Array提供 methods 用來建立, 存取, 改動 arrays。Modifier提供 methods 對 modifiers (如 static, public) 解碼(解釋)。

o bject class

Reflection

Object class

java.lang.Object

java.lang.Class

Object class 是所有 Java classes 的 root。

public class Object {

public final nativeClass<? extends Object>getClass();

public native int hashCode();

public boolean equals(Object obj) {

return (this == obj);

}

protected native Object clone() throws CloneNotSupportedException;

public String toString() {

return getClass().getName() + "@" + Integer.toHexString(hashCode());

}

public final native void notify();

public final native void notifyAll();

public final native void wait(long timeout) throws InterruptedException;

public final void wait(long timeout, int nanos) throws InterruptedException;

public final void wait() throws InterruptedException;

protected void finalize() throws Throwable { }

}

class class

Reflection

Class class

java.lang.Object

java.lang.Class

Class instance 所表現的,是執行中的 Java 程式內的 classes 和 interfaces。enum, annotation, array, primitive Java types (boolean, byte, char, short, int, long, float, double), 以及關鍵字 void 也都可被表現為 Class objects.

Class並沒有public constructor,其 objects 係當 classes 被載入或 class loader 的 defineClass() 被呼叫時,由 Java Virtual Machine 自動建構。

以下使用 Class object 列印某個 object 的 class 名稱:

void printClassName(Object obj) {

System.out.println("The class of " + obj + " is " + obj.getClass().getName());

}

也可對已知型別(或 void),根據其 class literal 取得 Class object,例如:

System.out.println("The name of class Foo is: "+Foo.class.getName());

class class1

Reflection

Class class

Class並沒有public constructor。其 objects 係當 classes 被載入 (loadClass(...))或 class loader 的 defineClass(...) 被呼叫時,由 Java Virtual Machine 自動建構。因此,我可以(修改源碼後)測得某個 class 被載入,卻無法測得其對應之 Class object 的誕生。

public final

class Class<T> implements java.io.Serializable,

java.lang.reflect.GenericDeclaration,

java.lang.reflect.Type,

java.lang.reflect.AnnotatedElement {

private Class() {}

...

public String toString() {

return ( isInterface() ? "interface " :

(isPrimitive() ? "" : "class "))

+ getName();

}

class class2

Reflection

Class class

獲得 java.lang.Class objects 的各種辦法

From getClass().

String str = "abc";

Class c1 = str.getClass();

From the method Class.getSuperclass()

Button b = new Button();

Class c1 = b.getClass();

Class c2 = c1.getSuperclass();

BTW getSuperclass() returns null for the class Object.

From the static method Class.forName()

Class c1 = Class.forName ("java.lang.String");

Class c2 = Class.forName ("java.awt.Button");

Class c3 = Class.forName

("java.util.LinkedList$Entry");

Class c4 = Class.forName ("I");

Class c5 = Class.forName ("[I");

From the .class syntax

Class c1 = String.class;

Class c2 = java.awt.Button.class;

Class c3 = Main.InnerClass.class;

Class c4 = int.class;

Class c5 = int[].class;

From the primitive wrapper classes

Class c1 = Boolean.TYPE;

Class c2 = Byte.TYPE;

Class c3 = Character.TYPE;

Class c4 = Short.TYPE;

Class c5 = Integer.TYPE;

Class c6 = Long.TYPE;

Class c7 = Float.TYPE;

Class c8 = Double.TYPE;

Class c9 = Void.TYPE;

class loader class

Reflection

ClassLoader class

所謂 class loader 是個 object,負責載入 classes。ClassLoader 是個 abstract class。給予它 class 名稱,class loader 便應該嘗試定位 (locate) 或生成 (generate) 某些資料,用以構成一個 class definition。典型策略是將該名稱轉換為檔名,然後讀入對應的 "class file"。

每個Class object 都內含一個getClassLoader(), reference to「定義該 Class object」的那個ClassLoader。

ClassLoader class 運用delegation model 來搜尋 classes 和 resources。其每一個 instance 都有一個 associated parent class loader。一旦請求搜尋一個 class 或 resource,ClassLoader instance 便會將工作委託 (delegate) 給其 parent class loader,在企圖找到 class 或 resource 本身之前。Virtual machine 的內建 class loader 稱為 bootstrap class loader,它本身沒有 parent,但也許用做一個ClassLoader instance 的 parent。

通常,Java virtual machine 以一種 platform-dependent 方式從 local file system 載入 classes。例如在 UNIX 系統上,virtual machine 從環境變數 CLASSPATH 所定義的目錄中載入 classes 。

然而某些 classes 最初或許並非來自檔案,而是來自其他資源,像是網絡,或是被應用程式所建構。method defineClass(String, byte[], int, int)會轉換an array of bytes 成為一個Class instance。這種新定義出來的 class,可使用 Class.newInstance() 產生 instances。

class

Reflection

Class methods

Class 涵蓋範圍(局部)

Package getPackage()

String getName()

TypeVariable<Class>[]

getTypeParameters()

Class getSuperClass()

Class[] getInterfaces()

Class[] getDeclaredClasses()

Class getDeclaringClass()

Consructor[]

getDeclaredConstructors()

Method[]

getDeclaredMethods()

Field[]

getDeclaredFields()

but 無法取得 import lib...

1

2

package java.util;

public class LinkedList<E>

extends AbstractSequentialList<E>

implements List<E>, Queue<E>,

Cloneable, java.io.Serializable

{

private static class Entry<E> { … }

public LinkedList() { … }

public LinkedList(Collection<? extends E> c) { … }

public E getFirst() { … }

public E getLast() { … }

private transient Entry<E> header = …;

private transient int size = 0;

}

3

4

5

6

7

8

9

tname

yy (class name part)

nm (fully qualified name)

key

value

java.lang.Integer

Integer

java.lang.Integer

這樣是一個 Hashtable 元素

lastIndexOf(".")

Reflection

小工具 tName()

static String tName(String nm, Hashtable ht) {

String yy;

String arr;

if (nm.charAt(0) != '[') {

int i = nm.lastIndexOf(".");

if (i == -1)

return nm; // primitive type, ignore it.

else {

yy = nm.substring(i+1);

if (ht != null)

ht.put(nm, yy);

return yy;

}

}

...

p ackage

Reflection

取得 package

Package getPackage()

1

package java.util;

Class c = null;

c = Class.forName(args[0]);

Package p;

p = c.getPackage();

if (p != null)

System.out.println("package "+p.getName()+";");

package java.util;

import list

Reflection

Constructor cn[];

Method mm[];

Field ff[];

取得完整的 import list

(1)取得所有fields,將其type記錄於hashtable

ff = c.getDeclaredFields();

for (int i = 0; i < ff.length; i++)

x = tName(ff[i].getType().getName(), classRef);

cn = c.getDeclaredConstructors();

for (int i = 0; i < cn.length; i++) {

Class cx[] = cn[i].getParameterTypes();

for (int j = 0; j < cx.length; j++)

x = tName(cx[j].getName(), classRef);

}

mm = c.getDeclaredMethods();

for (int i = 0; i < mm.length; i++) {

x = tName(mm[i].getReturnType().getName(), classRef);

Class cx[] = mm[i].getParameterTypes();

for (int j = 0; j < cx.length; j++)

x = tName(cx[j].getName(), classRef);

}

classRef.remove(c.getName());

(2)取得所有ctors,將其parameters type

記錄於hashtable

(3)取得所有methods,將其return/parameters type

記錄於hashtable

(4)從hashtable中移除自己

import list1

Reflection

取得完整的 import list

import java.lang.Object;

import java.util.Collection;

import java.util.Set;

import java.util.ListIterator;

import java.lang.Object;

import java.util.LinkedList$Entry;

import java.util.Collection;

import java.io.ObjectOutputStream;

import java.io.ObjectInputStream;

class name modifier

Reflection

取得 class name 及modifier

2

public class LinkedList<E>

String getName()

public final class Class

public class LinkedList

c = Class.forName(args[0]);

int mod = c.getModifiers();

System.out.print(Modifier.toString(mod)); //整個modifier

if (Modifier.isInterface(mod))

System.out.print(" "); //"interface" 已含於modifier

else

System.out.print(" class "); //關鍵字 "class"

System.out.print(tName(c.getName(), null)); //class名稱

public abstract interface Map

type parameters

Reflection

取得 Type Parameters

package java.util

public class LinkedList<E>

3

TypeVariable<Class>[]

getTypeParameters()

TypeVariable<Class>[] tv;

tv = c.getTypeParameters(); //warning: unchecked conversion

for (int i = 0; i < tv.length; i++) {

x = tName(tv[i].getName(), null); //例如 E,K,V...

if (i == 0) //第一個

System.out.print("<" + x);

else //非第一個

System.out.print("," + x);

if (i == tv.length-1) //最後一個

System.out.println(">");

}

public class LinkedList<E>

public abstract interface Map<K,V>

super class

Reflection

取得 Super Class

Class getSuperClass()

4

public class LinkedList<E>

extends AbstractSequentialList<E>

Class supClass;

supClass = c.getSuperclass();

if (supClass != null) //如果有super class

System.out.print(" extends" +

tName(supClass.getName(),classRef));

public class LinkedList<E>

extends AbstractSequentialList,

implements List, Queue, Cloneable, Serializable, {

implemented interfaces

Reflection

取得 Implemented Interfaces

public class LinkedList<E>

extends AbstractSequentialList<E>

implements List<E>, Queue<E>,

Cloneable, java.io.Serializable

Class[] getInterfaces()

5

public class LinkedList<E>

extends AbstractSequentialList,

implements List, Queue, Cloneable, Serializable, {

Class cc[];

Class ctmp;

//找出所有被實現的interfaces

cc = c.getInterfaces();

if (cc.length != 0)

System.out.print(", \r\n" + " implements ");

for (Class cite : cc)

System.out.print(tName(cite.getName(), null)+", ");

JDK1.5, for loop 新語法

declaredclasses inner classes declaringclass outer class

Reflection

取得 DeclaredClasses (inner classes)和 DeclaringClass (outer class)

Class[] getDeclaredClasses()

Class getDeclaringClass()

public class LinkedList<E> ...

{

private static class Entry<E> { … }

6

class name: LinkedList$Entry

LinkedList$Entry

LinkedList$ListItr

Map$Entry

cc = c.getDeclaredClasses(); //找出inner classes

for (Class cite : cc)

System.out.println(tName(cite.getName(), null));

ctmp = c.getDeclaringClass(); //找出outer classes

if (ctmp != null)

System.out.println(ctmp.getName());

declared constructors 1

Reflection

取得 Declared Constructors (1)

public class LinkedList<E> ...

{

public LinkedList() { … }

public LinkedList(Collection<? extends E> c) { … }

7

Consructor[]

getDeclaredConstructors()

declared constructors 2

Reflection

取得 Declared Constructors (2)

public java.util.LinkedList(Collection)

G: public java.util.LinkedList(java.util.Collection<? extends E>)

public java.util.LinkedList()

G: public java.util.LinkedList()

Constructor cn[];

cn = c.getDeclaredConstructors();

for (int i = 0; i < cn.length; i++) {

int md = cn[i].getModifiers();

System.out.print(" " + Modifier.toString(md) + " " +

cn[i].getName());

Class cx[] = cn[i].getParameterTypes();

System.out.print("(");

for (int j = 0; j < cx.length; j++) {

System.out.print(tName(cx[j].getName(), null));

if (j < (cx.length - 1)) System.out.print(", ");

}

System.out.print(")");

System.out.println("G: " + cn[i].toGenericString());

}

declared methods 1

Reflection

取得 Declared Methods (1)

public class LinkedList<E> ...

{

public E getFirst() { … }

public E getLast() { … }

Method[]

getDeclaredMethods()

8

declared methods 2

Reflection

取得 Declared Methods (2)

public Object get(int)

G: public E java.util.LinkedList.get(int)

public int size()

G: public int java.util.LinkedList.size()

Method mm[];

mm = c.getDeclaredMethods();

for (int i = 0; i < mm.length; i++) {

int md = mm[i].getModifiers();

System.out.print(" "+Modifier.toString(md)+" "+

tName(mm[i].getReturnType().getName(), null)+" "+

mm[i].getName());

Class cx[] = mm[i].getParameterTypes();

System.out.print("(");

for (int j = 0; j < cx.length; j++) {

System.out.print(tName(cx[j].getName(), null));

if (j < (cx.length - 1)) System.out.print(", ");

}

System.out.print(")");

System.out.println("G: " + mm[i].toGenericString());

}

declared fields 1

Reflection

取得 Declared Fields (1)

public class LinkedList<E> ...

{

private transient Entry<E> header = …;

private transient int size = 0;

}

Field[]

getDeclaredFields()

9

declared fields 2

Reflection

取得 Declared Fields (2)

private transient LinkedList$Entry header;

G: private transient java.util.LinkedList.java.util.LinkedList$Entry<E> java.util.LinkedList.header

private transient int size;

G: private transient int java.util.LinkedList.size

Field ff[];

ff = c.getDeclaredFields();

for (int i = 0; i < ff.length; i++) {

int md = ff[i].getModifiers();

System.out.println(" "+Modifier.toString(md)+" "+

tName(ff[i].getType().getName(), null) +" "+

ff[i].getName()+";");

System.out.println("G: " + ff[i].toGenericString());

}

ob ject class name

Reflection

動態生成 object(class name於執行期才得知)

1. 建構時 no argument

2. 建構時 with arguments

Class c = Class.forName("DynTest");

Object obj = null;

obj = c.newInstance(); //不帶引數

System.out.println(obj);

Class c = Class.forName("DynTest");

Class[] pTypes = new Class[] { double.class, int.class };

Constructorctor = c.getConstructor(pTypes);

//指定parameter list,便可獲得特定之ctor

Object obj = null;

Object[] arg = new Object[] {3.14159, 125}; //引數

obj = ctor.newInstance(arg);

System.out.println(obj);

object s f ields field s name

Reflection

取得/設定object's fields 內容(field's name於執行期才得知)

1. 首先產生 "field 所屬 class" 的一個 Class object c。

2. 呼叫c.getField(_) 製造出一個 Field object f。必須餵以 field name。

3. 視需要呼叫 (Type)f.get(obj) 或 f.set(obj, newValue)。呼叫時必須餵以 calling obj(和newValue)。

object s f ields field s name1

Reflection

取得/設定object's fields 內容(field's name於執行期才得知)

Test.class

public class Test {

public double d;

public static void main(String args[])

{

Class c = Class.forName("Test");

Fieldf = c.getField("d");

Test obj = new Test();

System.out.println("d= " + (Double)f.get(obj));

f.set(obj, 12.34);

System.out.println("d= " + obj.d);

}

}

1

2

3

object s method s method s name
喚起 object's methods(method's name於執行期才得知)

1. 首先產生 "method 所屬 class" 的一個 Class object c。

2. 呼叫c.getMethod(_,_) 製造出一個 Method object m。必須餵以 signature (method name & parameters list) 。

3. 呼叫 m.invoke(_,_),必須餵以一個 calling object 和一個 arguments list.

object s method s 1
喚起 object's methods (例1)

Test.class

public int add(int a, int b)

{

return a + b;

}

public static void main(String args[])

{

Class c = Class.forName("Test");

Class ptypes[] = new Class[2];

ptypes[0] = Integer.TYPE;

ptypes[1] = Integer.TYPE;

Method m = c.getMethod("add",ptypes);

Test obj = new Test();

Object args[] = new Object[2];

arg[0] = new Integer(37);

arg[1] = new Integer(47);

Object r = m.invoke(obj, arg);

Integer rval = (Integer)r;

System.out.println(rval.intValue());

}

Test obj = new Test();

obj.add(37, 47)

1

知道signature就可做出Method object

2

add(int a, int b)

3

呼叫 Method::invoke(x,x),

給予 calling object 和

argument list. (Object[ ]),

獲得 Object.

object s method s 2
喚起 object's methods (例2)

Test.class

public String func(String s, Hashtable ht)

{

System.out.println("func invoked"); return s;

}

public static void main(String args[])

{

Class c = Class.forName("Test");

Class ptypes[] = new Class[2];

ptypes[0] = Class.forName("java.lang.String");

ptypes[1] = Class.forName("java.util.Hashtable");

Method m = c.getMethod("func",ptypes);

Test obj = new Test();

Object args[] = new Object[2];

arg[0] = new String("Hello,world");

arg[1] = null;

Object r = m.invoke(obj, arg);

Integer rval = (String)r;

System.out.println(rval);

}

Test obj = new Test();

obj.tName("Hello", null)

1

知道signature就可

做出Method object

2

tName(String s, Hashtable ht)

3

呼叫 Method::invoke(x,x),

給予 calling object 和

argument list. (Object[ ]),

獲得 Object.

reflection apis
本例使用之 Reflection APIs

Class class:

Field class:

getName

getType

getModifiers

getxxx

setxxx

toGenericString

forName

getName

getDeclaredFields

getDeclaredMethods

getDeclaredConstructors

getDeclaredClasses

getDeclaringClass

getModifiers

getSuperClass

getGenericInterfaces

getGenericSuperclass

getInterfaces

getPackage

isArray

isEnum

isPrimitive

isSynthetic

isAnnotation

isInterface

getTypeParameters

newInstance

Method class:

getName

getParameterTypes

getReturnType

getModifiers

toGenericString

invoke

Modifier class:

IsInterface

Isxxx

toString

Type class:

Constructor class:

[empty]

getName

getParameterTypes

getModifiers

toGenericString

Package class:

getName

TypeVariable class:

getName

getGenericDeclaration

java library
Java Library源碼修改經驗

c:\jdk150\src\java\lang\Class.java ↑這是待改源碼(備份為宜)。修改後編譯獲得*.class。

c:\jdk150\jre\lib\rt.jar ↑這是Java Library classes(過程中不受影響)

c:\somewhere\Test.java ↑這是測試程式

c:\jdk150\jre\lib\endorsed↑這是新增目錄,classloader 將優先從這兒讀取.jar。將*.class搬移到e:\java\lang,壓縮為foo.jar(或.zip。任意命名。需夾帶路徑例如java\lang),再將foo.jar 搬至endorsed目錄下,於是測試程式便可正確用到修改後的classes

java library1
Java Library源碼修改經驗

rem "rejava.bat" usage :

rem (1) enter the directory which you want to rewrite java source.

rem (2) backup the original java source "x.java" to "x.java.ori".

rem (3) modify java source.

rem (4) rejava path filename (no extension name)

rem ex: rejavajavax\swing\textGapContent

del c:\jdk150\jre\lib\endorsed\jj-javax.jar

del c:\jdk150\jre\lib\endorsed\jj-java.jar

javac %2.java

move *.class e:\%1

e:

cd e:\

jar cvfM c:\jdk150\jre\lib\endorsed\jj-javax.jar javax

jar cvfM c:\jdk150\jre\lib\endorsed\jj-java.jar java

dir e:\%1

dir c:\jdk150\jre\lib\endorsed

c:

jj-java.jar

jj-javax.jar

把修改後的.java 編譯為.class,壓縮為 xxx.jar(需帶路徑例如java\lang)並搬移到endorsed,即可被class loader優先讀取。

slide62
更多資訊

"Java泛型技術之發展"http://www.jjhou.com/javatwo-2002.htm

本講題三個範例程式http://www.jjhou.com/javatwo-2004-reflection-and-generics-in-jdk15-sample.zip

《Java Reflection in Action》, by Ira R. Forman and Nate FormanManning Publications Co. http://www.manning.com/catalog/view.php?book=forman

"Take an in-depth look at the Java Reflection API"-- Learn about the new Java 1.1 tools for finding out information about classeshttp://www.javaworld.com/javaworld/jw-09-1997/jw-09-indepth.html

"Take a look inside Java classes"-- Learn to deduce properties of a Java class from inside a Java programhttp://www.javaworld.com/javaworld/jw-08-1997/jw-08-indepth.html