需要上课的人员:

  1. 不了解JAVA Reflection的人员。

  2. 不了解Struts 2 中,JAVA的变数为何可以在JSP中使用的人员。

JAVA Reflection(映射)

在写程式的时候,有时候会遇到一些比较特殊的情况,例如我有一个Class如下:

我想将它转为JSON的格式,变成{name:"myname",age:18}这样之类的,除了利用套件自动生成外,另一种方式是自己写,如下:

可是这样会遇到二个问题,第一个问题是:当我这个class因业务需求,加了一个属性后,产生JSON的这段程式码也要跟著变;第二个问题是:当我今天有N个属性,我就是针对jObject.put这一段程式码写N次。难道不能让它自动对应产生吗?答案是可以的,这种对应的方法叫做Reflection。

Reflection的Field、Method定义

在JAVA的Reflection中,有一个专有名词是Field,Field定义的是Class中的属性,如下图红框的部份:

而Method的定为则为下方的红框处:

这些定义都会在程式里被用到。

JAVA Reflection实作

要利用Reflection的机制,必须先取得这一个Class,才能取得Class内的Field或Method,取得Class的方法很简单,利用getClass即可,如下图:

取得Class后,以本例来说,我们需要取得Class内的Field,所以透过getDeclaredFields的Method来取得这个Class内的Field。

我们可以利用Field的getName()来取得对应的变数文字,在本例中即是name与age。

再利用Field的get(Object o),此时传入的参数为想要取得值的Object,也就Employee的物件。最后我们利用for each的方式,来取得每一个Field的name与Value,并将它塞入JSONObject中:

执行后的结果:

这就是Reflection的其中一种应用,另外Method是透过invoke的method来触发,下方是网路上的范例:

Reflection很好用,但一开始不太好理解,需要多写几次才能理解。

JAVA命名规则

JAVA有一些命名规则,大致介绍如下:

  • Class:头文字大写,第二单词以大写相接。

  • Field变数:头文字小写,第二单词以大写相接。

  • Method:头文字小写,第二单词以大写相接。

  • Constant:全文字大写,第二单词以_(底线)相接。

 

如下图范例:

遵守这些命名规则有什么好处呢?因为有很多Framework是套用JAVA的命名规则来实作JAVA Reflection,所以这些Framework都是假设我们已经遵守这些命名规则了。

Framework与命名规则与Reflection实例

大多数的Framework在实作Reflection的功能时,是以Method的方式来实作的,而不是利用Field,这一点要请大家搞清楚,而且因应时机的不同,分别去触发的Method也不同,以下图的Struts2程式为例:

UserAction.java的程式码如下:

JSP中的程式码如下:

我们可以看到几个重点:

  1. 在Action中的Method与Field是不相称的,Method是setQ,而Field是query。

  2. 在JSP中的程式码,name的属性为q,所以送到后端时会变为q=xxx之类的参数。

这代表著前端使用者输入的内容,在Action中会触发setQ的Method,把值设进Field query之中。在这种状况中,被触发的Method是setQ,而且它并不会判断是否有Field q及Method getQ存在与否(实际上并没有getQ这个Method被宣告)。

上方的范例可以得到二个重点:

  1. Method与Field可以不对称。

  2. set与get并不需要同时存在,而是视需求来撰写。

Struts 2 其实是根据Request与Response来决定要呼叫get或set,Request时呼叫的是set Method,Response时呼叫的是get Method,这点请大家记清楚。

已实作Reflection的Framework

我们来谈谈有那些东西是套用命名规则与Reflection的套件吧:

  1. Struts2

  2. EL

  3. JSTL

  4. net.sf.json

  5. Volecity

….等等,有太多的Framework都会实作Reflection,并利用「.」来区隔物件,例如user.name是先取得变数user的Object后,再去取得这个Object内的getName;所以请开发人员了解JAVA的命名规则,并实际运用在写程式上,因为这些Framework都是以开发人员已经使用JAVA的命名规则为基础来开发的。

作业-实作Reflection中的Method

请依下方的程式码,实作setName与getName的Method。

相关文章