Java类:匿名vs嵌套vs私有
有人能解释一下Java中匿名类、嵌套类和私有类之间的区别吗?我想知道与每种方法相关的运行时成本以及每种方法的编译器方法,以便掌握哪种方法最适合用于性能(编译器优化的可能性)、内存使用以及其他Java编码器的普遍接受性 我所说的匿名类是指那些以这种奇怪的Java方式在函数中内联声明的类。这在Swing代码的示例中经常可以看到,在这些示例中,您编写了一个与按钮处理程序声明内联的按钮处理程序。我真的不喜欢匿名类,因为你会得到那些有趣的MyClass$1.class文件,而且通常情况下,当你想让匿名类成为一个单例类或者需要它的句柄或其他东西时,你会不得不重构。我也不喜欢你在另一个函数调用中间附加一个处理程序的形式。这让我觉得很奇怪。:-) 私有类是您在文件底部编写的类,完全在公共类声明之外。我更喜欢私有类,只是因为它们在源文件和类之间没有很强的1:1关系的其他语言中有意义。我没有那种奇怪的感觉,我知道(或者我想我知道)Java编译器将如何处理该类的声明 嵌套类是编写在公共类的波形中的类。与其他两个类相比,我真的不知道嵌套类意味着什么。:-) 有人能解释一下Java中匿名类、嵌套类和私有类之间的区别吗?Java类:匿名vs嵌套vs私有,java,jvm,javac,Java,Jvm,Javac,有人能解释一下Java中匿名类、嵌套类和私有类之间的区别吗?我想知道与每种方法相关的运行时成本以及每种方法的编译器方法,以便掌握哪种方法最适合用于性能(编译器优化的可能性)、内存使用以及其他Java编码器的普遍接受性 我所说的匿名类是指那些以这种奇怪的Java方式在函数中内联声明的类。这在Swing代码的示例中经常可以看到,在这些示例中,您编写了一个与按钮处理程序声明内联的按钮处理程序。我真的不喜欢匿名类,因为你会得到那些有趣的MyClass$1.class文件,而且通常情况下,当你想让匿名类成
- 例如,匿名类在中是可运行的
new Thread(new Runnable() { public void run() { ... } }.start();
- 嵌套类看起来像
class SomeClass { ... class NestedClass { .... } }
- 私有类(您称之为“完全在公共类声明之外的文件底部编写的类”)实际上是包范围的类。类前面不能有
修饰符,除非它是嵌套的private
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-ctestouter$TestInner
从“TestOuter.java”编译而来
公共类TestOuter扩展了java.lang.Object{
国际外场;
公共TestOuter();
代码:
0:aload_0
1:invokespecial#1;//方法java/lang/Object。“:()V
4:返回
公共无效方法外部();
代码:
0:返回
}
$javap-ctouter
从“TestOuter.java”编译而来
公共类TestOuter扩展了java.lang.Object{
国际外场;
公共TestOuter();
代码:
0:aload_0
1:invokespecial#1;//方法java/lang/Object。“:()V
4:返回
公共无效方法外部();
代码:
0:返回
}
$javap-c测试包
从“TestOuter.java”编译而来
类TestPackage扩展了java.lang.Object{
int现场包;
TestPackage();
代码:
0:aload_0
1:invokespecial#1;//方法java/lang/Object。“:()V
4:返回
public-void-methodPackage();
代码:
0:返回
}
至于运行时成本,私有类和公共类是相同的。理论上是有区别的,因为JVM可以更容易地从私有类内联方法,但这只是理论
嵌套类:有两种,静态类和非静态类。这实际上是一个比较大的区别:静态类类似于私有类,而非静态类有一个指向父对象的指针(引用,不管您想调用它什么)。这意味着它需要更多的内存,所以如果可能,可以使用静态嵌套类。否则,嵌套类与私有类或公共类一样快。从非静态嵌套类可以访问父对象(这就是为什么它有对父对象的引用),但是在访问私有字段时要小心,因为这是使用特殊的隐藏匿名函数来完成的(Eclipse会给您一个警告)
如果您真的想理解所有的差异,那么应该使用
javap
来反编译类。首先更正一些术语
- 私有类是使用访问修饰符
声明的类。此修饰符只能用于嵌套类,因此私有类是嵌套类的子集private
- “完全在公共类声明之外写在文件底部”的类实际上是包私有的。这是因为他们的访问/可见性。。。并不是因为它们在同一个文件中或者其他类中
- 包私有类与普通
或公共类
相同,只是它仅对同一包中的其他类可见受保护类
- 嵌套类是在另一个类中声明的
类。对于所有意图和目的,它的行为方式与非嵌套类相同。特别是,可以独立于任何封闭类实例创建实例静态
- 本地的内部阶级
$ 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 }