2011-01-14 3 views
0

У меня возник еще один «философский» вопрос относительно Java. Речь идет о следующем сценарии:В чем разница между реализациями класса Listener?

У вас есть класс T, который определяет интерфейс L, который будет использоваться в качестве прослушивателя, оповещения для второго класса.

Теперь у вас есть второй класс (в следующем коде они относятся к классам и B). Этот класс создаст новый объект класса T и использует L, который последний будет использовать для связи с первым.

Так я представляю 4 различные версии того, как его Слушатель объект может быть передан T:

  • Классы A определяют реализацию L, класс LL и использовать новый объект его создать a T класс.

    1. A1 предварительно выделяет объект
    2. A2 создает новый объект на месте
  • Классы B использовать встроенный способ создания объекта путем использования анонимных классов L (спасибо Тим Бендер для коррекции)

    1. B1 предопределяет объект
    2. B2 создает новый объект на месте

Мой вопрос, является любой из более эффективных в той или иной форме эти версии? Кто-нибудь из них небезопасен по какой-то причине? Пожалуйста, обсудите, предложите другие версии и объясните!

класса Т

class T extends TT{ 
    public interface L{ 
     public void do(int i); 
    } 

    private L Lo; 

    T(L i){ 
     Lo = i; 
    } 

    public void start(){ 
     // do stuff 
     L.do(0); 
    } 
} 

Класс A

class A1{ 
    private class LL implements L{ 
     @Override 
     public void do(int i){ 
      // do stuff 
     } 
    } 

    private LL l = new LL(); 

    public void function(){ 
     T t = new T(l) 
    } 
} 

class A2{ 
    private class LL implements L{ 
     @Override 
     public void do(int i){ 
      // do stuff 
     } 
    } 

    public void function(){ 
     T t = new T(new LL()) 
    } 
} 

Класс B

class B1{ 
    private L l = new L(){ 
     @Override 
     public void do(int i){ 
      // do stuff 
     } 
     }; 

    public void function(){ 
     T t = new T(l); 
    } 
} 

class B2{ 
    public void function(){ 
     T t = new T(new L(){ 
      @Override 
      public void do(int i){ 
       // do stuff 
      } 
     }); 
    } 
} 
+2

Ваше утверждение: «Классы B используют встроенный способ создания объекта без явного реализации интерфейса L». Интерфейс L явно реализован. То, что вы пытаетесь описать, обычно называют анонимным классом. –

+0

@Tim Bender, спасибо за исправление; поэтому в основном 'A' и' B' на самом деле не отличаются друг от друга, когда речь заходит о двоичном коде, это просто выбор программиста – alkar

ответ

2

Разница между А и В (с использованием анонимных классов) не разница во время выполнения. Когда вы компилируете этот код, вы должны обнаружить, что анонимный класс создается с использованием идентификатора типа B1 $ 1. Вы даже можете проверить этот файл класса в каталоге bin, в который вы скомпилировали.

Единственное отличие между 1 и 2 состоит в том, что, создавая переменную-член, вы раздуваете размер, необходимый для создания экземпляра содержащего класса. Вы должны создать переменную-член, если это необходимо (для целей повторного использования).

Самое главное, что основной проблемой при разработке всегда должно быть ясность и правильность. Если впоследствии возникнет проблема с производительностью, гораздо лучше подойти к функционирующему приложению с помощью инструмента анализа, который идентифицирует проблемные области. Или, возможно, используйте инструмент статического анализа, чтобы идентифицировать небольшие, но легкие выгоды (низкие висячие фрукты).

+0

Согласен. Вы никогда не знаете, какие оптимизации будут выполняться компилятором и движком hotspot (если вы не являетесь компилятором), поэтому сделать код более дружественным к человеку будет вашей первой целью. –

+0

Что, если я ожидаю, что функция 'finish()' будет называться несколько (или, может быть, даже довольно много) раз в течение всей жизни приложения? Тогда было бы лучше использовать метод переменной-члена? Действительно ли это повлияло бы на производительность, если бы каждый раз не приходилось создавать новый объект? – alkar

2

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

Моя личная тенденция - это третий вариант, когда внешний класс реализует интерфейс и this передается конструктору.