Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/348.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java类:匿名vs嵌套vs私有_Java_Jvm_Javac - Fatal编程技术网

Java类:匿名vs嵌套vs私有

Java类:匿名vs嵌套vs私有,java,jvm,javac,Java,Jvm,Javac,有人能解释一下Java中匿名类、嵌套类和私有类之间的区别吗?我想知道与每种方法相关的运行时成本以及每种方法的编译器方法,以便掌握哪种方法最适合用于性能(编译器优化的可能性)、内存使用以及其他Java编码器的普遍接受性 我所说的匿名类是指那些以这种奇怪的Java方式在函数中内联声明的类。这在Swing代码的示例中经常可以看到,在这些示例中,您编写了一个与按钮处理程序声明内联的按钮处理程序。我真的不喜欢匿名类,因为你会得到那些有趣的MyClass$1.class文件,而且通常情况下,当你想让匿名类成

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

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

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

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

有人能解释一下Java中匿名类、嵌套类和私有类之间的区别吗?

  • 例如,匿名类在中是可运行的

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

    class SomeClass {
    
        ...
    
        class NestedClass {
            ....
        }
    }
    
  • 私有类(您称之为“完全在公共类声明之外的文件底部编写的类”)实际上是包范围的类。类前面不能有
    private
    修饰符,除非它是嵌套的

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

我怀疑这些方法之间是否存在性能差异。为什么?因为每种方法最终都被编译成一个独立的或多或少的“常规”类。(“或多或少”,因为在某些情况下会生成access方法,但它没有副作用,而且很可能是由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-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
    声明的类。此修饰符只能用于嵌套类,因此私有类是嵌套类的子集

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

(尽管您喜欢这样做,但普遍认为在一个源文件中放置多个顶级类是个坏主意。首先,它可能会破坏工具和IDE。源:)

那么它们之间的区别是什么呢

  • 包私有类与普通
    公共类
    受保护类
    相同,只是它仅对同一包中的其他类可见

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

  • 本地的内部阶级
    $ 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
    
    }