2011-08-19 92 views
1

我一直在研究Java反射。這是維基百科http://en.wikipedia.org/wiki/Reflection_(computer_programming爲例):Java反射 - 通過類名稱字符串獲取級別

// Without reflection 
new Foo().hello(); 

// With reflection 
Class<?> cls = Class.forName("Foo"); 
cls.getMethod("hello").invoke(cls.newInstance()); 

我覺得這有點違反直覺的,因爲該方法是創建一個實例之前調用。

反思當然可以用來稱呼遊戲級別,特別是如果有數百人。

編輯 - 一些解決方案:

這裏是反射的一個簡單的例子,其在Android上工作:

try {     
     Class<?> clazz = Class.forName("com.test.Foo");     
     clazz.newInstance();    
    } catch (Exception e) {     
     throw new IllegalStateException(e);    
    } 

和類文件

public class Foo { 

    Foo(){ 
     hello();  
    } 

    private void hello() { 
     Log.e("FOO", "Hello!"); 
    } 
} 

假設一個要調用的活動通過反思:

Activity activity; 
try {     
    Class<?> clazz = Class.forName("com.test.MyLevelActivity");     
    activity = (Activity) clazz.newInstance();    
} catch (Exception e) {     
    throw new IllegalStateException(e);    
} 
startActivity(new Intent(this,activity.getClass())); 

假設包含數據,並通過反射的方法應該是「裝」的水平:

Level currentLevel; 
    try {     
     Class<?> clazz = Class.forName("com.test.Level_1_1");     
     currentLevel = (Level) clazz.newInstance();    
    } catch (Exception e) {     
     throw new IllegalStateException(e);    
    } 

    String levelName = currentLevel.getLevelName(); 
    String result = Integer.toString(currentLevel.processData(3, 7)); 

    Toast.makeText(this, levelName + " result= " + result, Toast.LENGTH_LONG).show(); 

這裏是類:

public abstract class Level { 

    public abstract String getLevelName(); 

    public abstract int processData(int a, int b); 

} 


public class Level_1_1 extends Level{ 
    private String levelName = "level 1.1"; 

    public String getLevelName(){ 
     return levelName; 
    } 

    public int processData(int a, int b) { 
     return a * b; 
    } 
} 
+0

您是否試圖編寫您發佈的代碼的第二小節?它有用嗎?它編譯了嗎? – luketorjussen

+0

Class類的方法已經定義好了,它肯定沒有hello()方法。泛型不會改變這種情況。當然,您可以將新實例投射到您的類並調用其方法 - 如下所示: Foo foo =(Foo)cls.newInstance(); foo.hello(); 但是因此你的代碼將取決於Foo類。而使用反射來進行方法調用的想法是避免這種依賴。 –

回答

3

這裏

foo.hello(); 

不能工作,富只是一個對象,沒有一個方法,你好()。

不熟悉的事情可能看起來違反直覺,但最終新的成語會變得自然。只需採用標準方法即可。

爲了理解它,認爲方法定義不是對象的一部分,你爲類編寫一次方法,它獨立於任何給定的對象「生活」。因此,班級說「嘿方法,在這個對象的背景下應用自己,他是我們中的一員」是非常合理的。

+0

新Foo()。hello();做?也許這個地方對我來說不清楚?順便說一句,我喜歡你最後一句話! – Lumis

+0

新的Foo()使Foo,Foo的可以hello()。類 foo被編譯器看作是一個更一般的東西,它並沒有意識到它碰巧是一個Foo,所以它不知道它可以hello()。 – djna

+0

是的,這一切都是合理的:) – Lumis

7

我覺得這有點違反直覺的,因爲該方法在創建實例之前調用

對不起,不這麼認爲。在傳遞給「invoke」之前,方法參數首先被評估,因此最終將Foo類的「新」實例傳遞給Method類的「invoke」方法。此外,如果您想知道爲什麼要在方法對象上調用「invoke」,那是因爲對於給定的類,您只需創建一次對象,所有後續調用將取決於對象的「狀態」而不是「方法」被調用。

+0

我明白了,但每個初學者都面對面和類繼承會讓你頭痛的說出你的意思;) – Lumis

2

這不是很清楚你的意思,但這有幫助嗎?

Class<?> cls = Class.forName("Foo"); 
Method method = cls.getMethod("hello"); 

Object instance = cls.newInstance(); 
method.invoke(instance); 
+0

謝謝你。它確實需要大量的try/catch語句,並且類字符串必須是包含的全名。 – Lumis

1

您不是首先調用方法。你只是定義了方法然後調用它。另外,在我們實際輸入invoke之前,cls的實例被創建。我發現反射是一個在Java中非常有用的API,幾乎所有在Java上工作的framworks都可以使用,如struts,log4j等。在反思中,你總是定義你想調用的方法,然後才能處理你想要操作的實際對象。

希望這會有所幫助!

相關問題