重载方法的Java动态转换

重载方法的Java动态转换,java,Java,我试图创建一个函数,在这个函数中,我可以传递名称和值,这些名称和值将被放入一个函数中。我遇到的问题是,我试图允许一次传递多个键/值对,因此键可以是字符串数组,但值必须是对象和ContentValue。put()不允许对象,它们需要转换为String、Double、Float、,等等。是否有一种方法可以确定对象的类型并强制转换它,以便它调用正确的put()?下面是一个有效的方法,但它要求我为每种可能的值类型添加一个if public long create(String[] names, Obj

我试图创建一个函数,在这个函数中,我可以传递名称和值,这些名称和值将被放入一个函数中。我遇到的问题是,我试图允许一次传递多个键/值对,因此键可以是字符串数组,但值必须是对象和ContentValue。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);
    }
public长创建(字符串[]名称,对象[]值){
ContentValues initialValues=新的ContentValues();
for(int i=0;i
您有两个选择:

  • 创建一个if-else块列表,就像您正在做的那样。如果你那样做,我就不会那样做了。我会改为“ob instanceof String”;或
  • 使用反射查找传入类型的正确方法

  • 一个要考虑的是空值。如果传入的值为null,则没有类,因此您无法确定类型(如果该类型与您的使用相关)。

    ContentValues应该按照您将要编写的内容提供一个putObject()方法。我可能倾向于使用提供该方法的类来扩展或包装ContentValue,从而使代码可重用


    您正在使用的if/else方法可能会让人觉得乏味,但会明确地说出您的意思,而生成简单、可维护的代码是我的首要任务。使用反射也是可能的,但实现起来更复杂。我会坚持你所做的

    您的方法是正确的,尽管您应该使用
    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.");
    }
    

    另一个选择是使用反射,但我认为反射是一种最后的方法。< /P>


    如果
    ContentValues
    不是
    final
    的话,另一个选择是对其进行扩展,并添加一个方法,该方法采用
    对象
    这是尽可能简洁、高效和正确的,依我看。编译器可以优化类型转换,但这并不重要

    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);
    }
    
    public长创建(字符串[]名称,对象[]值){
    ContentValues initialValues=新的ContentValues();
    for(int i=0;i
    一些注意事项:

  • 编辑:一般来说,您可能不想测试确切的C类。您更可能想测试“C或C的子类”。您不能使用类名来测试它。为此使用
    instanceof
  • 如果测试类名,请确保使用正确的类名。例如
    Double.class.getName()
    实际上给出了
    “java/lang/Double”
    而不是
    “java.lang.Double”
  • 比较类名不仅比
    的instanceof
    慢,而且并不总能给出正确的答案。如果某个类正在使用类加载器技巧,则不同的类可以具有由
    getName()
    getCanonicalName()
    报告的相同名称
  • 避免对这样的事情使用反射。它不可避免地会变慢,而且编译器将无法发现您的许多错误

  • 为什么你认为反思是一种最后的方法?在我看来这是个好方法。为什么要使用instanceof?primitive的包装始终是最终的。。不需要检查子类dfa:instanceof更一般、更简洁。为什么不使用instanceof?@Asa:除了成本高昂之外,反射通常会导致代码更难维护,并且会破坏静态分析(包括编译时类型检查、重构工具等)。一般来说,如果不使用反射就可以完成同样的事情,那么不要使用反射。为什么要使用instanceof?primitive的包装始终是最终的。。不需要检查子类在这种情况下,instanceof应该比String.equals()调用快。一般来说,我们不能假设所有类型都是最终的。事实上,如果涉及类加载器,比较类名可能不足以区分类。您也可以对原语而不是instanceof执行(object.getClass()==String.class)。这可能是被暗示的,而不是.equals()。我是为android编写的,据我所知它使用Java5,但我对Java是新手,我不知道如何验证这一点。