大型内部类和私有变量 [英] Large Inner classes and private variables

查看:138
本文介绍了大型内部类和私有变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到过几次的事情是服务类(如JBoss服务),由于辅助内部类而变得过大.我还没有找到一种很好的方法来上课.这些助手通常是线程.这是一个示例:

One thing I've run into a few times is a service class (like a JBoss service) that has gotten overly large due to helper inner classes. I've yet to find a good way to break the class out. These helpers are usually threads. Here's an example:

/** Asset service keeps track of the metadata about assets that live on other
 * systems. Complications include the fact the assets have a lifecycle and their
 * physical representation lives on other systems that have to be polled to find
 * out if the Asset is still there. */
public class AssetService
{
  //...various private variables
  //...various methods

  public AssetService()
  {
    Job pollerJob = jobService.schedule( new AssetPoller() );
    Job lifeCycleJob = jobService.schedule( AssetLifecycleMonitor() );
  }

  class AssetPoller
  {
    public void run()
    { 
      // contact remote systems and update this service's private variables that
      // track the assets.
    }
  }

  class AssetLifecycleMonitor
  {
    public void run()
    {
      // look for assets that have meet criteria for a lifecycle shift
      // and update this service's private variables as relevant.
    }
  }
}

因此,如果我有几个帮手,而且他们都很复杂,会发生什么情况,那就是整个类文件可能会变得非常大.我喜欢内部类,因为它可以清楚地表明这些类完全由服务拥有,并且仅用于帮助该服务.我试图突破类并通过父服务作为参考,这在大多数情况下都是有效的,但是我不喜欢的是:

  • 我最终公开了程序包级别的访问器,以便使分解后的类可以访问变量,而在此之前,由于内部类具有直接访问权限,所以我根本没有公开设置器.
  • 另外,由于我不断调用访问器而不是基础变量,因此事情变得更加复杂.未成年人,已获准.
  • 便捷方法(例如checkAssetIsValid()或其他此类方法)现在需要进行程序包级别的公开,以便帮助程序类可以调用它们,就像以前的内部类一样,它们可以是私有的.
  • 更糟糕的是,我需要将服务实现类传递给帮助器类的构造函数,因为我不想在服务实现的接口中公开这些帮助器方法,因为这会迫使它们公开.这会产生一些单元测试/模拟问题.
  • 更糟糕的是,我想做的任何同步都会通过某种外部便捷方法(例如,在轮询器更新期间锁定lockDownAssets())泄漏出去.以前,内部类可以访问私有锁.

    So, what can happen if I have a couple helpers and they're at all complex, is the overall class file can get really large. I like the inner classes in that it makes clear the classes are wholly owned by the service and exist only to help that service. I've tried breaking the classes out and passing the parent service as a reference, which works mostly, but things I don't like are:

  • I end up exposing package level accessors so the broken out classes can get to the variables, whereas before I didn't expose the setters at all since the inner classes had direct access.
  • Plus, things get a bit more wordy as I'm constantly calling accessors rather than the underlying variables. A minor nit, granted.
  • Convenience methods (e.g. checkAssetIsValid() or some such) need package level exposure now so the helper classes can call them, where as before as inner classes they could be private.
  • Even worse, I need to pass the service implementation class to the helper classes constructors since I don't want to expose these helpers methods in the interface the service implements because that forces them to be public. This can create some unit test/mocking issues.
  • Worse yet, any synchronization I wanted to do gets leaked out through some external convenience method (e.g. lockDownAssets() during a poller update). Before, the internal classes had access to private Locks.

    因此,简而言之,将类拆分出去会丢失一些我喜欢的封装.但是,将它们保留在其中可能会导致一些大型的Java文件.我还没有找到解决这个问题的好方法. C ++具有朋友"的概念,这是我很少错过的,但在这种情况下实际上会有所帮助.

    So, in short, breaking the classes out loses some of the encapsulation I like. But leaving them in can lead to some large java files. I've yet to find a good way to deal with this. C++ had the concept of "friends" which I've rarely missed, but would actually help in this case.

    有想法吗?

    推荐答案

    在字节码级别上,内部类只是普通的Java类.由于Java字节码验证程序不允许访问私有成员,因此它将为您使用的每个私有字段生成综合访问器方法.另外,为了将内部类与其封闭的实例链接起来,编译器将合成指针添加到外部"this".

    On bytecode level inner classes are just plain Java classes. Since the Java bytecode verifier does not allow access to private members, it generates synthetic accessor methods for each private field which you use. Also, in order to link the inner class with its enclosing instance, the compiler adds synthetic pointer to the outer 'this'.

    考虑到这一点,内部类只是语法糖的一层.它们很方便,您已经列出了一些要点,所以我将列出一些您可能要考虑的负面方面:

    Considering this, the inner classes are just a layer of syntax sugar. They are convenient and you have listed some good points, so I'd list some negative aspects which you might want to consider:

    • 您的内部类对整个父类具有隐藏的依赖关系,该父类混淆了其入站接口.如果将其提取为package-private类,则有机会改善设计并使其更易于维护.最初它比较冗长,但通常您会发现:
      • 您实际上不想共享10个访问器,而是希望共享一个值对象.通常,您会发现实际上并不需要引用整个外部类.这也适用于IoC.
      • 与其提供显式锁定方法,不如将操作及其上下文封装在一个单独的类中(或将其移至两个类之一(外部或以前是内部)),这样更易​​于维护.
      • 便利方法属于软件包专用实用程序类.您可以使用Java5静态导入使它们显示为本地.
      • Your inner class has a hidden dependency to the whole parent class, which obfuscates its inbound interface. If you extract it as package-private class you have a chance to improve your design and make it more maintainable. Initially it's more verbose, but often you'd find that:
        • Instead of exposing 10 accessors you actually want to share a single value object. Often you would find that you don't really need a reference to the whole outer class. This also works well with IoC.
        • Instead of providing methods for explicit locking, it's more maintainable to encapsulate the operation with its context in a separate class (or move it to one of the two classes - outer or formerly-inner).
        • Convenience methods belong in package private utility classes. You can use the Java5 static import to make them appear as local.

        P.S.我说的是非平凡的内部类(尤其是那些没有实现任何接口的内部类).三行侦听器实现是好的.

        P.S. I'm talking about non-trivial inner classes (especially ones that do not implement any interfaces). Three line listener implementations are good.

        这篇关于大型内部类和私有变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆