2012-06-11 2 views
1

У меня есть приложение, которое использует код, который создает различные типы объектов и структуры данных, возвращая их как экземпляры экземпляра, и хотел бы, чтобы общий способ установить, является ли какой-либо из этих объектов «пустым» (или null).Java global isEmpty() метод

(Это не вопрос дизайна, или о том, следует ли использовать такой метод, но вопрос оптимизации решения существующей потребности.)

Итак, вот простой идти:

public static boolean isEmpty(Object content) 
{ 
    if (content == null) 
    { 
     return true; 
    } 
    else if (content instanceof CharSequence) 
    { 
     return (((CharSequence)content).length() == 0); 
    } 
    else if (content instanceof Collection<?>) 
    { 
     return ((Collection<?>)content).isEmpty(); 
    } 
    else if (content instanceof Object[]) 
    { 
     return (((Object[])content).length == 0); 
    } 
    else // Use reflection (an exaggeration, for demo purposes) 
    { 
     try 
     { 
      Method isEmpty = content.getClass(). 
          getDeclaredMethod("isEmpty", (Class<?>[])null); 
      if (isEmpty != null) 
      { 
       Object result = isEmpty.invoke(content, (Object[])null); 

       if (result instanceof Boolean) 
       { 
        return (Boolean)result; 
       } 
      } 
     } 
     catch (Exception e) 
     { 
     } 
    } 

    return false; 
} 

Любые идеи для потенциальных улучшений с точки зрения производительности или покрытия?

Например, отражение может также использоваться для определения того, имеет ли объект метод length() или size(), вызывать его и видеть, равен ли результат 0. (В действительности отражение, вероятно, слишком много, но я включая его здесь для полноты.)

Есть ли класс верхнего уровня, который обычно используется, который имеет метод length() или size() вместо метода isEmpty() для включения в вышеуказанный случай, аналогично коллекции, которая имеет isEmpty()?

+7

С первого взгляда * использование * такого метода само по себе кажется плохим дизайнерским решением. Как это будет использоваться? –

+0

Используется для проверки «пустоты» объекта, возвращаемого не изменяемым методом, который создает множество различных типов данных. – PNS

+3

Почему? Если вы вызываете этот метод, вы, вероятно, уже знаете, какой объект вы ему передаете, просто вызовите 'isEmpty' на самом объекте и избавите себя от этой проблемы. – Jeffrey

ответ

5

Вместо уродливых экземпляров, разделите метод на несколько методов с тем же именем, но с разными аргументами. например

static boolean isEmpty(Object[] array) 
static boolean isEmpty(Collection collection) 
static boolean isEmpty(CharSequence cs) 

Вместо отражения, если вы действительно хотите иметь свой собственный интерфейс для специальных объектов, объявить этот интерфейс, а затем, для обеспечения согласованности с вышеизложенным, предлагаем статическую утилиту

static boolean isEmpty(IMayBeEmpty imbe); 
+0

Не только это, но затем вы можете включить некоторые из общих инструментов lang isEmpty. Уменьшение количества кода, который вы должны записать. –

+0

Тем не менее, он пахнет (не означает, что это не оправдано или неизбежно). Но это самое элегантное решение, о котором я могу думать. – ptyx

+0

@Jim Вы правы, что перегрузка лучше, чем использование instanceof, но поскольку объявленный тип возвращаемого объекта является Object, будет вызван только метод isEmpty() с аргументом Object. Описанный вами код «commons lang» относится к Apache Commons? – PNS

1

Этот метод в наименее решает вашу проблему с общей проблемой isEmpty (Object). Тем не менее, вы не получаете безопасность времени компиляции с этим, и вызов его без метода, существующего для запрашиваемого точного типа, приведет к ошибке выполнения. Обратите внимание, что класс MethodUtils - от apache commons-beanutils, хотя вы можете легко использовать отражение напрямую, но для простоты я использую beanutils здесь.

Метод «invokeExactcMethod» ищет статический метод в данном классе с заданным именем, которое имеет совместимые параметры передаваемого массива объектов. Поэтому, если тип среды выполнения объекта ArrayList, он будет искать isEmpty (ArrayList), затем isEmpty (AbstractList), а затем isEmpty (List). Затем он вызывает этот метод, если он может его найти, иначе он выдает исключение NoSuchMethodException.

public class MyUtility { 
    static boolean isEmpty(Object object) { 
    if (object == null) { 
     return true; 
    } 
    else { 
     try { 
     return MethodUtils.invokeStaticMethod(
        MyUtility.class, "isEmpty", new Object[]{object}); 
     } 
     catch (NoSuchMethodException e) { 
     throw new IllegalArgumentException(e); 
     } 
     catch (IllegalAccessException e) { 
     throw new IllegalArgumentException(e); 
     } 
     catch (NoSuchMethodException e) { 
     throw new RuntimeException(e); 
     } 
    } 
    } 
} 

«invokeExactStaticMethod» является более детерминированным и не использует совместимость присваивания, но точное соответствие подписи. Это означает, что isEmpty (List) никогда не будет соответствовать чему-либо, потому что вы не можете построить что-либо из этого типа.

+0

Хороший ответ, спасибо! Но не было бы быстрее иметь экземпляр, особенно если ожидаемыми типами данных являются CharSequence, Collection или массив любого типа? – PNS

+0

вполне вероятно, что MethodUtils собирается кэшировать ответы, но да, это может быть быстрее. Однако, это означает, что каждый раз, когда вы добавляете новый метод isEmpty, вам нужно изменить значение с большим предложением IF. С помощью этого решения вам просто нужно добавить новый метод. Я все для менее подверженного ошибкам кода, и я думаю, что это меньше подвержено ошибкам. Вы поверите мне в первый раз, когда вы попытаетесь добавить новый метод и забудьте предложение if. – Matt

+0

Очень разумный подход. Еще раз спасибо. – PNS