Java: быстрее перегрузки или if / else - PullRequest
4 голосов
/ 17 апреля 2009

У меня есть дочерние классы, каждый из которых имеет свой тип значения вместе с другими членами. Это может быть LongObject, IntObject, StringObject и т. Д.

Мне будет дано значение, которое может быть long, int, string и т. Д., И я должен создать LongObject, IntObject, StringObject и т. Д. Соответственно.

Было бы быстрее перегрузить метод, как показано ниже (а), или просто использовать elseif, как показано ниже (б)?

Это не может быть заметной разницы в производительности. Может случиться так, что перегруженные методы в любом случае будут реализованы аналогично if / else. Я не знаю.

Я также слышу, как некоторые из вас говорят просто проверить это. Конечно, я должен. Я также хотел бы знать, как этот тип перегрузки обрабатывается под капотом, если кто-нибудь знает.

Пожалуйста, дайте мне знать, что вы думаете.

Спасибо, JBU

а)

BaseObject getObject(long l)
{
     return new LongObject(l);
}

BaseObject getObject(int i)
{
     return new IntObject(i);
}

BaseObject getObject(String s)
{
     return new StringObject(s);
}

...

б)

BaseObject getObject(Object x)
{
    if(value is a long)
         return new LongObject((Long)x);
    else if(value is an int)
         return new IntObject((Int)x);
    else if(value is a String)
         return new StringObject((String)x);
    ...
}

edit: Я думаю, я не полностью добавил все детали, некоторые из вас это поняли. Для обоих вариантов мне все еще нужно получить объект / значение и по значению определить, какой это тип. Следовательно, мне все еще нужно выполнить if / else некоторого вида, чтобы даже использовать перегруженные методы.

Ответы [ 7 ]

21 голосов
/ 17 апреля 2009

Здесь есть огромное расхождение: перегрузки выбираются в время компиляции , тогда как ваше "if (значение длинное)" будет время выполнения тест.

Если вы знаете тип во время компиляции, я настоятельно рекомендую вам использовать эту информацию. Если вы этого не сделаете, то в любом случае опция перегрузки не будет реально осуществима.

РЕДАКТИРОВАТЬ: Комментарий предлагает мне немного рассказать о перегрузках, которые выбираются во время компиляции.

Компилятор выбирает, какая сигнатура метода вызывается на основе информации времени компиляции об аргументах. Это отличается от переопределения , когда используемая реализация метода определяется типом фактической цели метода.

Вот пример:

public class Test
{
    public static void main(String[] args)
    {
        Object x = "I'm a string";
        foo(x);
    }

    public static void foo(String x)
    {
        System.out.println("foo(String)");
    }

    public static void foo(Object x)
    {
        System.out.println("foo(Object)");
    }
}

Это печатает foo(Object), потому что тип времени компиляции x равен Object, а не String. Тот факт, что тип времени выполнения объекта, на который ссылается x, равен String, не означает, что foo(String) вызывается.

5 голосов
/ 17 апреля 2009

Решение для перегрузки намного быстрее (и лучше), потому что оно разрешается во время компиляции.

По сути, компилятор выясняет, какой метод вызывать при передаче ему значения. Когда вы вызываете getObject ("abc"), компилятор отправляет вызовы метода:

BaseObject getObject(String s)
{
     return new StringObject(s);
}

вместо того, чтобы пытаться пройти через ваше состояние if ... else и оценить тип объекта (что является медленным действием) во время выполнения.

1 голос
/ 17 апреля 2009

Не беспокойтесь, если условие не проверяется миллионы раз в секунду, это не имеет значения.

0 голосов
/ 17 апреля 2009

Самое главное, getObj (int), getObj (string) и т. Д. - потерпит неудачу во время компиляции, если вы попытаетесь передать что-то не ожидаемое.

Если вы позволите любому объекту быть переданным в метод, у вас может быть экземпляр, в котором приложение пытается передать что-то, с чем метод не может справиться, и у вас возникает ужасная ошибка времени выполнения.

0 голосов
/ 17 апреля 2009

Каскадные условные обозначения - плохая карма в ОО-программировании и действительно ужасны при тестировании типа объекта. Язык уже обеспечивает этого короля теста полиморфизмом.

Кроме того, как парень, не являющийся Java, я бы использовал getLong(l), getInt(i), getString(s). Я нахожу перегрузку методов более запутанной, чем нет (статические типы imho не должны влиять на выполнение программы (кроме как в плане оптимизации (и, несмотря на внешность, я не Лиспер)

0 голосов
/ 17 апреля 2009

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

Это часто называют «ранним связыванием» против «позднего связывания».

0 голосов
/ 17 апреля 2009

a) (перегрузка) будет быстрее, так как это дает своевременному компилятору возможность оптимизировать. Может быть решено включить создание нового объекта.

...