反射相關:[利用反射的各種操作都是在運行期進行的. ]1.在面向對象的世界里,萬事萬物皆對象.
但是java語言中,靜態的成員 與基本數據類型類 不是對象.
類是不是對象? 誰的對象呢?
類是對象,任何類都是java.lang.Class類的實例對象.
2.類java.lang.Class的對象到底如何表示呢?(與普通類的對象區別)
[There is a class named 'Class'] 一個名叫Class的類.
//官方稱呼為: (一個類的)類類型(Class Type).
//一個類只能有一個類類型,或者理解成,它只是Class類的一個具體的實例對象.
所以,不管通過以下三種中任何一種方式,得到同一個類的類類型都是相同的.(都是同一個Class類的實例對象).
[上面關于類類型的理解一定要把握好.]
已知一個類Foo, Foo f1=new Foo();
1.Class c1=Foo.class;[實際在告訴我們任何一個類都有一個隱含的靜態成員變量class]
2.Class c2=f.getClass();[通過某個類的一個對象獲取此類的類類型]
3.Class c3=Class.forName("包名.類名");[直接指定類的全稱進行獲取]
并且,c1==c2==c3.因為都是指Class的同一個實例對象Foo.該類稱為Foo的類類型.
得到了某個類的類類型后,我們就可以通過它去創建該類的實例對象:
Foo f2 = (Foo) c1.newInstance();[前提是此類(Foo)必須要有無參構造方法]
3.Java動態加載類
1.Class.forName("類的全稱").第三種途徑則是動態加載類.
.不僅表示了類的類類型,還代表了是動態加載類.
.要區分開編譯與運行.
.編譯時刻加載類是靜態加載類/運行時刻加載類是動態加載類.
public Class Office{
public static void main(String[] args){
//使用NEW關鍵字創建對象,是靜態加載類,在編譯時刻就需要
//加載所有的可能用到的類.所以相關的類不論是否用到都必須存在.
if("Word".equals(args[0]){
Word w=new Word();
w.start();
}
if("Excel".equals(args[0]){
Excel e=new Excel();
e.start();
}
}
}
但是,我們更希望在使用的時候,用到哪個類(功能)去加載哪個類,不用的不加載.那么上面的例子是做不到的.因為不論用到哪個,其他的類必須全部存在.
那么,如何解決?----動態加載類,在運行時,用到哪個類再去加載哪個類.
public Class OfficeBetter{
public static void main(String [] args){
//動態加載指定類.
Class c=Class.forName(args[0]);
OfficeAble oa=(OfficeAble)c.newInstance();
//多態:實際是哪個類,就調用實際類中此項功能.
oa.start();
}
}
//給各個類制定一個統一的標準.(多態的應用)
public interface OfficeAble{
void start();
}
這樣在編譯OfficeBetter時,是完全通過的.而在運行時,需要你去指定具體用到哪個類,它就會去加載這個類.(非常好的設計思想@_@)
[所以,以后功能性的類盡量用這種設計思想,盡量用動態加載.這樣更新的時候,只需要添加,刪除各個功能類并且讓各個功能類實現這一統一的標準(接口)]
4.反射獲取方法的信息(返回值類型,方法名,參數類型)
Class c1=int.class;
Class c2=String.class;
Class c3=double.class;//與下面的Double完全不同.
Class c4=Double.class;
Class c5=void.class;
基本數據類型,void都有對應的類類型.
public Class ClassUtil{
public static void PRintMethodInfo(Object obj){
//首先獲取對象所屬類的類類型
Class c=obj.getClass();
//獲取類的類名稱
system.out.println("類的名稱:"+c.getName());
//java.lang.reflect.Method類,萬事萬物皆對象,那么任何一條方法也是這//Method類的對象.
//此方法獲取的是所有的public 的函數,包括從父類繼承來的方法(肯定是public方法)
Method[] methods=c.getMethods();
//此方法返回的是此類自己聲明的所有方法(包括public&private方法)
Method[] methods1=c.getDeclaredMethods();
for(int i=0;i<methods.length;i++){
//得到返回值類型的類類型(int.class,void.class)
Class returnType=methods[i].getReturnType();
//得到了返回值類型的名字.
system.out.print(returnType.getName());
//得到了方法的名字.
system.out.print(methods[i].getName());
//得到方法的參數類的類類型
Class[] paramTypes=method[i].getParameterTypes();
for(int j=0;j<paramTypes.length;j++){
//得到具體某個參數類型的名字
system.out.print(paramTypes[j].getName());
}
}
}
//成員變量也是對象.
//java.lang.reflect.Field類的對象.
//此類封裝了關于成員變量的操作.
//getFields():獲取所有public的成員變量
//getDeclaredFields():獲取所有此類自己聲明的成員變量(public&private)
public static void printFieldInfo(Object obj){
Class c=obj.getClass();
Field[] fields=c.getDeclaredFields();
for(Field field:fields){
//獲得此成員變量的類類型
Class fieldType=field.getType();
String typeName=fieldType.getName();
//得到成員變量的名字.
String fieldName=field.getName();
system.out.println("fieldType:"+typeName+","+"fieldName:"+fieldName);
}
}
public static void printConstructorInfo(Object object) {//1.由某個類的對象,得到 該類的 類類型.Class<?> cls=object.getClass();//2.由該類的類類型,得到該類的所有指定的構造函數.Constructor[] constructors=cls.getDeclaredConstructors();for (Constructor constructor : constructors) {System.out.print("構造器名稱: "+constructor.getName()+" :參數類型:");Class[] paramTypes=constructor.getParameterTypes();for (Class class1 : paramTypes) {System.out.print(class1.getName()+";");}System.out.println();}}
}
5.方法反射來調用方法.
語法:m.invoke(obj,參數);
obj.print(參數);
//b.print(10,20);方法的反射操作是用method為進行方法調用.與b.print(10,20)效//果一樣.可變參數Object...可以寫成new Object[]{10,20},也可以直接寫入各個參//數:10,20;
public class Test4 { /** * 學習如何獲得方法對象,通過方法對象調用方法執行. * @param args */ public static void main(String[] args) { B b=new B(); Class<?> cls=b.getClass(); try { Method method=cls.getDeclaredMethod("print", new Class[]{int.class,int.class}); Object object=method.invoke(b, 10,20); Method method2=cls.getDeclaredMethod("print", new Class[]{String.class,String.class}); Object object2=method2.invoke(b, new String[]{"Manny","HaiXia"}); /** * 學習如何獲得字段對象,并且更改它的值; */ Field field=cls.getDeclaredField("count"); field.setaccessible(true); field.set(b, 100); System.out.println(field.get(b)); } catch (NoSuchMethodException | SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}class B{ private int count; public void printCount() { System.out.println(count); } public void print(int a,int b) { System.out.println(a+b); } public void print(String a,String b) { System.out.println(a.toUpperCase()+","+b.toLowerCase()); }}6.通過反射了解集合泛型 的本質;/** * 集合泛型 的本質是編譯期起檢查作用的.而反射是在運行期進行的,自然就繞過了編譯期的檢查. * @param args */ public static void main(String[] args) { ArrayList<String> list1=new ArrayList<>(); ArrayList list2=new ArrayList(); list2.add("hello"); list1.add("hello"); list2.add(20); Class cls1=list1.getClass(); Class cls2=list2.getClass(); //運行期時,list1&list2的類的類型沒有區別;即不存在了泛型這個檢查; System.out.println(cls1==cls2); try { Method method=cls1.getDeclaredMethod("add",Object.class); method.invoke(list1 , 20); System.out.println(list1.size()); //取出時仍然要用反射,繞過編譯期的泛型檢查. //所以泛型不僅要檢查放的數據類型是否符合泛型,還要檢查拿出的數據類型是否符合泛型; Method method2=cls1.getDeclaredMethod("get", int.class); System.out.println(method2.invoke(list1, 1)); /*for(int i=0;i<list1.size();i++){ System.out.println(list1.get(i)); }*/ /*Method[] eMethods=cls1.getDeclaredMethods(); for (Method method : eMethods) { System.out.print(method.getName()+";"); Class[] paraTypes = method.getParameterTypes(); for (Class class1 : paraTypes) { System.out.print(class1.getName()); } System.out.println(); }*/ } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
新聞熱點
疑難解答