Java中内部类和静态嵌套类的主要区别是什么?设计/实现是否在选择其中一个方面发挥作用?
当前回答
简单来说,我们需要嵌套类,主要是因为Java不提供闭包。
嵌套类是在另一个封闭类的主体内定义的类。它们有两种类型——静态和非静态。
它们被视为封闭类的成员,因此您可以指定四个访问说明符中的任意一个-私有、包、受保护和公共。对于顶级类,我们没有这种奢侈,它只能声明为public或packageprivate。
内部类(也称为非堆栈类)可以访问顶级类的其他成员,即使它们被声明为私有,而静态嵌套类不能访问顶级类中的其他成员。
public class OuterClass {
public static class Inner1 {
}
public class Inner2 {
}
}
Inner1是我们的静态内部类,Inner2是我们的非静态内部类。它们之间的关键区别是,如果没有Outer,就无法创建Inner2实例,因为您可以独立创建Inner1对象。
你什么时候使用内部类?
想象一下这样一种情况:a类和B类是相关的,B类需要访问a类成员,而B类只与a类相关。
为了创建内部类的实例,需要创建外部类的实例。
OuterClass outer = new OuterClass();
OuterClass.Inner2 inner = outer.new Inner2();
or
OuterClass.Inner2 inner = new OuterClass().new Inner2();
什么时候使用静态内部类?
当您知道静态内部类与封闭类/顶层类的实例没有任何关系时,可以定义它。如果您的内部类不使用外部类的方法或字段,这只是浪费空间,所以请将其设置为静态。
例如,要为静态嵌套类创建对象,请使用以下语法:
OuterClass.Inner1 nestedObject = new OuterClass.Inner1();
静态嵌套类的优点是它不需要包含类/顶级类的对象来工作。这可以帮助您减少应用程序在运行时创建的对象数量。
其他回答
Java编程语言允许您在另一个类中定义一个类。这样的类称为嵌套类,如下所示:
class OuterClass {
...
class NestedClass {
...
}
}
嵌套类分为两类:静态类和非静态类。声明为静态的嵌套类称为静态嵌套类。非静态嵌套类称为内部类。我们应该记住的一点是,非静态嵌套类(内部类)可以访问封闭类的其他成员,即使它们被声明为私有。静态嵌套类只能访问封闭类的其他成员(如果这些成员是静态的)。它无法访问外部类的非静态成员。与类方法和变量一样,静态嵌套类与其外部类相关联。例如,要为静态嵌套类创建对象,请使用以下语法:
OuterClass.StaticNestedClass nestedObject =
new OuterClass.StaticNestedClass();
要实例化内部类,必须首先实例化外部类。然后,使用以下语法在外部对象中创建内部对象:
OuterClass.InnerClass innerObject = new OuterClass().new InnerClass();
为什么我们使用嵌套类
这是一种对仅在一个地方使用的类进行逻辑分组的方法。它增加了封装性。它可以产生更可读和可维护的代码。
来源:Java™ 教程-嵌套类
内部类的实例是在创建外部类的实例时创建的。因此,内部类的成员和方法可以访问外部类的实例(对象)的成员和对象。当外部类的实例超出范围时,内部类实例也将停止存在。
静态嵌套类没有具体实例。它只是在第一次使用时加载的(就像静态方法一样)。它是一个完全独立的实体,其方法和变量不能访问外部类的实例。
静态嵌套类不与外部对象耦合,它们速度更快,并且不占用堆/堆栈内存,因为不需要创建此类的实例。因此,经验法则是尽量使用有限的范围(private>=class>=protected>=public)定义静态嵌套类,然后将其转换为内部类(通过删除“static”标识符),如果确实有必要,则放宽范围。
嵌套类是一个非常通用的术语:每个不是顶级的类都是嵌套类。内部类是非静态嵌套类。约瑟夫·达西写了一篇关于嵌套、内部、成员和顶级课程的非常好的解释。
不同之处在于,同样是静态的嵌套类声明可以在封闭类之外实例化。
当您有一个非静态的嵌套类声明(也称为内部类)时,Java不允许您实例化它,除非通过封闭类。从内部类创建的对象链接到从外部类创建的目标,因此内部类可以引用外部类的字段。
但是如果它是静态的,那么链接就不存在,外部字段就不能被访问(除非像其他对象一样通过普通引用),因此您可以自己实例化嵌套类。
我认为这里的人应该注意到海报:静态嵌套类只是第一个内部类。例如:
public static class A {} //ERROR
public class A {
public class B {
public static class C {} //ERROR
}
}
public class A {
public static class B {} //COMPILE !!!
}
所以,总结一下,静态类并不取决于它包含的类。所以,他们不能在正常班级上课。(因为普通类需要一个实例)。
推荐文章
- Java中的split()方法对点(.)不起作用。
- Eclipse调试器总是阻塞在ThreadPoolExecutor上,没有任何明显的异常,为什么?
- Java生成两个给定值之间的随机数
- 如何有效地从数组列表或字符串数组中删除所有空元素?
- 比较JUnit断言中的数组,简洁的内置方式?
- codestyle;把javadoc放在注释之前还是之后?
- 如何在Spring中定义List bean ?
- 将Set<T>转换为List<T>的最简洁的方法
- 在JavaScript中,什么相当于Java的Thread.sleep() ?
- 使用Java重命名文件
- URL从Java中的类路径加载资源
- .toArray(new MyClass[0]) or .toArray(new MyClass[myList.size()])?
- Hibernate中不同的保存方法之间有什么区别?
- Java 8流和数组操作
- Java Regex捕获组