java反射 day--03(上)
阿新 • • 發佈:2018-12-18
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();//獲取變數型別呢
}