- Class類的使用
1.在面向對象的世界里洪燥,萬事萬物皆對象類是(哪個類的對象呢)誰的對象呢?
類是java.lang.Class類的實例對象
2.怎么表示Class類的實例對象呢稚疹?
public class ClassDemo1{
public static void main(String[] args){
//Foo的實例對象如何表示
Foo foo1 = new Foo();//foo1就表示出來了
//Foo這個類 也是一個實例對象,是Class類的實例對象,如何表示呢钾恢?
//任何一個類都是Class的實例對象翘鸭,這個實例對象有三種表示方式
//第一種表示方式--->實際在告訴我們任何一個類都有一個隱含的靜態(tài)成員變量class
Class c1 = Foo.class;
//第二種表達方式 已知該類的對象通過getClass方法
Class c2 = foo1.getClass();
//第三種表達方式
Class c3 = null;
try{
c3 = Class.forName("com.imooc.reflect.Foo");//(參數為全稱即包名)
}catch(ClassNotFoundException e){
e.printStackTrace();
}
//c1,c2,c3表示了Foo類的類類型(class type)
//表示Foo類本身就是Class類的實例對象滴铅,這個對象我們稱之為該類的類類型
//c1,c2,c3都代表了Foo類的類類型就乓,一個類只可能是Class的一個實例對象汉匙,所以他們都是相等的
//我們完全可以通過類的類類型創(chuàng)建該類的對象實例--->通過c1 or c2 or c3 創(chuàng)建Foo的實例
try{
Foo foo = (Foo)c1.newInstance();//前提是要有無參數的構造方法
foo.print();//調用foo類的print方法
}catch{InstantiationException e}{
e.printStackTrace();
}
}
}
class Foo{
void print(){
System.out.printIn("foo");
}
}
3.Class類動態(tài)加載類的用法
首先學會區(qū)分什么是動態(tài)加載,什么是靜態(tài)加載
Class.forName("類的全稱")
- 不僅表示了類的類類型生蚁,還代表了動態(tài)加載類
- 請大家區(qū)分編譯噩翠,運行
- 編譯時刻加載類是靜態(tài)加載類,運行時刻加載類是動態(tài)加載類
new 創(chuàng)建對象是靜態(tài)加載類邦投,在編譯時刻就需要加載所有的可能使用到的類
靜態(tài)加載的弊端是伤锚,類名一旦更改,我們之前編寫的程序中所有用到該類名的地方都要修改志衣,這樣的程序耦合性很高屯援,擴展性就很差.
那么聰明的人就想到了一個辦法,就是動態(tài)加載蠢涝。用一個抽象的雷鳴代替具體的類名玄呛,或者一個統一的接口代替具體的方法,這樣一來程序運行的時候就在加載相應的類或接口即可和二。
擴展的功能(新功能就代表一個新類)只要implement這個類即可實現功能的擴展徘铝。
try{
//動態(tài)加載類,在運行時刻加載
Class c = Class.forName(args[0]);
//通過類類型惯吕,創(chuàng)建該類的對象
OfficeAble oa=c.newInstance();//OfficeAble定義的功能類型接口
oa.start();
}catch(Exception e){
e.printStackTrace();
}
4.基本的數據類型 void關鍵字 都存在類類型
Class c1 = int.class;
Class c2 = String.class;
Class c3 = double.class;
Class c4 = Double.class;
Class c5 = void.class;
System.out.println(c1.getName());
System.out.println(c2.getName());
System.out.println(c2.getSimpleName());//不包含包名的類的名稱
System.out.println(c5.getName());
5.Class類的基本API操作
//可以獲取任意一個類的全部信息
publicclass ClassUtil{
/**
*打印類的信息惕它,獲取類的成員函數
*@param obj 該對象所屬類的信息
public static void printClassMethodMessage(Object obj){
//要獲取類的信息 首先要獲取類的類類型
Class c = obj.getClass();//傳遞的是哪個子類的對象 c就是該子類的類類型
//獲取類的名稱
System.out.println("類的名稱是:"+c.getName());
/*
*Method類,方法對象
*一個成員方法就是一個Method對象
*getMethods()方法獲取的所有的public的函數废登,包括父類繼承而來的
*getDeclaredMethods()獲取的是所有該類自己聲明的方法淹魄,不問訪問權限
*/
Method[]ms = c.getMethods();//c.getDeclaredMethods()
for(int i = 0; i < ms.length;i++){
//得到方法的返回值類型的類類型
Class returnType = ms[i].getReturnType();
System.out.print(returnType.getName()+ " ");
//得到方法的名稱
System.out.print(ms[i].getName()+"(");
//獲取參數類型-->得到的是參數列表類型的類類型
Class[] paramTypes = ms[i].getParameterTypes();
for(Class class1:paramTypes){
System.out.print(class1.getName()+",")
}
System.out.println(")");
}
}
/**
*打印類的信息,獲取類的成員變量
*@param obj 改對象所屬類的信息
*/
public static void printFieldMessage(Object obj){
Class c = obj.getClass();
/*
*成員變量也是對象
*java.lang.reflect.Field
*Filed類封裝了關于成員變量的操作
*getFields()方法獲取的是所有的public的成員變量的信息
*getDeclaredFields獲取的是該類自己聲明的成員變量的信息
//Field[]fs = c.getFields();
Field[] fs = c.getDeclaredFields();
for(Field field : fs){
//得到成員變量的類型的類類型
Class fieldType = field.getType();
String typeName = fieldType.getName();
//得到成員變量的名稱
String fieldName = field.getName();
System.out.println(typeName+" " + fieldName);
}
}
/**
*打印對象的構造函數的信息
*@param obj
*/
public static void printConMessage(Object obj){
Class c = obj.getClass();
/*
*構造函數也是對象
*java.lang.Constructor中封裝了構造函數的信息
*getConstructors獲取所有的public的構造函數
*getDeclaredConstructors();得到所有的構造函數
*/
//Constructor[] cs = c.getConstructors();
Constructor[] cs = c.getDeclaredConstructors();
for(Constructor constructor : cs){
System.out.println(constructor.getName()+"(");
//獲取構造函數的參數列表-->得到的是參數列表的類類型
Class[] paramTypes = constructor.getParameterTypes();
for(Class class1 : paramTypes){
System.out.print(class1.getName()+",");
}
System.out.println(")");
}
}
}
-
方法的反射
1.如何獲取某個方法
方法的名稱和方法參數列表才能唯一決定某個方法
2.方法反射的操作
method.invoke(對象堡距,參數列表)public class MethodDemo1{ public static void main(String[] args){ //要獲取print(int,int)方法 //1.首先要獲取類的信息甲锡,獲取類的信息就要先獲取類的類類型 A a1 = new A(); Class c = a1.getClass(); /* *2.獲取方法 名稱和參數列表來決定 *getMethod獲取的是public的方法包括繼承來的 *getDelcaredMethod自己聲明的方法 */ try{ //Method m =c.getMethod("print",new Class[]{int.class,int.class}); Method m = c.getMethod("print",int.class,int.class); //方法的反射操作 //a1.print(10,20);方法的反射操作是用m對象來進行方法調用和a1.print調用的效果完全相同 //方法如果沒有返回值返回null,有返回值的返回具體的返回值需要強制轉換 //Object o =m.invoke(a1,new Object[]{10,20}); Object o = m.invoke(a1,10,20); System.out.println("============="); //獲取方法對象print(String,String) Method m1 = c.getMethod("print",String.class,String.class); //用方法進行反射操作 //a1.print("hello","WORLD"); o = m1.invoke(a1,"hello","WORLD"); Syystem.out.println("=====無參函數===="); //Method m2 = c.getMethod("print",new Class[]{}); Method m2 = c.getMethod("print"); //m2.invoke(a1,new Object[]{}); m2.invoke(a1); }catch(Exception e){ e.printStackTrace(); } } } class A{ public void print(){ System.out.println("helloworld"); } 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()); } }
成員變量的反射
構造函數的反射
Java類加載機制
//參考視頻地址 http://www.imooc.com/video/3725
總結:反射可以進行動態(tài)加載,繞過編譯羽戒,提高了代碼的靈活性缤沦,在java的框架中應用較多。