㈠ 請問什麼是java中的內省和反射
用一句比較白的話來概括,反射就是讓襪枝你可以通過名稱來得到對象 ( 類,屬性,方法 ) 的技術。內省是 Java 語言對 Bean 類屬性、事件的一種預設處理方法。應該說幾乎所有的項目都友檔或多或少的採用這兩種技術。在實際應用過程中二者要相互結合方能發告告敏揮真正的智能化以及高度可擴展性。
㈡ 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 中反射機制和內省機制的區別是什麼
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開發技術,那究竟如何才能學習Java呢?
第一階段:企業入門級項目階段,可掌握Java核心基礎、面向對象、JavaSE API、MySQL資料庫、JDBS、HTML+CSS、Servlet、JSP、JavaScript等,可以完成常見中小型互聯網項目開發,達到初級Java開發工程師能力。
第二階段企業框架級項目階段是進階階段,增強Java基礎、web基礎、CSS/JavaScript進階、Maven項目管理、Spring5、SpringMVC、Mybatis、SMM綜合項目、學員項目等,完成本階段學員可以勝任各行業企業級項目中高級工程師崗位。
第三階段億級大並發分布式項目階段,掌握Linux、Docker、Vue、SpringBoot、項目整合Vue、分布式項目、Zookeepr、Dubbo、Springcloud、Redis、Elasticsearch、Quartz、RocketMQ、FastDFS、Mycat、CAS、分布式鎖、分布式事務、微信開發、學生項目等,學員學完後可以勝任大型、超大型互聯網項目開發高級工程師崗位。
初學Java雖然有一定的難度,但Java學習並不是不可逾越,只要你明確方向,找到有效的學習方法,堅持學習,一定能攻克Java難關,成為一名合格的Java開發工程師。
㈤ java中的反射機制是什麼,有什麼作用啊
Method類中的方法的使用(含代碼和注釋):
getMethods()獲得本類及父類中的public許可權修飾**符方法
getDeclaredMethods()專門獲得調用該方法的對象的本類中的所有方法包括private許可權修飾符**的方法
getDeclaredMethod(Stringname,class<?>...parameterTypes)
第一個參數:方法的名稱
第二個參數:可變長度,寫你要查找的那個方法的參數類型列表.class
getParameterCount()得到方法的參數個數123456
packageLessonForReflection03;importjava.lang.reflect.Method;importjava.lang.reflect.Modifier;abstractclassCard{
privatevoidcreatRandomNumbers(intcount)//private關鍵字
{
}
publicvoidgetFullCardsNumbers(String[]random,Stringpre_numbers)
{
}
publicstaticvoidgetUserInfor()
{
}
(Stringtel);
(intsal1,intsal2),ArithmeticException;}publicclassMethodInforGetter{
publicstaticvoidmain(String[]args)
{
Class<?>c1=Card.class;
System.out.println("-------------------------");
Method[]m1=c1.getMethods();//getMethods()獲得本類及父類中的public方法!
for(Methodm:m1)
{
System.out.println(m);
}
System.out.println("-------------------------");
Method[]m2=c1.getDeclaredMethods();//getDeclaredMethods()專門獲得本類中的所有方法包括private!
for(Methodm:m2)
{
System.out.println(m);
}
System.out.println("-------------------------");
/*
*getDeclaredMethod(Stringname,class<?>...parameterTypes)
*第一個參數:方法的名稱
*第二個參數:可變長度,寫你要查找的那個方法的參數類型列表
*
*getParameterCount()得到方法的參數個數
*/
try
{
Methodm3=c1.getDeclaredMethod("getUserInfor");
System.out.println(m3);
//getParameterCount()方法,獲得方法參數個數
System.out.println(m3.getParameterCount());
System.out.println(Modifier.toString(m3.getModifiers()));//獲得方法修飾符
System.out.println(m3.getReturnType());
System.out.println("-------------------------");
Methodm4=c1.getDeclaredMethod("getUserInfor",int.class,int.class);
//getExceptionTypes()可以獲得初始化當前Method對象的給Class對象初始化的那個類的那個指定方法拋出的異常類型
Class<?>[]exception=m4.getExceptionTypes();
for(Class<?>e:exception)
{
System.out.println(e);
}
}catch(NoSuchMethodException|SecurityExceptione)
{
e.printStackTrace();
}
}}576777879808182838485868788
Constructor類中的方法的使用www.xiaoyuani.com(含代碼和注釋):
java.lang.reflect.Constructor:
Constructor[]getConstructor()獲得本類里的public許可權修飾符構造函數,不能獲取父類的!
Constructor[]getDeclaredConstructor()獲得本類中的所以構造函數!
Constructor<T>getConstructor(Class...parameterType)用參數決定獲得本類中的某個的構造方法,只能獲得public的
Constructor<T>getDeclaredConstructor(Class...parameterType)用參數決定獲得本類中的某個構造方法
附:
JDK8.0之後新增的類:
Executable:
它是Method和Constructor的父類
常用方法:
getParameter()獲得類中方法參數
getExceptionTypes()獲得類中某個方法拋出異常類型
getMoidfiers()獲得方法許可權修飾符
Parameter:
封裝並代表了參數實例123456789101112131415
packageLessonForReflection03;importjava.lang.reflect.Constructor;importjava.lang.reflect.Modifier;importjava.lang.reflect.Parameter;/*
*java.lang.reflect.Constructor
*
*Constructor[]getConstructor();獲得本類里的public許可權修飾符構造函數,不能獲取父類的
*Constructor[]getDeclaredConstructor();得本類里的全部構造
*
*Constructor<T>getConstructor(Class...parameterType);用參數決定獲得哪個構造方法
*Constructor<T>getDeclaredConstructor(Class...parameterType);
*
*/{
publicstaticvoidmain(String[]args)
{
System.out.println("獲得Cricle本類里的public許可權修飾符構造函數,不能獲取父類的Constructor[]getConstructor()");
System.out.println("子類繼承不了父類中的構造方法和private");
//Constructor[]getConstructor()獲得Cricle本類里的public許可權修飾符構造函數,不能獲取父類的
//子類繼承不了父類中的構造方法和private
Class<Circle>c1=Circle.class;
Constructor<?>[]cons1=c1.getConstructors();
for(Constructor<?>cons:cons1)
{
System.out.println(cons);
//System.out.println(cons.getName());
}
System.out.println("-----------------------");
System.out.println("方法獲得本類中的所有構造函數getDeclaredConstructor()");
Constructor<?>[]cons2=c1.getDeclaredConstructors();
for(Constructor<?>cons:cons2)
{
System.out.println(cons);
}
System.out.println("-----------------------");
try
{
System.out.println("方法用參數指定獲得本類!構造方法,只能獲取public的Constructor<T>getConstructor(Class...parameterType)");
Constructor<?>cons3=c1.getConstructor(int.class);
System.out.println(Modifier.toString(cons3.getModifiers()));
System.out.println(cons3);
System.out.println("-----------------------");
System.out.println("方法用參數指定獲得本類!構造方法任何許可權修飾符的都可以獲得Constructor<T>getDeclaredConstructor(Class...parameterType)");
Constructor<?>cons4=c1.getDeclaredConstructor(String.class);
System.out.println(cons4);
System.out.println("-----------------------");
/*
*JDK8.0之後新增的類
*Executable:
*是Method和Constructor的父類
*方法:
*getParameter();
*getExceptionTypes();
*getModifiers();
*getTypeParameters();
*
*Parameter:
*封裝並代表了參數實例
*/
System.out.println("獲取類中方法的參數getParameters()");
Constructor<?>cons5=c1.getDeclaredConstructor(int.class,String.class);
Parameter[]p1=cons5.getParameters();
for(Parameterp:p1)
{
System.out.println(p);
}
}catch(NoSuchMethodException|SecurityExceptione)
{
e.printStackTrace();
}
}}5767778798081828384858687
代碼中提到的Circle類和Shape類二者為繼承關系:
packageLessonForReflection03;publicclassCircleextendsShape{
privateintr;
privateStringcolor;
publicCircle(intr,Stringcolor)
{
super();
this.r=r;
this.color=color;
}
publicCircle(intr)
{
super();
this.r=r;
}
protectedCircle(Stringcolor)
{
super();
this.color=color;
}
Circle()
{
super();
}}
packageLessonForReflection03;publicclassShape{
privateintper;
publicShape(intper)
{
super();
this.per=per;
}
publicShape()
{
super();
}}1234567891011121314151617
部分文字來源於:
咕嘟咖啡楊海濱老師 — 《java編程語言高級特性》
輕量化研習Java相關技術倡導者
「愛碼學院」聯合創始人自適應教學理念提出者踐行者;多年開發及項目管理經歷;出版《JavaEE企業級應用與開發》一書;10餘年高校項目實踐畢設指導經驗;企業軟培經驗豐富