Java类:匿名vs嵌套vs私有

时间:2011-03-29 06:12:06

标签: java jvm javac

有人可以解释Java中的匿名类,嵌套类和私有类之间的区别吗?我想知道与每个相关的运行时成本以及每个的编译器方法,因此我可以掌握哪个最适合用于例如:性能(编译器优化的可能性),内存使用率以及与其他Java编码器的一般可接受性。

匿名类我的意思是那些以奇怪的Java方式在函数中内联声明的内容。这通常出现在Swing代码的示例中,您可以使用它的声明内联编写一个按钮处理程序。我真的不喜欢匿名类,因为你得到了那些有趣的MyClass $ 1.class文件,而且当你发现你想要让匿名类成为单例或需要它的句柄时,你将不得不重构。一些东西。我也不喜欢你在另一个函数调用的中间以你刚刚编写的东西的形式附加处理程序的方式。这让我觉得很奇怪。 : - )

私有类是您在公共类声明之外完全写入文件底部的类。我更喜欢私有类,因为它们在源文件和类之间没有强大的1:1关系的其他语言中是有意义的。我没有那种奇怪的感觉,我知道(或者我想我知道)Java编译器将如何处理该类的声明。

嵌套类是在公共类的波形内写的。我真的不知道嵌套类与其他两个相比意味着什么。 : - )

3 个答案:

答案 0 :(得分:7)

  

有人可以解释Java中的匿名类,嵌套类和私有类之间的区别吗?

  • 匿名类例如是

    中的Runnable
    new Thread(new Runnable() {
        public void run() {
            ...
        }
    }.start();
    
  • 嵌套类看起来像

    class SomeClass {
    
        ...
    
        class NestedClass {
            ....
        }
    }
    
  • 私有类(您将其称为"您在文件底部完全写在公共类声明之外的#34;)实际上是包括作用域的类。你不能在一个类前面有private修饰符,除非它是嵌套的!

  

我想知道与每种方法相关的运行时成本以及每种方法的编译器方法,因此我可以掌握哪种方法最适合用于例如:性能(编译器优化的可能性),内存使用率以及与其他Java编码器的一般可接受性。

我怀疑这些方法之间存在任何性能差异。为什么?因为每种方法最终都被编译成一个或多或少的常规"类。 ("或多或少"由于在某些情况下会生成访问方法,但它的副作用是免费的,最有可能由JIT内联。)

此代码:

public class TestOuter {

    int fieldOuter;
    public void methodOuter() {
    }

    class TestInner {
        int fieldInner;
        public void methodInner() {
        }
    }
}


class TestPackage {

    int fieldPackage;
    public void methodPackage() {
    }

}

获取编译成:

$ javap -c TestOuter$TestInner
Compiled from "TestOuter.java"
public class TestOuter extends java.lang.Object{
int fieldOuter;

public TestOuter();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public void methodOuter();
  Code:
   0:   return

}

$ javap -c TestOuter
Compiled from "TestOuter.java"
public class TestOuter extends java.lang.Object{
int fieldOuter;

public TestOuter();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public void methodOuter();
  Code:
   0:   return

}

$ javap -c TestPackage
Compiled from "TestOuter.java"
class TestPackage extends java.lang.Object{
int fieldPackage;

TestPackage();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public void methodPackage();
  Code:
   0:   return

}

答案 1 :(得分:3)

至于运行时成本,私有和公共类是相同的。理论上存在差异,因为JVM可以更容易地从私有类内联方法,但这是理论。

嵌套类:有两种,静态和非静态。这实际上是一个相对较大的区别:静态类就像一个私有类,非静态类有一个指向父对象的指针(引用,无论你想调用它)。这意味着它需要更多内存,因此如果可能的话使用静态嵌套类。否则,嵌套类与私有类或公共类一样快。从非静态嵌套类中,您可以访问父对象(这就是它引用父对象的原因),但在访问私有字段时要小心,因为这是使用特殊的隐藏匿名函数完成的(Eclipse会给你一个警告)

如果您真的想了解所有差异,则应使用javap对该类进行反编译。

答案 2 :(得分:1)

首先纠正一些术语。

  • private 类是使用访问修饰符private声明的类。此修饰符只能用于嵌套类,因此私有类是嵌套类的子集。

  • “您在公共类声明之外完全写入文件底部”的类实际上是包私有。这是因为他们的访问/可见性...而不是他们在同一个文件中的其他类别。

(尽管你喜欢这样做,但人们普遍认为将一个以上的顶级类放在一个源文件中是一个坏主意。它可能会破坏工具和IDE,一开始。 :http://geosoft.no/development/javastyle.html。)

那么它们之间有什么区别?

  • 包私有类与普通的publicprotected类相同,只是它只对同一个包中的其他类可见。

  • 嵌套类是在另一个类中声明的static类。它的行为与所有意图和目的的行为方式与非嵌套类相同。特别是,可以独立于任何封闭的类实例创建实例。

  • 本地内部类是在另一个类中声明的非static类。必须在封闭类的实例的上下文中创建实例,并且可以访问该实例的所有成员。

  • 匿名内部类在功能上类似于本地内部类,除了:

    • 它在方法中声明并且可以使用方法中声明的变量(假设它们是final),并且
    • 它并没有名称,也无法独立实例化。

    匿名内部类语法结合了声明和实例化,旨在使编写轻量级回调变得容易。

性能怎么样?

  • 嵌套类(私有或其他)的性能与常规类相同。
  • 两种形式的内部类具有很小的性能成本,因为它们使用隐藏属性来保存对封闭实例的引用。

可接受性怎么样?

  • 嵌套类(包括私有类)和两种形式的内部类都是可以接受的,并有其用途。 (显然有些比其他更合适,具体取决于用例。但你可以说每个Java结构。)

  • 您错误标记为“私有”的表单(将多个顶级类放入一个源文件中)通常被认为是个坏主意。