【问题标题】:What is the difference between "Listener" class implementations?“Listener”类实现有什么区别?
【发布时间】:2011-01-14 03:47:10
【问题描述】:

我遇到了另一个关于 Java 的“哲学”问题。这是关于以下场景:

您有一个T 类,它定义了一个接口L,该接口将用作侦听器,第二个类的通知器。

现在你有了第二个类(在下面的代码中它们是AB 类)。该类将创建T 类的新对象并使用L,后者将使用该对象与第一个进行通信。

所以我提出了 4 个不同版本的监听器对象如何传递给T

  • A 类定义了L 的实现,LL 类并使用它的新对象创建T 类。

    1. A1 预分配对象
    2. A2 现场创建新对象
  • B通过使用L的匿名类使用内联方式创建对象(感谢Tim Bender的更正)

    1. B1 预分配对象
    2. B2 现场创建一个新对象

我的问题是,这些版本中的任何一个在某种程度上更有效吗?它们中的任何一个由于某种原因不安全吗?请讨论,建议其他版本并解释!

T 类

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
            }
        });
    }   
}

【问题讨论】:

  • 您的陈述“B 类使用内联方式创建对象而不显式实现接口 L”是不正确的。接口 L 是显式实现的。您试图描述的通常称为匿名类。
  • @Tim Bender,感谢指正;所以基本上AB 在二进制文件方面并没有什么不同,这只是程序员的选择

标签: java class implementation listener


【解决方案1】:

A 和 B 之间的差异(使用匿名类)不是运行时差异。当你编译这段代码时,你会发现一个匿名类是使用像 B1$1 这样的标识符创建的。你甚至可以检查你编译到的 bin 目录中的那个类文件。

1 和 2 之间的唯一区别是,通过创建成员变量,您会膨胀实例化包含类的实例所需的大小。您应该只在需要时才创建成员变量(出于重用目的)。

不过,最重要的是,开发时的主要关注点应该始终是清晰度和正确性。如果稍后出现性能问题,最好使用能够识别问题区域的分析工具来处理正常运行的应用程序。或者,可能使用静态分析工具来识别小而容易获得的收益(低悬的果实)。

【讨论】:

  • 同意。你永远不知道编译器和热点引擎会做什么样的优化(除非你是编译器的书呆子),所以让代码更人性化应该是你的首要目标。
  • 如果我希望finish() 函数在应用程序的整个生命周期中被调用几次(甚至可能很多次)怎么办?那么使用成员变量方法会更好吗?如果不用每次都创建一个新对象,真的会影响性能吗?
【解决方案2】:

软件效率确实没有显着差异。它真的归结为程序员的效率和更大的上下文。如果您确定它只会使用一次,那么B2 通常是首选方法,因为它更简洁。 A1 更冗长,但也更可重用。此外,通过选择好的变量名,如果代码非常复杂,冗长往往更适合自记录代码。

我个人的倾向是第三种选择,外部类实现接口并将this 传递给构造函数。

【讨论】:

    猜你喜欢
    • 2013-01-25
    • 2015-07-03
    • 1970-01-01
    • 2011-02-02
    • 2011-12-03
    • 2016-12-19
    • 2013-05-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多