【问题标题】:Are Inner Classes lightweight?内部类是轻量级的吗?
【发布时间】:2011-06-16 07:06:14
【问题描述】:

是内部类比普通类更轻量级,还是java最终编译内部类就像普通类一样?

我知道java中的类本身并不是非常轻量级的,它们占据了永久内存的一部分,所以我想知道是否最好使用类闭包函数作为内部类,或者标准类是否也可以还好吗?

【问题讨论】:

  • JVM 只有原始数据类型(intfloat 等)和类。他们之间什么都没有。

标签: java closures inner-classes permgen


【解决方案1】:

内部类和匿名内部类都编译为.class 文件。例如:

class Outer {
     class Inner {

     }

     Object function() {
          return new Object() {

          };
     }
}

将生成三个.class 文件,Outer.classOuter$Inner.classOuter$1.class。它们并不比其他类更“轻量级”,而且(据我所知)从性能的角度来看,使用一个比另一个没有优势。当然,内部类,尤其是匿名内部类在常规类难以编码的情况下非常有用,但这是一个单独的问题。

【讨论】:

  • +1。如果有任何内部类“更重”,因为它们包含编译器创建的合成方法和字段,以促进它们对包含类的特殊可见性规则。
【解决方案2】:

内部类仍然是类,它们仍然必须由 ClassLoader 加载。如果有的话,情况恰恰相反。非静态内部类可以防止父类被垃圾回收,因为它具有对拥有它的类的引用。

【讨论】:

  • +1。除了父引用之外,还有合成方法允许从相关类调用“私有”方法。
【解决方案3】:

它们不是轻量级的,但它们有限制。 AFAIK,您不能创建多个匿名内部类的实例,因此如果您需要这样做,则必须使用非匿名类。

编辑 1:感谢所有 cmets 和澄清。请帮助我更好地理解这一点...我知道您可以拥有多个匿名内部类实例,但是如果我声明一个匿名内部 ActionListener 对象,例如,我如何才能拥有 该类的多个实例 只有那个类而不使用反射?提前谢谢(或者我应该在我自己的问题中问这个?)!

好的,因为我没有被咬...让我用代码演示一下。假设我在这里创建了一个匿名 ActionListener:

  JButton button = new JButton("Button");

  button.addActionListener(new ActionListener() {
     @Override
     public void actionPerformed(ActionEvent arg0) {
        System.out.println("Button says \"Foo!\"");
     }

  });

  JOptionPane.showMessageDialog(null, button);

我创建了一个匿名的 ActionListener 并且一举创建了这个类的一个对象。我一直被教导的,我在这里的帖子顶部提到的(并且被叮咬)是,即使不是不可能(没有反射的魔力),也很难(如果不是不可能)制作这个匿名类的另一个对象,即只能制作一个对象,在只需要一个对象的情况下,这很好。但在其他情况下,这并不好。当然,您可以创建多个类似的匿名 ActionListener 类,例如在 for 循环中:

   JPanel panel = new JPanel(new GridLayout(5, 5));
  JButton[] buttons = new JButton[25];
  for (int i = 0; i < 25; i++) {
     final int btnNumber = i;
     buttons[i] = new JButton(String.valueOf(btnNumber));
     buttons[i].addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
           System.out.println("From button " + btnNumber);
        }
     });
     panel.add(buttons[i]);
  }
  JOptionPane.showMessageDialog(null, panel);

但即便如此,这里创建的每个匿名类都是不同的。如果多个 JButtens 使用相同类型的侦听器,这可能很重要,它具有状态,并且其行为取决于此状态。同意?不同意?提前感谢您的任何意见!

【讨论】:

  • 您可以拥有多个匿名内部类实例,例如,将类放入for 循环并多次实例化它。我认为 Java 要求这些类都具有相同的类型,但我不记得这是否正确。
  • 你想多了。匿名内部类仍然是一个类。您可以拥有任意数量的实例。您还可以根据需要指定任意数量的匿名内部类。编译器在编译时处理所有这些。它找到的第一个匿名规范的名字叫 Foo$1,第二个是 Foo$2,以此类推。像new Runnable(){...} 这样的代码变成Foo.new 1()
  • 感谢 cmets 和有用的信息!请为我澄清......如果我有一个匿名的内部 ActionListener,我怎么能有这个类的两个不同的实例(没有反射),因为它是在创建对象时创建的。我知道我可以拥有许多匿名 ActionListener 的实例,但我想知道如何拥有一个已声明的不同匿名类的多个实例。
  • 编辑:由于我没有收到澄清,我在这里为这个问题创建了一个新线程/问题:stackoverflow.com/questions/4820031/…。如果可以这样做,请告诉我。谢谢!
猜你喜欢
  • 2020-07-16
  • 2011-02-01
  • 2010-09-29
  • 1970-01-01
  • 2012-06-26
  • 2011-08-31
  • 1970-01-01
  • 1970-01-01
  • 2013-01-08
相关资源
最近更新 更多