㈠ java反射機制怎樣調用類的私有方法
為了一看就懂,請看下面的示例(假設調用 MyTest類的私有方法 privateMethod()):
publicclassReflectionTest{
(Objectobj)throwsSecurityException,NoSuchMethodException,IllegalArgumentException,IllegalAcces***ception,InvocationTargetException{//核心代碼加粗
Classcls=obj.getClass();
//獲得類的私有方法
Methodmethod=cls.getDeclaredMethod("privateMethod",null);
method.setAccessible(true);//沒有設置就會報錯
//調用該方法
method.invoke(obj,null);
}
publicstaticvoidmain(Stringargs[])throwsSecurityException,IllegalArgumentException,NoSuchMethodException,IllegalAcces***ception,InvocationTargetException{
setObjectColor(newMyTest());
}
}
//測試類
classMyTest{
publicvoidsetMyTest(){
System.out.println("setMyTest");
}
/**
類的私有方法
**/
privatevoidprivateMethod(){
System.out.println("調用了privateMethod");
}
}
㈡ java反射訪問私有方法的的問題
java的反射可以繞過訪問許可權,訪問到類的私有方法和成員。可能這點會引起安全性的討論。反射的使用幫助解決很多復雜的問題,其運行時的類型檢查,動態調用,代理的實現等,反射為我們寫程序帶來了很大的靈活性,很多功能都是基於反射。
利用反射還可以訪問內部類、匿名內部類的私有屬性。
用java自帶的java -private 類名 反編譯命令可以查看類的完整定義。(參考think in java)
下面舉例子說明。首先定義一個介面
Java代碼
public interface Ref {
public void f();
}
public interface Ref {
public void f();
}
介面的實現類
Java代碼
public class RefImpl implements Ref {
//實現介面方法
public void f() {
System.out.println("public method f()");
}
void g(String args){
System.out.println("package method g():" + args);
}
private void w(){
System.out.println("private method w()");
}
}
public class RefImpl implements Ref {
//實現介面方法
public void f() {
System.out.println("public method f()");
}
void g(String args){
System.out.println("package method g():" + args);
}
private void w(){
System.out.println("private method w()");
}
}
測試類
Java代碼
public class TestRef {
public static void main(String[] args) {
Ref ref = new RefImpl();
System.out.println(ref.getClass().getSimpleName()); //RefImpl類型
ref.f(); //調用介面方法
// ref.g(); //向上轉型後實現類添加的方法不能調用
if(ref instanceof RefImpl){
RefImpl ref1 = (RefImpl)ref; //類型識別後轉型
ref1.g("zhouyang");
// ref1.w(); //私有方法不能訪問
}
//通過反射調用方法
try {
Ref ref2 = new RefImpl();
Method m = ref2.getClass().getDeclaredMethod("f");
Method m1 = ref2.getClass().getDeclaredMethod("g", String.class);//有參的方法
Method m2 = ref2.getClass().getDeclaredMethod("w");
System.out.println("==============");
m.invoke(ref); //調用方法f()
m1.invoke(ref, "yangzhou");
m2.setAccessible(true);///調用private方法的關鍵一句話
m2.invoke(ref);
} catch (Exception e) {
e.printStackTrace();
}
//java的javap反編譯能夠查看類的信息,-private 開關能夠打開所有信息
//javap -private 類名 類必須是編譯成.calss 文件
//利用反射訪問私有成員,改變私有成員值,但是final域可以訪問不可改變
PrivateField pf = new PrivateField();
// ps.ss; //私有成員不能訪問
//列印原來的成員值
pf.print();
try {
//反射訪問和改變原來值
Field[] f = pf.getClass().getDeclaredFields();
for(int i=0;i<f.length;i++){
f[i].setAccessible(true);
System.out.println(f[i].getType());//列印欄位類型
System.out.println(f[i].get(pf)); //列印值
if("ss".equals(f[i].getName())){
f[i].set(pf, "hehe"); //修改成員值
}else{
f[i].setInt(pf, 55);
}
}
//重新列印修改後的成員值,final域值不變
pf.print();
} catch (Exception e) {
e.printStackTrace();
}
/*列印輸出的結果
* RefImpl
public method f()
&nb
㈢ 既然Java反射可以訪問和修改私有成員變數,那封裝成private還有意義么
你沒發現反射訪問是很費力嗎?,private的意義就在於沒想讓人訪問,而JAVA反射的開發在於實現這個功能而已,其實在開發之初也沒想到你用反射只是為了訪問一個私有的變數。
㈣ java反射調用private方法
Java程序不能訪問持久化類的private方法,但是利用JAVA的反射機制可以實現調用,代碼如下:
<spanstyle="font-size:14px;">
importjava.lang.reflect.InvocationTargetException;
importjava.lang.reflect.Method;
publicclassReflectDemo{
publicstaticvoidmain(String[]args)throwsException{
Methodmethod=PackageClazz.class.getDeclaredMethod("privilegedMethod",newClass[]{String.class,String.class});
method.setAccessible(true);
method.invoke(newPackageClazz(),"452345234","q31234132");
}
}
classPackageClazz{
privatevoidprivilegedMethod(StringinvokerName,Stringadb){
System.out.println("---"+invokerName+"----"+adb);
}
}
</span>
#程序輸出結果為:---452345234----q31234132
㈤ Java反射 在只知道類名的情況下,怎樣給其中的私有屬性賦值
利用反射能
//假設類名為A
//實例化類
Ap=newA();
//獲取class
Classc=p.getClass();
//獲取該類所有的欄位
Field[]fields=c.getDeclaredFields();
//遍歷賦值
for(inti=0;i<fields.length;i++){
StringfiledName=fields[i].getName();
//AccessibleTest類中的成員變數為private,故必須進行此操作
fields[i].setAccessible(true);
//判斷類型
Class<?>type=fields[i].getType();
//獲取欄位類型
StringtypeName=type.getName();
System.out.println(type.getName());
//對欄位進行賦值第一個參數為對象引用第二個參數為要附的值
//如果為字元串類型
if("java.lang.String".equals(typeName)){
fields[i].set(p,"1");
}
//如果為日期類型
elseif("java.util.Date".equals(typeName)){
fields[i].set(p,newDate());
}
else{
fields[i].set(p,1);
}
}
//樓主我只是簡單的寫了下。可能還需要判斷欄位名稱以及其他類型什麼的。
最後希望樓主多看看java 文檔。