內省java
⑴ java 中反射機制和內省機制的區別是什麼
1.什麼是反射
反射就是在運行狀態把 Java 類中的各種成分映射成相應相應的 Java 類,可以動態得獲取所有的屬性以及動態調用任意一個方法。
1).一段java代碼在程序的運行期間會經歷三個階段:source-->class-->runtime
2).Class對象在java中用一個Class對象來表示一個java類的class階Class對象封裝了一個java類定義的成員變數、成員方法、構造方法、包名、類名等。
2.反射怎麼用
1).獲得java類的各個組成部分,首先需要獲得代表java類的Class對象獲得Class對象有以下三種方式:
Class.forname(className) 用於做類載入
obj.getClass() 用於獲得對象的類型
類名.class 用於獲得指定的類型,傳參用2).反射類的構造方法,獲得實例
Class clazz = 類名.class;
Constuctor con = clazz.getConstructor(new Class[]{paramClazz1,paramClazz2,.....});
con.newInstance(params....);
內省
什麼是內省
通過反射的方式操作JavaBean的屬性,jdk提供了PropertyDescription類來操作訪問JavaBean的屬性,Beantils工具基於此來實現。
2.內省怎麼用
1).操作一個屬性
Object obj = new Object();
PropertyDescriptor pd = new PropertyDescriptor(propertyName,Class);聲明屬性描述對象,一次只可描述一個屬性
Method m = pd.getWriterMethod();//獲取setter方法
m.invoke(obj,value);
Method m = pd.getReaderMethod();//獲取getter方法
Object value = m.invoke(obj);
⑵ Java編程時如何節省內存,效率高
從理論上來講Java做的系統並不比其他語言開發出來的系統更佔用內存,那麼為什麼卻有這么多理由來證明它確實占內存呢?兩個字,陋習。
1、別用new Boolean()。
在很多場景中Boolean類型是必須的,比如JDBC中boolean類型的set與get都是通過Boolean封裝傳遞的,大部分ORM也是用Boolean來封裝boolean類型的,比如:
以下是引用片段:
ps.setBoolean(「isClosed」,new Boolean(true));
ps.setBoolean(「isClosed」,new Boolean(isClosed));
ps.setBoolean(「isClosed」,new Boolean(i==3));
通常這些系統中構造的Boolean實例的個數是相當多的,所以系統中充滿了大量Boolean實例小對象,這是相當消耗內存的。Boolean類實際上只要兩個實例就夠了,一個true的實例,一個false的實例。
Boolean類提供兩了個靜態變數:
以下是引用片段:
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
因為valueOf的內部實現是:return (b ? TRUE : FALSE);
所以可以節省大量內存。相信如果Java規范直接把Boolean的構造函數規定成private,就再也不會出現這種情況了。
2、別用new Integer。
和Boolean類似,java開發中使用Integer封裝int的場合也非常 多,並且通常用int表示的數值通常都非常小。SUN SDK中對Integer的實例化進行了優化,Integer類緩存了-128到127這256個狀態的Integer,如果使用 Integer.valueOf(int i),傳入的int范圍正好在此內,就返回靜態實例。這樣如果我們使用Integer.valueOf代替new Integer的話也將大大降低內存的佔用。如果您的系統要在不同的SDK(比如IBM SDK)中使用的話,那麼可以自己做了工具類封裝一下,比如IntegerUtils.valueOf(),這樣就可以在任何SDK中都可以使用這種特性。
3、用StringBuffer代替字元串相加。
這個我就不多講了,因為已經被 人講過N次了。我只想將一個不是笑話的笑話,我在看國內某「著名」java開發的WEB系統的源碼中,竟然發現其中大量的使用字元串相加,一個拼裝SQL 語句的方法中竟然最多構造了將近100個string實例。無語中!
4、過濫使用哈希表
有一定開發經驗的開發人員經常會使用hash表(hash 表在JDK中的一個實現就是HashMap)來緩存一些數據,從而提高系統的運行速度。比如使用HashMap緩存一些物料信息、人員信息等基礎資料,這 在提高系統速度的同時也加大了系統的內存佔用,特別是當緩存的資料比較多的時候。其實我們可以使用操作系統中的緩存的概念來解決這個問題,也就是給被緩存的分配一個一定大小的緩存容器,按照一定的演算法淘汰不需要繼續緩存的對象,這樣一方面會因為進行了對象緩存而提高了系統的運行效率,同時由於緩存容器不是無限制擴大,從而也減少了系統的內存佔用。現在有很多開源的緩存實現項目,比如ehcache、oscache等,這些項目都實現了FIFO、MRU等常見的緩存演算法。
5、避免過深的類層次結構和過深的方法調用。
因為這兩者都是非常佔用內存的(特別是方法調用更是堆棧空間的消耗大戶)。
6、變數只有在用到它的時候才定義和實例化。
7、盡量避免使用static變數,類內私有常量可以用final來代替。
8、對頻繁使用的對象採用對象池技術
9、保證每個IO操作,connection及時關閉
⑶ 內省的Java 內省機制
內省(Introspector)是Java語言對Bean類屬性、事件的一種預設處理方法。例如類A中有屬性name,那我們版可以通過getName,setName來得權到其值或者設置新的值。通過getName/setName來訪問name屬性,這就是默認的規則。Java中提供了一套API用來訪問某個屬性的getter/setter方法,通過這些API可以使你不需要了解這個規則(但你最好還是要搞清楚),這些API存放於包java.beans中。
一般的做法是通過類Introspector來獲取某個對象的BeanInfo信息,然後通過BeanInfo來獲取屬性的描述器(PropertyDescriptor),通過這個屬性描述器就可以獲取某個屬性對應的getter/setter方法,然後我們就可以通過反射機制來調用這些方法。
⑷ Java通過內省操作JavaBean有什麼作用
反射和內省操作很多時候都是在以後要做框架的時候作用非常大。
現在你學的是面向對象內編程,容即:你所寫代碼都能夠找到對應的類或介面,找到具體的方法寫出對應的代碼。
但是以後學面向抽象編程的時候,即:我們所寫的代碼完全抽象,比如我們寫的框架所要面向的類或方法目前並沒有的,而是以後別人用我們的框架寫出來的類。但是我們又怎麼調用去他們的類get/set方法呢?所以這個時候要用到反射和內省進行抽象編程。
現在你可以不懂那麼多,以後慢慢學多了就好了
⑸ java內省和反射的區別
經過多方面的資料搜集整理,寫下了這篇文章,本文主要講解java的反射和內省機制,希望對大家有點幫助,也希望大家提出不同的看法!
1).內省(Introspector)是 Java 語言對 Bean 類屬性、事件的一種預設處理方法。例如類 A 中有屬性 name, 那我們可以通過 getName,setName 來得到其值或者設置新的值。通過 getName/setName 來訪問 name 屬性,這就是默認的規則。 Java 中提供了一套 API 用來訪問某個屬性的 getter/setter 方法,通過這些 API 可以使你不需要了解這個規則(但你最好還是要搞清楚),這些 API 存放於包 java.beans 中。
2).直接通過屬性的描述器java.beans.PropertyDescriptor類,來訪問屬性的getter/setter 方法;
相關代碼:
public class Point {
private Integer x;
private Integer y;
public Point(Integer x, Integer y) {
super();
this.x = x;
this.y = y;
}
public Integer getX() {
return x;
}
public void setX(Integer x) {
this.x = x;
}
public Integer getY() {
return y;
}
public void setY(Integer y) {
this.y = y;
}
}
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
public class Reflect {
public static void main(String[] args) throws Exception {
Point point = new Point(2, 5);
String proName = "x";
getProperty(point, proName);
setProperty(point, proName);
}
private static void setProperty(Point point, String proName) throws Exception {
PropertyDescriptor proDescriptor = new PropertyDescriptor(proName, Point.class);
Method methodSetX = proDescriptor.getWriteMethod();
methodSetX.invoke(point, 8);
System.out.println(point.getX());// 8
}
private static void getProperty(Point point, String proName) throws Exception {
PropertyDescriptor proDescriptor = new PropertyDescriptor(proName, Point.class);
Method methodGetX = proDescriptor.getReadMethod();
Object objx = methodGetX.invoke(point);
System.out.println(objx);// 2
}
}
3).通過類 Introspector 來獲取某個對象的 BeanInfo 信息,然後通過 BeanInfo 來獲取屬性的描述器( PropertyDescriptor ),通過這個屬性描述器就可以獲取某個屬性對應的 getter/setter 方法,然後我們就可以通過反射機制來調用這些方法。
相關代碼:
把2中的getProperty()修改成如下形式:
private static void getProperty(Point point, String proName) throws Exception {
BeanInfo beanInfo = Introspector.getBeanInfo(point.getClass());
PropertyDescriptor[] proDescriptors = beanInfo.getPropertyDescriptors();
for(PropertyDescriptor prop: proDescriptors){
if(prop.getName().equals(proName)){
Method methodGetx = prop.getReadMethod();
System.out.println(methodGetx.invoke(point));//8
break;
}
}
}
4).我們又通常把javabean的實例對象稱之為值對象(Value Object),因為這些bean中通常只有一些信息欄位和存儲方法,沒有功能性方法。一個JavaBean類可以不當JavaBean用,而當成普通類用。JavaBean實際就是一種規范,當一個類滿足這個規范,這個類就能被其它特定的類調用。一個類被當作javaBean使用時,JavaBean的屬性是根據方法名推斷出來的,它根本看不到java類內部的成員變數(javabean的成員變數通常都是私有private的)。
5).除了反射用到的類需要引入外,內省需要引入的類如下所示,它們都屬於java.beans包中的類,自己寫程序的時候也不能忘了引入相應的包或者類。
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
6).下面講解一些開源的工具類Beanutils,需要額外下載的,commons-beanutils.jar,要使用它還必須導入commons-logging.jar包,不然會出異常;
相關代碼一:
public static void main(String[] args) throws Exception {
Point point = new Point(2, 5);
String proName = "x";
BeanUtils.setProperty(point, proName, "8");
System.out.println(point.getX());// 8
System.out.println(BeanUtils.getProperty(point, proName));// 8
System.out.println(BeanUtils.getProperty(point, proName).getClass().getName());// java.lang.String
BeanUtils.setProperty(point, proName, 8);
System.out.println(BeanUtils.getProperty(point, proName).getClass().getName());// java.lang.String
}
//我們看到雖然屬性x的類型是Integer,但是我們設置的時候無論是Integer還是String,BeanUtils的內部都是當成String來處理的。
相關代碼二:
BeanUtils支持javabean屬性的級聯操作;
public static void main(String[] args) throws Exception {
Point point = new Point(2, 5);//在point中加一個屬性 private Date birth = new Date();並產生setter/getter方法
String proName = "birth";
Date date= new Date();
date.setTime(10000);
BeanUtils.setProperty(point, proName, date);
System.out.println(BeanUtils.getProperty(point, proName));
BeanUtils.setProperty(point, "birth.time", 10000);
System.out.println(BeanUtils.getProperty(point, "birth.time"));//10000
}
//之所以可以 BeanUtils.setProperty(point, "birth.time", 10000);這樣寫,那是因為Date類中有getTime()和setTime()方法,即Date類中相當於有time這個屬性。
相關代碼三:
BeanUtils和PropertyUtils對比:
public static void main(String[] args) throws Exception {
Point point = new Point(2, 5);
String proName = "x";
BeanUtils.setProperty(point, proName, "8");
System.out.println(BeanUtils.getProperty(point, proName));//8
System.out.println(BeanUtils.getProperty(point, proName).getClass().getName());//java.lang.String
// PropertyUtils.setProperty(point, proName, "8");//exception:argument type mismatch
PropertyUtils.setProperty(point, proName, 8);
System.out.println(PropertyUtils.getProperty(point, proName));//8
System.out.println(PropertyUtils.getProperty(point, proName).getClass().getName());//java.lang.Integer
}
//BeanUtils它以字元串的形式對javabean進行轉換,而PropertyUtils是以原本的類型對javabean進行操作。如果類型不對,就會有argument type mismatch異常。
6).理解了相應的原理,那些現成的工具用起來就會更舒服,如Beanutils與PropertyUtils工具。這兩個工具設置屬性的時候一個主要區別是PropertyUtils.getPropety方法獲得的屬性值的類型為該屬性本來的類型,而BeanUtils.getProperty則是將該屬性的值轉換成字元串後才返回。
總結
Web 開發框架 Struts 中的 FormBean 就是通過內省機制來將表單中的數據映射到類的屬性上,因此要求 FormBean 的每個屬性要有 getter/setter 方法。但也並不總是這樣,什麼意思呢?就是說對一個 Bean 類來講,我可以沒有屬性,但是只要有 getter/setter 方法中的其中一個,那麼 Java 的內省機制就會認為存在一個屬性,比如類中有方法 setMobile ,那麼就認為存在一個 mobile 的屬性。
將 Java 的反射以及內省應用到程序設計中去可以大大的提供程序的智能化和可擴展性。有很多項目都是採取這兩種技術來實現其核心功能,例如我們前面提到的 Struts ,還有用於處理 XML 文件的 Digester 項目,其實應該說幾乎所有的項目都或多或少的採用這兩種技術。在實際應用過程中二者要相互結合方能發揮真正的智能化以及高度可擴展性。
⑹ 請問什麼是java中的內省和反射
用一句比較白的話來概括,反射就是讓你可以通過名稱來得到對象 ( 類,屬性,方法 ) 的技術。內省是 Java 語言對 Bean 類屬性、事件的一種預設處理方法。應該說幾乎所有的項目都或多或少的採用這兩種技術。在實際應用過程中二者要相互結合方能發揮真正的智能化以及高度可擴展性。
⑺ java的內省機制和反射機制什麼區別
內省,是針對復JavaBean對象的,反射,就是制把一個普通類中的每個組成部分都可以單獨取出來,對其每一個成員的調用或者修改不必依賴於new對象。內省技術訪問JavaBean,可以認為是和反射很像,但是內省和反射是不相同不相等的。。
⑻ Java的反射和內省的區別
1.什麼是反射
反射就是在運行狀態把 Java 類中的各種成分映射成相應相應的 Java 類,可以動態得獲取所有的屬性以及動態調用任意一個方法。
1).一段java代碼在程序的運行期間會經歷三個階段:source-->class-->runtime
2).Class對象
在java中用一個Class對象來表示一個java類的class階段
Class對象封裝了一個java類定義的成員變數、成員方法、構造方法、包名、類名等。
2.反射怎麼用
1).獲得java類的各個組成部分,首先需要獲得代表java類的Class對象
獲得Class對象有以下三種方式:
Class.forname(className) 用於做類載入
obj.getClass() 用於獲得對象的類型
類名.class 用於獲得指定的類型,傳參用
2).反射類的構造方法,獲得實例
Class clazz = 類名.class;
Constuctor con = clazz.getConstructor(new Class[]{paramClazz1,paramClazz2,.....});
con.newInstance(params....);
⑼ java 中反射機制和內省機制的區別
1.什麼是反射
反射就是在運行狀態把 Java 類中的各種成分映射成相應相應的 Java 類,可以動態得獲取所有的屬性以及動態調用任意一個方法。
1).一段java代碼在程序的運行期間會經歷三個階段:source-->class-->runtime
2).Class對象
在java中用一個Class對象來表示一個java類的class階段
Class對象封裝了一個java類定義的成員變數、成員方法、構造方法、包名、類名等。
2.反射怎麼用
1).獲得java類的各個組成部分,首先需要獲得代表java類的Class對象
獲得Class對象有以下三種方式:
Class.forname(className) 用於做類載入
obj.getClass() 用於獲得對象的類型
類名.class 用於獲得指定的類型,傳參用
2).反射類的構造方法,獲得實例
Class clazz = 類名.class;
Constuctor con = clazz.getConstructor(new Class[]{paramClazz1,paramClazz2,.....});
con.newInstance(params....);
3).反射類的成員方法
Method m = clazz.getMethod(methodName,new Class[]{paramClazz1,paramClazz2,.....});
m.invoke();
4).反射類的屬性
Field field = clazz.getField(fieldName);
field.setAccessible(true);//設置為可訪問
filed.setObject(value); //設置值
Object value = field.get(clazz); //獲得值
Object staticValue = filed.get(Class); //獲得靜態值
二:內省
1.什麼是內省
通過反射的方式操作JavaBean的屬性,jdk提供了PropertyDescription類來操作訪問JavaBean的屬性,Beantils工具基於此來實現。
2.內省怎麼用
1).操作一個屬性
Object obj = new Object();
PropertyDescriptor pd = new PropertyDescriptor(propertyName,Class); //聲明屬性描述對象,一次只可描述一個屬性
Method m = pd.getWriterMethod();//獲取setter方法
m.invoke(obj,value);
Method m = pd.getReaderMethod();//獲取getter方法
Object value = m.invoke(obj);
2).操作多個屬性
BeanInfo bi = Instospector.getBeanInfo(beanClass);//獲取Bean描述對象
PropertyDescriptor[] pds = bi.getPropertyDescriptors();//獲取屬性描述對象數組
拿到屬性描述對象數組之後再循環數組,剩餘的操作就跟"操作一個屬性"相同了。
⑽ 麻煩大家給我推薦一些介紹Java反射、內省、註解這類內容的書
專門講反射來的書……java reflection in action 沒有源中文版。中文版講這個的應該是沒有的。
註解不需要專門一本書的,想要看看的話,thinking in java 中有講解註解的這一章。第4版。