基础训练--(06)JAVA Reflection(映射)与命名规则
需要上课的人员:
-
不了解JAVA Reflection的人员。
-
不了解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中的程式码如下:
我们可以看到几个重点:
-
在Action中的Method与Field是不相称的,Method是setQ,而Field是query。
-
在JSP中的程式码,name的属性为q,所以送到后端时会变为q=xxx之类的参数。
这代表著前端使用者输入的内容,在Action中会触发setQ的Method,把值设进Field query之中。在这种状况中,被触发的Method是setQ,而且它并不会判断是否有Field q及Method getQ存在与否(实际上并没有getQ这个Method被宣告)。
上方的范例可以得到二个重点:
-
Method与Field可以不对称。
-
set与get并不需要同时存在,而是视需求来撰写。
Struts 2 其实是根据Request与Response来决定要呼叫get或set,Request时呼叫的是set Method,Response时呼叫的是get Method,这点请大家记清楚。
已实作Reflection的Framework
我们来谈谈有那些东西是套用命名规则与Reflection的套件吧:
-
Struts2
-
EL
-
JSTL
-
net.sf.json
-
Volecity
….等等,有太多的Framework都会实作Reflection,并利用「.」来区隔物件,例如user.name是先取得变数user的Object后,再去取得这个Object内的getName;所以请开发人员了解JAVA的命名规则,并实际运用在写程式上,因为这些Framework都是以开发人员已经使用JAVA的命名规则为基础来开发的。
作业-实作Reflection中的Method
请依下方的程式码,实作setName与getName的Method。