2010-01-20 26 views
3

如何在Java ME中獲得類實例的超類。也就是說,在CLDC 1.1中提供有限功能的Class.getSuperclass()功能?Java ME上的Class.getSuperclass()替換?

我想要做的就是讓抽象的超類做這樣的事情:

public Styler getStylerForViewClass(Class clazz) { 
    Styler s = stylers.get(clazz); 
    if (s == null) { 
    for (Class c = clazz; s == null; c = c.getSuperclass()) { 
     if (c == Object.class) { 
     throw new IllegalArgumentException("No Styler for " + clazz.getName()); 
     } 
     s = createStylerForViewClass(c); 
    } 
    stylers.put(clazz, s); 
    } 
    return s; 
} 
public Styler createStylerForViewClass(Clazz clazz) { 
    if (clazz == View.class) { 
    return new DefaultStyler(); 
    } else { 
    return null; 
    } 
} 

子類可以再添加特這樣的:

public Styler createStylerForViewClass(Class clazz) { 
    if (clazz == SpecialView.class) { 
    return new SpecialStyler(); 
    } else { 
    return super.createSylerForViewClass(clazz); 
    } 
} 
+0

是否有所有視圖類的通用超?這些方法('createStylerForViewClass'和'getStylerForViewClass')是否屬於那個超類?如果是這樣,那麼爲什麼需要'clazz'參數? – finnw

+0

是的,他們有一個共同的超類,但你不會實現這些方法。只需使用自己的類調用getStylerForViewClass()以獲得最適合他們的樣式器。 – PeyloW

回答

1

正如您已經發現的那樣,MIDP不提供獲取類的超類的方法,也不提供用於枚舉應用程序中的所有類的方法。

所以你所能做的就是自己跟蹤類層次結構。

擁有一個共同的超使它稍微容易些,因爲你可以有新的對象添加自己的類全局類集合(如果尚未存在)在超類的構造函數:

abstract class View { 
    protected View() { 
     classHierarchy.add(this.getClass()); 
    } 
} 

,但不幸的是這將不適用於抽象類,因爲沒有創建任何實例。

跟蹤一個已知子類的超類/子類關係很容易。例如爲:

import java.util.Enumeration; 
import java.util.Hashtable; 
import java.util.Vector; 

public class ClassHierarchy { 
public ClassHierarchy() { 
    childToParentMap = new Hashtable(); 
    parentToChildMap = new Hashtable(); 
    parentToChildMap.put(Object.class, new Vector()); 
} 

public boolean addClass(Class toAdd) { 
    if (toAdd.isInterface()) return false; 
    if (toAdd.equals(Object.class)) return false; 
    if (childToParentMap.get(toAdd) != null) return false; 

    addClassBelow(toAdd, Object.class, new Vector()); 
    return true; 
} 

public Class getParent(Class subclass) { 
    return (Class) childToParentMap.get(subclass); 
} 

private void addClassBelow(Class toAdd, Class parent, Vector initialChildren) { 
    Vector children = (Vector) parentToChildMap.get(parent); 
    Class reparented; 
    do { 
    reparented = null; 
    for (Enumeration childEnum = children.elements(); 
     childEnum.hasMoreElements(); 
     ) { 
    Class child = (Class) childEnum.nextElement(); 
    if (child.isAssignableFrom(toAdd)) { 
    addClassBelow(toAdd, child, initialChildren); 
    return; 
    } else if (toAdd.isAssignableFrom(child)) { 
    children.removeElement(child); 
    initialChildren.addElement(child); 
    childToParentMap.put(child, toAdd); 
    // Guard against concurrent modification 
    reparented = child; 
    break; 
    } 
    } 
    } while (reparented != null); 

    children.addElement(toAdd); 
    childToParentMap.put(toAdd, parent); 
    parentToChildMap.put(toAdd, initialChildren); 
} 


private Hashtable childToParentMap; 

private Hashtable parentToChildMap; 
} 

但是,這可以「錯過」以後添加中間類,例如如果你有這些類:

Object >= View >= A >= B >= C 

,並添加AC樹,並要求其爲C超它會給你A,如果你後來添加B它將取代AC超,但是直到錯誤的樣式文件返回了C的某些實例。

所以我認爲你必須添加限制,祖先類(它們爲其定義的樣式)必須首先添加到樹中。可能來自覆蓋createStylerForViewClass的類的靜態初始化器塊,或者視圖類本身的靜態初始化器。

我沒想到一個其他邪惡的黑客,但我真的不能推薦一下:

  • View構造函數中,創建一個新的Exception,但不要把它。
  • 暫時交換System.err爲自己的作家寫入到ByteArrayOutputStream
  • 呼叫printStackTrace()異常
  • 上恢復System.err其原始值
  • 解析從ByteArrayOutputStream堆棧跟蹤。中間類的構造函數的名稱將在堆棧跟蹤中。現在你可以使用Class.forName()來查找它們並將它們添加到樹中。
+0

足夠好,可以使用。我想我會要求所有的View子類調用'registerClass(MyClass.class)'作爲靜態初始化器。很難執行,但足夠好。你的醜陋的黑客攻擊是不可行的,因爲'System.err'如果'final'在CLDC,我已經考慮過這個問題,以及:(。 – PeyloW

+0

沒有標準的方式來獲得在J2ME堆棧跟蹤。無論是在運行這個仿真器或使用Symbian手機及其「重定向://」GCF協議。 –

1

你有兩個選擇:

如果您知道超類屬於有限集合,您可以調用instanceof或使用Class.isInstance()方法。

或者,你可以有一個預處理程序在你的代碼上運行,並創建一個單獨保存的數據結構來保存你的類信息。可能即使是自定義doclet也可以做到這一點。輸出可以是描述結構的文本或二進制文件:

ClassA:SuperClass 
ClassB:AnotherSuperClass 
etc. 

通知你可能有問題,通過這種方式混淆。

+0

我個人嘗試堅持'instanceof'運營商,並嘗試利用有限的一組類。我真的不喜歡使用的預處理器,因爲它們可以讓你的代碼更加晦澀 – Malcolm

+0

我不打算用預處理程序處理的文字。請參閱回覆以進行澄清。 –

+0

因爲我正在實施框架,所以我無法知道這些超類是什麼。我無法控制客戶想要使用什麼樣式的客戶端。我只是想創建一個靈活和懶惰的加載方法來爲任何給定的類提取正確的樣式。 – PeyloW