嗨! 这篇文章致力于Java面向对象编程中的一个重要概念-嵌套类。 简单来说,嵌套类是在另一个类(外部类)中定义的类。 它们用于提供更高级别的封装并组织逻辑代码,这些代码仅在一个地方使用。 在进行GUI开发时(例如,在Android编程中),您还会遇到嵌套类。 最后,如果您真的想通过Oracle考试,则必须将嵌套类作为任务掌握在两个阶段中。
在本文中,我们将观察什么是Java中的嵌套类以及此类的具体类型。
What is a nested class?
从技术角度来看,嵌套类是类,在另一个类中定义。 外部类也称为封闭类。 这些类使开发人员能够在逻辑上对仅在一个地方使用的类进行分组,因此,这将增加封装的程度,并创建更具可读性和可维护性的代码。 Java中的嵌套类分为两类:静态的和non-静态的. First group are also called 静态的 nested classes. Non-静态的 nested classes are known as inner classes. Take a look on the graph below, that demonstrates an hierarchy of Java nested classes:
使用嵌套类有几个参数:
- 当一个类仅对另一个类有用时,将其嵌入该类并将两者保持在一起是合乎逻辑的将小类嵌套在顶级类中,使代码更接近使用位置嵌套类的使用是增加封装级别的有力措施
这些类型的嵌套类根据范围,访问封闭的类成员等的不同而有所不同。现在,我们将更深入地研究它们。 我们将从静态嵌套类开始。
Static classes
首先要讨论的组是静态嵌套类组。
Static nested classes
静态嵌套类与其封闭类相关联。 它不能直接引用其封闭类中定义的实例变量或方法-换句话说,您必须使用对象参考。 让我们看下面的例子:
class Outer{
static class Nested{
}
}
// create nested class instance
Outer.Nested nestedInstance = new Outer.Nested();
注意,在示例代码中,使用外部类名访问静态嵌套类。 嵌套类无法访问非静态数据成员,外部类的方法可以访问外部类的静态数据成员,包括声明为私人的。 看一下另一个代码片段:
class Car{
//static members
static String manufacturer;
private static String vin;
// instance member
String model;
static class Engine{
System.out.println(manufacturer);
System.out.println(vin);
//This will be a compilation error
System.out.println(model);
}
}
那么,静态嵌套类应该记住些什么呢? 以下几点:
- 静态嵌套类能够访问静态成员外层阶级他们能够't访问实例(非静态)成员外层阶级 直,仅使用对象参考(喜欢嵌套)静态嵌套类are created as OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
相反,有几种类型的非静态内类。
Non-static classes
非静态类与封闭类的实例相关联,并且可以直接访问封闭类的方法和字段。 而且,由于内部类与外部类的实例相关联,因此它本身不能定义任何静态成员。 让我们观察一下非静态类的类型。
Local inner classes
局部内部类是在一个块中定义的类,该块是一组在平衡括号之间的零个或多个语句。 通常,这些类在方法内定义,但是您可以在任何块内定义局部类。 让我们观察下面的代码:
class Outer{
int value = 10;
void calculate(){
class Sum{
int value;
Sum(int a, int b){
this.value = a + b;
}
int getValue(){
return this.value;
}
}
Sum sum = new Sum(20,30);
System.out.println(sum.getValue());
System.out.println(value);
}
public static void main(String[] args) {
Outer outer = new Outer();
outer.calculate();
}
}
因此,此示例演示了遮蔽:如果特定作用域(例如内部类或方法定义)中类型的声明(例如成员变量或参数名称)与封闭范围中的另一个声明具有相同的名称,则该声明将 封闭范围的声明。 在示例中,我们有两个值变量并引用我们使用的Sum成员这个关键词。 本地类中的类型声明(例如变量)会在封闭范围内的阴影声明中具有相同的名称。
谈论本地内部类,谈论访问也很重要局部变量。 让我们修改上面的代码:
void calculate(){
int y - 10;
class Multiplicator{
int x;
Sum(int x){
this.value = x * y;
}
int getValue(){
return this.value;
}
}
Multiplicator multiplicator = new Multiplicator(10);
System.out.println(multiplicator.getValue());
}
How can Multiplicator class access a local variable y? This is a popular interview question. Local classes can only access local variables that are declared final. When a local class accesses a local variable or parameter of the enclosing block, it captures that variable or parameter. But that how it was before Java 8. However, in the 8th release was introduced a concept of effectively final varialbes: these are variables or parameters whose value is never changed after it is initialized.
而实际上,最终变量不需要最后无论如何,它们前面的关键字不能改变初始化后。 遵循此原理,此代码片段将无法编译:
void calculate(){
int y - 10;
class Multiplicator{
int x;
Sum(int x){
this.value = x * y;
}
int getValue(){
return this.value;
}
}
y = 20;
Multiplicator multiplicator = new Multiplicator(10);
System.out.println(multiplicator.getValue());
}
当我们尝试对其进行编译时,Java将指示类似于此错误输出:
让我们总结一下到目前为止我们学习到的关于本地内部类的知识:
- 本地内部类范围是定义它的块它不能从创建它的块外部实例化它能够访问局部变量(如果它们是最终的(在Java 8之前)或实际上是最终的)本地内部类有权访问其所在类的成员
同样,局部内部类可以扩展抽象类,也可以实现接口。
Anonymous classes
最后,让我们探索匿名类。 从技术角度来看,它们就像本地内部类,只是它们没有名称。 因此,仅当我们需要重载类或接口的方法而不必实际扩展(实现)它们时,才使用它们。 让我们直接看一个例子:
void doWork(){
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Hello runnable");
}
};
runnable.run();
}
我们实施了可运行直接在调用它的方法内部接口。 这样可以使代码更简洁。 我们可以同时声明和实例化一个类。 您可以在匿名类内部声明字段和父类或接口内部不存在的其他方法,甚至可以添加本地类。 然而,您不能在匿名类中声明构造函数。
关于匿名类要记住的重要事项:
- 他们可以访问其封闭类的成员与本地内部类相同,它们不能访问其封闭范围内未声明为final或有效的final的局部变量。像嵌套类一样,匿名类中的类型声明(例如变量)会掩盖封闭范围内具有相同名称的任何其他声明匿名类可以具有静态成员,前提是它们是常量变量
Conclusion
在本教程中,我们探索了Java中不同类型的嵌套类。 这个主题非常重要,因此,如果您认真考虑要通过Oracle考试,则必须掌握嵌套类,并将其作为任务同时存在于两个阶段中。 我们讨论了如何使用以及对它们的限制。
References
from: https://dev.to//andreevich/introduction-to-nested-classes-in-java-3d4a