程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Groovy >> Groovy探索之對Java語言反射的簡化

Groovy探索之對Java語言反射的簡化

編輯:Groovy

Java語言的反射功能是我們不得不使用的功能,但事實上它的使用是相當繁瑣卻在功能上比較單一的一個功能。

例如,我們使用Java語言反射最多的地方是在運行時對POJO對象或者Domain對象的“set”和“get”方法的調用,因為對象屬性是私有的,獲取和設置對象屬性的值是通過對應的“get”和“set”方法進行的。下面是一個關於“get”方法調用的例子:

public static Object getFieldValue(Object bean,Field field)
{
try
{
String type = field.getType().getName();
if(type.equals("boolean")||type.equals("java.lang.Boolean"))
{
Method m1 = bean.getClass().getMethod(StrUtil.getIsMethodName(field.getName()),null);
return m1.invoke(bean, null);
}
else
{
Method m1 = bean.getClass().getMethod(StrUtil.getGetMethodName(field.getName()),null);
return m1.invoke(bean, null);
}
}
catch(Exception e)
{
e.printStackTrace();
if(logger.isDebugEnabled())
{
logger.debug("getFieldValue", e);
}
returnnull;
}
}

上面的代碼首先判斷Field的屬性是否為boolean,如果是,則調用isXXXX()方法;否則調用getXXXX()方法。

在調用的時候,首先Field的name獲取對應的“is”或“get”方法名,然後獲得Method對象,最後調用該對象的invoke方法獲得返回值。

整個過程相當的繁瑣。

但Groovy語言中,我們設置或獲取對象的屬性值可以直接通過“對象名.屬性名”獲取,因此設置和獲取對象屬性的值就不直接通過“set”和“get”方法了。

上面的Java代碼在Groovy程序中可以改造成下面的代碼:

defstatic getFieldValue(Object bean,String fieldName)
{
bean."$fieldName"
}

不錯,在前面的文章中,我曾經提出,Groovy語言的動態性跟Gstring有很大的關系,現在就可以看到,動態設置或獲取對象屬性值是通過Gstring對象來完成的。

真是簡單得不可思議,假如有如下一個Domain類:

class Man
{
String name
String age
String addr
}

我們使用該類來進行測試:

Man man = new Man()
man.name = 'Mike'
man.age = '22'
man.addr = 'Shenzhen'
println getFieldValue(man,'age')

打印結果為:

22

再做一個測試:

Man man = new Man()
man.name = 'Mike'
man.age = '22'
man.addr = 'Shenzhen'
man.metaClass.properties.each
{
println"property name: ${it.name}, property value: ${man."${it.name}"}"
}

結果為:

property name: class, property value: class base.Man
property name: addr, property value: Shenzhen
property name: age, property value: 22
property name: metaClass, property value: groovy.lang.MetaClassImpl@1749757[class base.Man]
property name: name, property value: Mike

可以看到,Groovy語言中設置或獲取對象屬性的值,根本不需要另寫一個類似“getFieldValue”這樣的方法,直接獲取就行了,簡單明了。

除了使用Gstring設置或獲取對象的屬性值,在運行時獲取方法的返回值也是通過Gstring完成的。請看下面的例子。

我們首先在上面的Man類中加入一個“toString”方法,如下:

class Man
{
String name
String age
String addr
public String toString()
{
"$name is $age year old, and live in $addr"
}
}

下面,我們就在運行時調用“toString”方法:

Man man = new Man()
man.name = 'Mike'
man.age = '22'
man.addr = 'Shenzhen'
def functionName = 'toString'
println man."${functionName}"()

可以看到,與動態設置或獲取屬性值唯一不同的是在Gstring對象後面跟了一個“()”。在Groovy語言中,Gstring對象後面如果沒有括號,表示調用的是屬性;有括號表示調用的是方法。

如果你將上面代碼的後一句改為如下代碼:

println man."${functionName}()"

則會拋出如下的Exception:

Exception in thread "main" groovy.lang.MissingPropertyException: No such property: toString() for class: base.Man

在Groovy語言中,這種動態調用對象方法的方法將會在很多地方派上用場。其中就有著名的委派模式。Java語言由於其語言的特點,很少使用委派模式。而面向對象的繼承卻在實踐中遇到了越來越多的問題。

在“使用組合代替繼承”口號越來越響亮的今天,委派技術將不可避免的越來越多的使用到。下面試著舉出一個例子來說明。

class Buyer
{
def borrow4Car()
{
println'borrow money for car'
}
def borrow4House()
{
println'borrow money for house'
}
}

class Bank
{
def borrowMoney(type)
{
Buyer buyer = new Buyer()
buyer."borrow4${type}"()
}
}

buyer向bank貸款,目的各不相同,有的是為了買車,有的是為了買房。如果bank要調查buyer貸款的目的,我們需要調用Bank類的“borrowMoney”方法,但Bank類本身不知道buyer貸款的目的,因此它需要將這個功能委派給Buyer類。

在Bank類的“borrowMoney”方法體內,我們可以看到先new了一個Buyer對象,然後調用該對象的方法,就完成了委派的過程。

buyer."borrow4${type}"()

可以看到,委派功能的完成,同樣是借助Gstring的動態特性,在運行時調用對象的方法。

下面來測試上面的代碼:

Bank bank = new Bank()
bank.borrowMoney('Car')

打印結果為:

borrow money for car

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved