簡體   English   中英

用於重載方法的Java動態轉換

[英]Java dynamic casting for overloaded methods

我正在嘗試創建一個函數,我可以傳遞將放入ContentValues的名稱和值。 我遇到的問題是我試圖允許一次傳遞更多的一個鍵/值對,因此鍵可以是一個字符串數組,但值必須是對象,而ContentValues.put()不是允許對象,需要將它們轉換為String,Double,Float等。有沒有辦法可以確定對象的類型並將其強制轉換,以便調用正確的put()? 下面是一個有效的方法,但它要求我為每種可能的值添加一個if。

 public long create(String[] names, Object[] values) {
        ContentValues initialValues = new ContentValues();

        for (int i = 0; i < names.length; i++)
        {
            String type = values[i].getClass().getName();
            if (type.equals("java.lang.Double"))
            {
                initialValues.put(names[i], (Double)values[i]);
            }
            else if (type.equals("java.lang.String")) {
                initialValues.put(names[i], (String)values[i]);
            }
            else
            {
                throw new InvalidParameterException("Unable to convert type:"+type);
            }
        }

        return mDb.insert(this.getTableName(), null, initialValues);
    }

您的方法是正確的,但您應該使用instanceof而不是getClass().getName() 即:

if (values[i] == null) {
  initialValues.putNull(names[i]);
} else if (values[i] instanceof Boolean) {
  initialValues.put(names[i], (Boolean)values[i]);
} else if (values[i] instanceof Byte) {
  initialValues.put(names[i], (Byte)values[i]);
} else if (values[i] instanceof Double) {
  initialValues.put(names[i], (Double)values[i]);
} else if (values[i] instanceof Float) {
  initialValues.put(names[i], (Float)values[i]);
} else if (values[i] instanceof Integer) {
  initialValues.put(names[i], (Integer)values[i]);
} else if (values[i] instanceof Long) {
  initialValues.put(names[i], (Long)values[i]);
} else if (values[i] instanceof Short) {
  initialValues.put(names[i], (Short)values[i]);
} else if (values[i] instanceof String) {
  initialValues.put(names[i], (String)values[i]);
} else if (values[i] instanceof byte[]) {
  initialValues.put(names[i], (byte[])values[i]);
} else if (values[i] instanceof ContentValues) {
  initialValues.putAll(names[i], (ContentValues)values[i]);
} else {
  throw new IllegalArgumentException(
      "can't put " + values[i].getClass().getName() + " in ContentValues.");
}

另一個選擇是使用反射,但我認為反射是最后的手段。

如果ContentValues不是final另一個選項是擴展它並添加一個接受Object的方法。

您有兩種選擇:

  1. 像你一樣創建一個if-else塊列表。 如果你這樣做我不會那樣做。 我會做“ob instanceof String”而不是; 要么
  2. 使用反射為傳入的類型找到正確的方法。

要考慮的一件事是空值。 如果傳入的值為null,則沒有類,因此您無法確定類型,如果這與您的使用相關。

IMO,這就像你可以做到的那樣整潔,高效和正確。 編譯器可能可以優化類型轉換,但這並不重要。

public long create(String[] names, Object[] values) {
    ContentValues initialValues = new ContentValues();
    for (int i = 0; i < names.length; i++) {
        Object v = values[i];
        if (v instanceof Double) {
            initialValues.put(names[i], (Double) v);
        } else if (v instanceof String) {
            initialValues.put(names[i], (String) v);
        } else {
            // You could test for v == null here ... otherwise you'll
            // get an NPE 
            throw new InvalidParameterException(
                    "Unable to convert type: " + v.getClass());
        }
    }
    return mDb.insert(this.getTableName(), null, initialValues);
}

一些說明:

  1. 編輯:一般來說,你可能不想測試一個確切的類C.更有可能你想測試“C或C的子類”。 您無法使用類名對此進行測試。 為此使用instanceof
  2. 如果您測試類名,請確保使用正確的名稱。 例如, Double.class.getName()實際上給出了"java/lang/Double"而不是"java.lang.Double"
  3. 除了比instanceof更慢之外,比較類名並不總能給出正確的答案。 如果某些東西正在進行類加載器技巧,則不同的類可以具有與getName()getCanonicalName()報告的相同的名稱。
  4. 避免使用反射來做這樣的事情。 它不可避免地會變慢,編譯器將無法承擔很多錯誤。

可以說,ContentValues應該提供一個putObject()方法,就像你要編寫的那樣。 我可能傾向於使用提供該方法的類來擴展或以其他方式包裝ContentValue,從而使代碼可重用。

您正在使用的if / else方法可能會令人煩惱地平淡無奇,但會明確說出您的意思,並且生成簡單,可維護的代碼是我的優先事項。 使用反射也是可能的,但實施起來會更復雜。 我會堅持你正在做的事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM