1. 程式人生 > >java反射 day--03(上)

java反射 day--03(上)

java的反射機制(菜鳥隨筆)

java反射具體實現的功能有3種

1.執行時建立物件

    //以String類為例子
    CLass cs_Str=Class.forName("java.lang.String");
    Stirng str=(String)cs_Str.newInstance();
    //提示newInstance()方法已經被棄用 可以用如下方法來替代
     String str=(String)cs.getDeclaredConstructor().newInstance();
   

2.執行時呼叫物件方法

         //反射呼叫靜態類的方法。
Class<Math> csStr=Math.class; Method method_sin=csStr.getMethod("sin",double.class); //靜態類不例項化 System.out.println("結果:"+ method_sin.invoke(null,1.0)); //反射呼叫非靜態類 呼叫無參建構函式; Class<Random> randomClass=Random.class; Method method_nextInt=
randomClass.getMethod("nextInt", int.class); System.out.println( "使用無參建構函式:"+ method_nextInt.invoke(randomClass.getDeclaredConstructor().newInstance(),10) ); //使用帶引數的建構函式建立物件並呼叫方法 Class<Random> randomClass1=
Random.class; Method method_nextInt1=randomClass1.getMethod("nextInt", int.class); System.out.println( "使用帶參建構函式:"+ method_nextInt1.invoke(randomClass.getDeclaredConstructor(long.class).newInstance(1),10) );

3.獲取一個類的所有成員以及方法

 Class cs = Class.forName("java.lang.String");
                //獲取所有方法成員
               Method[] methods= cs.getMethods();
               Field[] fields= cs.getDeclaredFields();

               //獲取簡單類名
               System.out.println("類名"+cs.getSimpleName());

               for(Method method:methods)
               {
                   System.out.println("方法名:"+method.getName());
               }

               System.out.println("成員變數");
               for(Field field:fields)
               {
                   System.out.println("變數型別:"+field.getType()+"  變數名:"+field.getName());
               }

getDeclared…獲取定義的方法/欄位,包含公有和私有 私有的如果想要訪問那麼需要手動設定訪問許可權為true

-------------簡單測試類
public class MyTest {
    private String mimi="祕密";
    private void show()
    {
        System.out.println("我真不想告訴你:"+mimi);
    }
}
-------------實驗程式碼
    Class<MyTest> myTestClass=MyTest.class;
    MyTest myTest=myTestClass.getDeclaredConstructor().newInstance();
    //獲取私有欄位祕密
    Field field_mimi=myTestClass.getDeclaredField("mimi");
    //設定訪問許可權為可訪問
    field_mimi.setAccessible(true);
    //列印私有欄位:mimi
    System.out.println(field_mimi.get(myTest));
    //修改私有欄位的值
    field_mimi.set(myTest,"好了,這已經不是祕密了");
    //獲取私有方法
    Method method=myTestClass.getDeclaredMethod("show");
    //設定訪問許可權
    method.setAccessible(true);
    //呼叫私有方法
    method.invoke(myTest);

輸出結果

祕密
我真不想告訴你:好了,這已經不是祕密了

程序完成,退出碼 0

4.反射和動態代理


            //建立介面
            public interface ItestAble {
                 public void doSomething();
            }
            //實現介面
            public class TestImpl implements  ItestAble{

              @Override
             public void doSomething() {
                    System.out.println("幹了點事");
              }
            }
            //實現InvacationHandler介面



            //建立代理物件,使用Proxy類中的靜態方法newProxyInstance得到一個動態的代理物件,讓代理物件來實現某些事
            Class testClass= Class.forName("org.test.jinTest.TestImpl");
            TestImpl testImpl=(TestImpl) testClass.getDeclaredConstructor().newInstance();
            TestinvocationHandler testinvocationHandler=new TestinvocationHandler(testImpl);
            ItestAble itestAble=  (ItestAble)Proxy.newProxyInstance(testClass.getClassLoader(),testClass.getInterfaces(),testinvocationHandler);
            itestAble.doSomething();

            

輸出結果

做點準備
幹了點事
幹完收工

  看代理時想起來,學java好像沒用到過委託,找了找好像java並沒有支援委託型別,懷念咦哈。
 java中類似的是:將引數設定成介面型別,傳入實現類。

java內省

 簡述:內省(IntroSpector)是Java 語言對 JavaBean 類屬性、事件的一種預設處理方法。(通過反射來操作JavaBean)。
 JavaBean簡單理解車:成員都是私有通過get();Set()方法來獲取和設定。

簡單帶過:

//通過類名得到相應的BeanInfo物件
BeanInfo info = Introspector.getBeanInfo(類名.class);
//獲取成員變數陣列
PropertyDescriptor[] propertyDescriptors = info.getPropertyDescriptors();

for(PropertyDescriptor p:propertyDescriptors)
{
    p.getReadMethod();//獲取get方法;
    p.getWriteMethod();//獲取set方法
    p.getName();//獲取變數名
    p.getPropertyType();//獲取變數型別呢
}