我一直以為類的私有構造函數、屬性、方法除了類自身其他類是無法通路的,前幾天正好學習Spring架構,在學習Spring架構基礎 Bean包時,寫了一個簡單的例子,類似如下:
package study.spring.bean;
public class SimpleBean
{
private String beanName;
private SimpleBean() {
System.out.println( " SimpleBean " );
}
public String getBeanName()
{
return beanName;
}
public void setBeanName(String beanName)
{
this .beanName = beanName;
}
}
發現居然也能調用成功,當時很驚訝,反射機制平時在以前的項目中也常使用,但不能構造隻有私有構造函數的類。
自己做了一個簡單例子:
package study.spring.bean;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;來源:-計算機二級考試
public class SimpleTest
{
public static void main(String[] args)
{
// TODO Auto-generated method stub
try
{
Constructor[] cts=Class.forName("study.spring.bean.SimpleBean").getDeclaredConstructors();
for(int i=0;i
cts[i].newInstance(null);
}
}來源:-計算機二級考試
catch (SecurityException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (ClassNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IllegalArgumentException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (InstantiationException 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();
}
}
}
也是如我所想 抛出java.lang.IllegalAccessException異常,當時就懷疑Spring架構是否使用反射的一些特性,後來查了相關文檔才知道原因何在:
實際上java在反射建立一個類的執行個體時,預設會檢測是否符合相關安全,該檢測開關可以關閉。
Constructor、Field、Method都是繼承于AccessibleObject,對應執行個體調用setAccessible(true)就關閉該開關
如上面的例子,在代碼 cts[i].newInstance(null);行前調用上述方法: cts[i].setAccessible(true);
這樣就可以建立隻有構造函數的執行個體、調用私有構造方法,通路類的私有屬性。
呵呵,這樣好像java安全性就大大降低.如果你非常注重應用的安全性,java當然考慮到這方面,你可以在JVM啟動參數增加 -Djava.security.manager 啟用安全管理器,如果有該參數,它将檢測正在關閉接入檢測的代碼是否許可了這樣做,上述代碼執行時會抛出 java.security.AccessControlException異常。