Java 中 final 和 abstract 的区别
在使用 Java 时,理解 final 和 abstract 的概念对于编写高效且易于维护的代码至关重要。虽然 final 和 abstract 在面向对象编程中都扮演着重要的角色,但它们具有不同的用途。在本文中,我们将探讨 final 和 abstract 关键字在 Java 中的语法和用法,以及它们的不同实现方式。
语法
要定义一个 final 类或方法,我们在类或方法声明之前使用关键字“final”。例如,一个 final 类将定义如下:
final class MyClass { // Class implementation }
要定义一个 abstract 类或方法,我们在类或方法声明之前使用关键字“abstract”。例如,一个 abstract 类将定义如下:
abstract class MyAbstractClass { // Class implementation }
语法解释
关键字 "final" 用于指示一个类、方法或变量不能被修改或重写。final 类不能被子类化,final 方法不能在任何子类中被重写。此外,final 变量一旦赋值就不能重新赋值。
另一方面,关键字 "abstract" 用于指示一个类或方法是不完整的,必须由另一个类扩展或实现。abstract 类不能直接实例化,并且它可能包含 abstract 方法,这些方法必须由其子类实现。
方法 1:Final
在这种方法中,我们将重点关注 final 关键字的用法。使用 final 的主要目的是在 Java 中创建不可变实体。不可变对象是指其状态一旦创建就不能更改的对象。
算法
将类或方法声明为 final。
在类或方法中实现所需的功能。
防止其他类或子类进行任何进一步的修改。
示例
final class ImmutableClass { private final String name; public ImmutableClass(String name) { this.name = name; } public String getName() { return name; } } public class Main { public static void main(String[] args) { ImmutableClass immutableObject = new ImmutableClass("Hello"); System.out.println(immutableObject.getName()); } }
输出
Hello
方法 1 中代码的解释
ImmutableClass 被声明为不可变且不可扩展的,因为在声明期间包含了“final”关键字。它包含一个名为“name”的单个私有实例变量,该变量也被标记为 final,以防止在构造函数中初始赋值后进行修改。
ImmutableClass 的构造函数接受一个名为 name 的 String 参数,并将它的值赋给 name 变量。这确保了 name 变量只能在对象创建期间设置一次,并且之后不能修改。
在 ImmutableClass 中,有一个公共方法 getName() 用于获取对象的名称。由于 name 元素被声明为私有,因此必须阻止外部访问它,因此需要实现此查找工具。我们的程序入口点从 Main 类的 main() 函数开始,我们用参数“Hello”实例化一个 ImmutableClass 对象。
初始化后,我们将新实例存储在内存节省变量 immutableObject 中。我们通过将 System.out.println() 的输出流设置为 immutableObject 的 getName() 方法的返回值来结束我们的 main 函数,以便我们的程序通过在屏幕上显示“Hello”(我们最初指定的名称)来显示成功的执行。
方法 2:Abstract
在这种方法中,我们将重点关注 abstract 关键字的用法。abstract 类用于提供公共接口并为一组相关类定义公共行为。
算法
将类声明为 abstract。
定义 abstract 方法,这些方法应该由子类实现。
在 abstract 类中实现公共功能。
示例
abstract class Shape { protected String color; public Shape(String color) { this.color = color; } abstract double getArea(); } class Circle extends Shape { private double radius; public Circle(String color, double radius) { super(color); this.radius = radius; } @Override double getArea() { return Math.PI * radius * radius; } } public class Main { public static void main(String[] args) { Circle circle = new Circle("Red", 2.5); System.out.println("Color: " + circle.color); System.out.println("Area: " + circle.getArea()); } }
输出
Color: Red Area: 19.634954084936208
Shape 类使用 abstract 关键字声明为 abstract 类。abstract 类不能被实例化,这意味着不能直接创建 Shape 类的对象。Shape 类有一个名为 color 的受保护实例变量和一个接受 color 参数并将其值赋给 color 变量的构造函数。
Shape 类还声明了一个名为 getArea() 的 abstract 方法。在编程过程中,abstract 方法在创建代码实现的框架和结构方面发挥着关键作用。具体来说,使用此工具集,开发人员可以创建方法和结构,而无需立即在运行时确定它们,而是将它们留待以后从具体子类(即引入类别之外的类)进一步开发。
让我们具体研究 getArea() 在这里是如何相关的:简而言之,计算面积取决于形状分类和各种开发者使用的子类型因素;因此,将此变化因素放入非立即或独立开发中,允许任何具体子类实现自定义,而无需担心在子级创建之前表达的整体结构中断或完整性维护问题。此外,关于我们在这里的基础工作,Shape 可以被视为由 Circle 扩展为这样的子类,并进一步进行调制以集成到具有类似模板方法的开发的其他结构中。它添加了一个名为 radius 的私有实例变量,并带有一个同时接受 color 和 radius 参数的构造函数。Circle 的构造函数使用 super 关键字调用其超类 (Shape) 的构造函数来初始化 color 变量。然后它将 radius 参数赋给 Circle 类的 radius 变量。
Circle 类重写了从 Shape 类继承的 getArea() 方法。在这种情况下,它使用公式:π * radius * radius 计算圆的面积。Math.PI 常量表示 π 的值(约为 3.14159)。
此编程序列的基础是 Main 类,在其中我们可以找到 main 方法 - 建立程序的起点。在这个方法中,我们启动一个 Circle 对象,最初半径为 2.5,颜色为“红色”。此新对象从其各自的两个构造函数中获取信息:首先调用 Circle 构造函数,然后在重置其颜色值时调用 Shape 构造函数的帮助。最后,我们将“circle”指定为此特定实例的变量名。
最后,使用 circle.color 访问 circle 对象的 color 变量并将其打印到控制台。还对 circle 对象调用 getArea() 方法,并将返回值也打印到控制台。
Java 中 final 和 abstract 的区别
区别 |
方法 1:Final |
方法 2:Abstract |
---|---|---|
实例化 |
允许实例化类 |
不能直接实例化 |
继承 |
不能被子类化 |
允许子类化 |
方法重写 |
方法不能被重写 |
abstract 方法必须由子类实现 |
可修改性 |
防止修改类、方法或变量 |
为在子类中修改和扩展提供蓝图 |
用法 |
用于创建不可变实体或强制执行特定行为 |
用于为相关类定义公共接口和行为 |
结论
总之,虽然 final 和 abstract 具有不同的用途,但它们都是 Java 编程中的重要工具。通过适当使用它们,您可以编写更健壮、更灵活、更易于维护的代码,这些代码符合设计原则并满足特定需求。无论是创建不可变实体还是建立公共接口,final 和 abstract 关键字都有助于开发高质量的 Java 应用程序。