亚洲精品中文字幕无乱码_久久亚洲精品无码AV大片_最新国产免费Av网址_国产精品3级片

java語言

Java程序設(shè)計示例教程

時間:2024-09-19 06:16:23 java語言 我要投稿
  • 相關(guān)推薦

Java程序設(shè)計示例教程

  本文以實例形式詳細講述了Java的反射機制,是Java程序設(shè)計中重要的技巧。分享給大家供大家參考。具體分析如下:

  首先,Reflection是Java 程序開發(fā)語言的特征之一,它允許運行中的 Java 程序?qū)ψ陨磉M行檢查,或者說"自審",并能直接操作程序的內(nèi)部屬性。例如,使用它能獲得 Java 類中各成員的名稱并顯示出來。 Java 的這一能力在實際應(yīng)用中也許用得不是很多,但是在其它的程序設(shè)計語言中根本就不存在這一特性。例如,Pascal、C 或者 C++ 中就沒有辦法在程序中獲得函數(shù)定義相關(guān)的信息。

  JavaBean 是 reflection 的實際應(yīng)用之一,它能讓一些工具可視化的操作軟件組件。這些工具通過 reflection 動態(tài)的載入并取得 Java 組件(類) 的屬性。

  1. 一個簡單的例子

  考慮下面這個簡單的例子,讓我們看看 reflection 是如何工作的。

  import java.lang.reflect.*; public class DumpMethods { public static void main(String args[]) { try { Class c = Class.forName("java.util.Stack"); Method m[] = c.getDeclaredMethods(); for (int i = 0; i < m.length; i++) System.out.println(m[i].toString()); } catch (Throwable e){ System.err.println(e); } } }

  它的結(jié)果輸出為:

  public synchronized java.lang.Object java.util.Stack.pop()public java.lang.Object java.util.Stack.push(java.lang.Object)public boolean java.util.Stack.empty()public synchronized java.lang.Object java.util.Stack.peek()public synchronized int java.util.Stack.search(java.lang.Object)

  這樣就列出了java.util.Stack 類的各方法名以及它們的限制符和返回類型。

  這個程序使用 Class.forName 載入指定的類,然后調(diào)用 getDeclaredMethods 來獲取這個類中定義了的方法列表。java.lang.reflect.Methods 是用來描述某個類中單個方法的一個類。

  2.開始使用 Reflection

  用于 reflection 的類,如 Method,可以在 java.lang.relfect 包中找到。使用這些類的時候必須要遵循三個步驟:第一步是獲得你想操作的類的 java.lang.Class 對象。在運行中的 Java 程序中,用 java.lang.Class 類來描述類和接口等。

  下面就是獲得一個 Class 對象的方法之一:

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

  這條語句得到一個 String 類的類對象。還有另一種方法,如下面的語句:

  Class c = int.class; 或者 Class c = Integer.TYPE;

  它們可獲得基本類型的類信息。其中后一種方法中訪問的是基本類型的封裝類 (如 Integer) 中預(yù)先定義好的 TYPE 字段。

  第二步是調(diào)用諸如 getDeclaredMethods 的方法,以取得該類中定義的所有方法的列表。

  一旦取得這個信息,就可以進行第三步了——使用 reflection API 來操作這些信息,如下面這段代碼:

  Class c = Class.forName("java.lang.String"); Method m[] = c.getDeclaredMethods(); System.out.println(m[0].toString());

  它將以文本方式打印出 String 中定義的第一個方法的原型。

  在下面的例子中,這三個步驟將為使用 reflection 處理特殊應(yīng)用程序提供例證。

  模擬 instanceof 操作符

  得到類信息之后,通常下一個步驟就是解決關(guān)于 Class 對象的一些基本的問題。例如,Class.isInstance 方法可以用于模擬 instanceof 操作符:

  class S { } public class IsInstance { public static void main(String args[]) { try { Class cls = Class.forName("S"); boolean b1 = cls.isInstance(new Integer(37)); System.out.println(b1); boolean b2 = cls.isInstance(new S()); System.out.println(b2); } catch (Throwable e) { System.err.println(e); } } }

  在這個例子中創(chuàng)建了一個S 類的 Class 對象,然后檢查一些對象是否是S的實例。Integer(37) 不是,但 new S()是。

  3.找出類的方法

  找出一個類中定義了些什么方法,這是一個非常有價值也非;A(chǔ)的 reflection 用法。下面的代碼就實現(xiàn)了這一用法:

  import java.lang.reflect.*; public class Method1 { private int f1(Object p, int x) throws NullPointerException { if (p == null) throw new NullPointerException(); return x; } public static void main(String args[]) { try { Class cls = Class.forName("Method1"); Method methlist[] = cls.getDeclaredMethods(); for (int i = 0; i < methlist.length; i++) { Method m = methlist[i]; System.out.println("name = " + m.getName()); System.out.println("decl class = " + m.getDeclaringClass()); Class pvec[] = m.getParameterTypes(); for (int j = 0; j < pvec.length; j++) System.out.println("param #" + j + " " + pvec[j]); Class evec[] = m.getExceptionTypes(); for (int j = 0; j < evec.length; j++) System.out.println("exc #" + j + " " + evec[j]); System.out.println("return type = " + m.getReturnType()); System.out.println("-----"); } } catch (Throwable e) { System.err.println(e); } } }

  這個程序首先取得 method1 類的描述,然后調(diào)用 getDeclaredMethods 來獲取一系列的 Method 對象,它們分別描述了定義在類中的每一個方法,包括 public 方法、protected 方法、package 方法和 private 方法等。如果你在程序中使用 getMethods 來代替 getDeclaredMethods,你還能獲得繼承來的各個方法的信息。

  取得了 Method 對象列表之后,要顯示這些方法的參數(shù)類型、異常類型和返回值類型等就不難了。這些類型是基本類型還是類類型,都可以由描述類的對象按順序給出。

  輸出的結(jié)果如下:

  name = f1 decl class = class method1 param #0 class java.lang.Object param #1 int exc #0 class java.lang.NullPointerException return type = int-----name = main decl class = class method1 param #0 class [Ljava.lang.String; return type = void

  4.獲取構(gòu)造器信息

  獲取類構(gòu)造器的用法與上述獲取方法的用法類似,如:

  import java.lang.reflect.*;public class Constructor1 { public Constructor1() { } protected Constructor1(int i, double d) { } public static void main(String args[]) { try { Class cls = Class.forName("Constructor1"); Constructor ctorlist[] = cls.getDeclaredConstructors(); for (int i = 0; i < ctorlist.length; i++) { Constructor ct = ctorlist[i]; System.out.println("name = " + ct.getName()); System.out.println("decl class = " + ct.getDeclaringClass()); Class pvec[] = ct.getParameterTypes(); for (int j = 0; j < pvec.length; j++) System.out.println("param #" + j + " " + pvec[j]); Class evec[] = ct.getExceptionTypes(); for (int j = 0; j < evec.length; j++) System.out.println("exc #" + j + " " + evec[j]); System.out.println("-----"); } } catch (Throwable e) { System.err.println(e); } } }

  這個例子中沒能獲得返回類型的相關(guān)信息,那是因為構(gòu)造器沒有返回類型。

  這個程序運行的結(jié)果是:

  name = Constructor1decl class = class Constructor1param #0 intparam #1 double-----name = Constructor1decl class = class Constructor1-----

  5.獲取類的字段(域)

  找出一個類中定義了哪些數(shù)據(jù)字段也是可能的,下面的代碼就在干這個事情:

  import java.lang.reflect.*; public class Field1 { private double d; public static final int i = 37; String s = "testing"; public static void main(String args[]) { try { Class cls = Class.forName("Field1"); Field fieldlist[] = cls.getDeclaredFields(); for (int i = 0; i < fieldlist.length; i++) { Field fld = fieldlist[i]; System.out.println("name = " + fld.getName()); System.out.println("decl class = " + fld.getDeclaringClass()); System.out.println("type = " + fld.getType()); int mod = fld.getModifiers(); System.out.println("modifiers = " + Modifier.toString(mod)); System.out.println("-----"); } } catch (Throwable e) { System.err.println(e); } } }

  這個例子和前面那個例子非常相似。例中使用了一個新東西 Modifier,它也是一個 reflection 類,用來描述字段成員的修飾語,如“private int”。這些修飾語自身由整數(shù)描述,而且使用 Modifier.toString 來返回以“官方”順序排列的字符串描述 (如“static”在“final”之前)。這個程序的輸出是:

  name = ddecl class = class Field1type = doublemodifiers = private-----name = idecl class = class Field1type = intmodifiers = public static final-----name = sdecl class = class Field1type = class java.lang.Stringmodifiers = -----

  和獲取方法的情況一下,獲取字段的時候也可以只取得在當前類中申明了的字段信息 (getDeclaredFields),或者也可以取得父類中定義的字段 (getFields) 。

  6.根據(jù)方法的名稱來執(zhí)行方法

  文本到這里,所舉的例子無一例外都與如何獲取類的信息有關(guān)。我們也可以用 reflection 來做一些其它的事情,比如執(zhí)行一個指定了名稱的方法。下面的示例演示了這一操作:

  import java.lang.reflect.*; public class Method2 { public int add(int a, int b) { return a + b; } public static void main(String args[]) { try { Class cls = Class.forName("Method2"); Class partypes[] = new Class[2]; partypes[0] = Integer.TYPE; partypes[1] = Integer.TYPE; Method meth = cls.getMethod("add", partypes); Method2 methobj = new Method2(); Object arglist[] = new Object[2]; arglist[0] = new Integer(37); arglist[1] = new Integer(47); Object retobj = meth.invoke(methobj, arglist); Integer retval = (Integer) retobj; System.out.println(retval.intValue()); } catch (Throwable e) { System.err.println(e); } } }

  假如一個程序在執(zhí)行的某處的時候才知道需要執(zhí)行某個方法,這個方法的名稱是在程序的運行過程中指定的 (例如,JavaBean 開發(fā)環(huán)境中就會做這樣的事),那么上面的程序演示了如何做到。

  上例中,getMethod用于查找一個具有兩個整型參數(shù)且名為 add 的方法。找到該方法并創(chuàng)建了相應(yīng)的Method 對象之后,在正確的對象實例中執(zhí)行它。執(zhí)行該方法的時候,需要提供一個參數(shù)列表,這在上例中是分別包裝了整數(shù) 37 和 47 的兩個 Integer 對象。執(zhí)行方法的返回的同樣是一個 Integer 對象,它封裝了返回值 84。

  7.創(chuàng)建新的對象

  對于構(gòu)造器,則不能像執(zhí)行方法那樣進行,因為執(zhí)行一個構(gòu)造器就意味著創(chuàng)建了一個新的對象 (準確的說,創(chuàng)建一個對象的過程包括分配內(nèi)存和構(gòu)造對象)。所以,與上例最相似的例子如下:

  import java.lang.reflect.*; public class Constructor2 { public Constructor2() { } public Constructor2(int a, int b) { System.out.println("a = " + a + " b = " + b); } public static void main(String args[]) { try { Class cls = Class.forName("Constructor2"); Class partypes[] = new Class[2]; partypes[0] = Integer.TYPE; partypes[1] = Integer.TYPE; Constructor ct = cls.getConstructor(partypes); Object arglist[] = new Object[2]; arglist[0] = new Integer(37); arglist[1] = new Integer(47); Object retobj = ct.newInstance(arglist); } catch (Throwable e) { System.err.println(e); } } }

  根據(jù)指定的參數(shù)類型找到相應(yīng)的構(gòu)造函數(shù)并執(zhí)行它,以創(chuàng)建一個新的對象實例。使用這種方法可以在程序運行時動態(tài)地創(chuàng)建對象,而不是在編譯的時候創(chuàng)建對象,這一點非常有價值。

  8.改變字段(域)的值

  reflection 的還有一個用處就是改變對象數(shù)據(jù)字段的值。reflection 可以從正在運行的程序中根據(jù)名稱找到對象的字段并改變它,下面的例子可以說明這一點:

  import java.lang.reflect.*; public class Field2 { public double d; public static void main(String args[]) { try { Class cls = Class.forName("Field2"); Field fld = cls.getField("d"); Field2 f2obj = new Field2(); System.out.println("d = " + f2obj.d); fld.setDouble(f2obj, 12.34); System.out.println("d = " + f2obj.d); } catch (Throwable e) { System.err.println(e); } } }

  這個例子中,字段 d 的值被變?yōu)榱?12.34。

  9.使用數(shù)組

  本文介紹的 reflection 的最后一種用法是創(chuàng)建的操作數(shù)組。數(shù)組在 Java 語言中是一種特殊的類類型,一個數(shù)組的引用可以賦給 Object 引用。觀察下面的例子看看數(shù)組是怎么工作的:

  import java.lang.reflect.*; public class Array1 { public static void main(String args[]) { try { Class cls = Class.forName("java.lang.String"); Object arr = Array.newInstance(cls, 10); Array.set(arr, 5, "this is a test"); String s = (String) Array.get(arr, 5); System.out.println(s); } catch (Throwable e) { System.err.println(e); } } }

  例中創(chuàng)建了 10 個單位長度的 String 數(shù)組,為第 5 個位置的字符串賦了值,最后將這個字符串從數(shù)組中取得并打印了出來。

  下面這段代碼提供了一個更復雜的例子:

  import java.lang.reflect.*; public class Array2 { public static void main(String args[]) { int dims[] = new int[]{5, 10, 15}; Object arr = Array.newInstance(Integer.TYPE, dims); Object arrobj = Array.get(arr, 3); Class cls = arrobj.getClass().getComponentType(); System.out.println(cls); arrobj = Array.get(arrobj, 5); Array.setInt(arrobj, 10, 37); int arrcast[][][] = (int[][][]) arr; System.out.println(arrcast[3][5][10]); } }

  例中創(chuàng)建了一個 5 x 10 x 15 的整型數(shù)組,并為處于 [3][5][10] 的元素賦了值為 37。注意,多維數(shù)組實際上就是數(shù)組的數(shù)組,例如,第一個 Array.get 之后,arrobj 是一個 10 x 15 的數(shù)組。進而取得其中的一個元素,即長度為 15 的數(shù)組,并使用 Array.setInt 為它的第 10 個元素賦值。

  注意創(chuàng)建數(shù)組時的類型是動態(tài)的,在編譯時并不知道其類型。

  相信本文所述對大家Java程序設(shè)計的學習有一定的借鑒價值。

【Java程序設(shè)計示例教程】相關(guān)文章:

java教程之Java編程基礎(chǔ)12-03

java selenium基本教程04-01

Java面向過程教程03-30

Java編程學習示例04-03

Java程序設(shè)計里的線程04-02

關(guān)于循環(huán)的java代碼示例04-03

Java語言程序設(shè)計基礎(chǔ)篇11-30

java程序設(shè)計基礎(chǔ)重點分析03-26

Java構(gòu)建JSE開發(fā)環(huán)境教程03-29