Java 类
最后修改于 2024 年 1 月 27 日
在本文中,我们将展示如何在 Java 中使用类。
Java 常规类
class 关键字用于定义类,类是创建对象的模板。这些对象被称为类的实例。 使用 new 关键字创建一个新类。
在类中,我们定义成员字段和成员函数。类中定义的函数称为方法。成员字段和函数通过点运算符访问。
package com.zetcode;
import java.util.Objects;
class User {
private String name;
private String occupation;
public User(String name, String occupation) {
this.name = name;
this.occupation = occupation;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getOccupation() {
return occupation;
}
public void setOccupation(String occupation) {
this.occupation = occupation;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("User{");
sb.append("name='").append(name).append('\'');
sb.append(", occupation='").append(occupation).append('\'');
sb.append('}');
return sb.toString();
}
}
public class RegularClassEx {
public static void main(String[] args) {
var u = new User("John Doe", "gardener");
System.out.println(u);
System.out.println(u.getName());
System.out.println(u.getOccupation());
}
}
在该程序中,我们定义了 User 类。 该类有两个字段:name 和 occupation。 在该类中,我们还定义了用于获取和设置字段的 getter 和 setter 方法,以及用于表示类字符串形式的 toString 方法。
class User {
...
}
class 关键字用于定义类。在花括号对内部,我们定义类的正文。
private String name; private String occupation;
定义了两个 String 字段。
public User(String name, String occupation) {
this.name = name;
this.occupation = occupation;
}
这是类的构造函数;它是一种特殊的方法,与类具有相同的名称。创建类的实例时会调用它。在我们的例子中,我们在构造函数中初始化我们的字段。
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getOccupation() {
return occupation;
}
public void setOccupation(String occupation) {
this.occupation = occupation;
}
对于访问私有字段,我们定义了两个 getter 和 setter 方法。
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("User{");
sb.append("name='").append(name).append('\'');
sb.append(", occupation='").append(occupation).append('\'');
sb.append('}');
return sb.toString();
}
要获取对象的字符串表示形式,我们定义了 toString 方法。 当我们将对象传递给 System.out.println 方法时,将调用该方法。
var u = new User("John Doe", "gardener");
使用 new 关键字创建一个新的 User 类实例。 此时,将调用该类的构造函数。 我们将两个字符串参数传递给构造函数。
System.out.println(u);
调用该类的 toString 方法。
System.out.println(u.getName()); System.out.println(u.getOccupation());
在 user 对象上,我们调用 getName 和 getOccupation 方法。 使用点运算符调用这些方法。
$ java com.zetcode.RegularClassEx
User{name='John Doe', occupation='gardener'}
John Doe
gardener
Java 抽象类
抽象类是一个未完成的类。 它必须在其子类中实现。 使用 abstract 关键字创建抽象类。 我们可以创建抽象方法和成员字段。
抽象类的目的是为派生类提供一个通用的定义。
抽象类无法实例化。 如果一个类包含至少一个抽象方法,它也必须声明为抽象的。 抽象方法无法实现;它们仅声明方法的签名。
package com.zetcode;
abstract class Drawing {
protected int x = 0;
protected int y = 0;
public abstract double area();
public String getCoordinates() {
return String.format("x: %d, y: %d", this.x, this.y);
}
}
class Circle extends Drawing {
private int r;
public Circle(int x, int y, int r) {
this.x = x;
this.y = y;
this.r = r;
}
@Override
public double area() {
return this.r * this.r * Math.PI;
}
@Override
public String toString() {
return String.format("Circle at x: %d, y: %d, radius: %d",
this.x, this.y, this.r);
}
}
public class AbstractClassEx {
public static void main(String[] args) {
Circle c = new Circle(12, 45, 22);
System.out.println(c);
System.out.format("Area of circle: %f%n", c.area());
System.out.println(c.getCoordinates());
}
}
我们有一个抽象的基类 Drawing。 该类定义了两个成员字段,定义了一个方法并声明了一个方法。 其中一个方法是抽象的,另一个方法是完全实现的。 Drawing 类是抽象的,因为我们无法绘制它。 我们可以绘制一个圆圈、一个点或一个正方形,但我们无法绘制一个“绘图”。 Drawing 类对于我们可以绘制的对象具有一些常见的功能。
abstract class Drawing {
我们使用 abstract 关键字来定义一个抽象类。
public abstract double area();
抽象方法也以 abstract 关键字开头。 Drawing 类是一个想法。 它是虚幻的,我们无法为其实现 area 方法。 这是我们使用抽象方法的情况。 该方法将在更具体的实体(如圆圈)中实现。
class Circle extends Drawing {
Circle 是 Drawing 类的子类。 因此,它必须实现抽象的 area 方法。
@Override
public double area() {
return this.r * this.r * Math.PI;
}
在这里,我们正在实现 area 方法。
$ java com.zetcode.AbstractClass Circle at x: 12, y: 45, radius: 22 Area of circle: 1520.530844 x: 12, y: 45
我们创建一个 Circle 对象并打印其面积和坐标。
Java 嵌套类
可以在另一个类中定义一个类。 在 Java 术语中,这样的类称为嵌套类。 不是嵌套类的类称为顶级类。
Java 有四种类型的嵌套类
- 静态嵌套类
- 内部类
- 局部类
- 匿名类
使用嵌套类可以提高代码的可读性并改善代码的组织。 内部类通常用作 GUI 中的回调。 例如,在 Java Swing 工具包中。
Java 静态嵌套类
静态嵌套类是一个嵌套类,可以在不使用封闭类实例的情况下创建。 它可以访问封闭类的静态变量和方法。
package com.zetcode;
public class SNCTest {
private static int x = 5;
static class Nested {
@Override
public String toString() {
return "This is a static nested class; x:" + x;
}
}
public static void main(String[] args) {
SNCTest.Nested sn = new SNCTest.Nested();
System.out.println(sn);
}
}
该示例展示了一个静态嵌套类。
private static int x = 5;
这是 SNCTest 类的私有静态变量。 静态嵌套类可以访问它。
static class Nested {
@Override
public String toString() {
return "This is a static nested class; x:" + x;
}
}
定义了一个静态嵌套类。 它有一种方法,用于打印一条消息并引用静态变量 x。
SNCTest.Nested sn = new SNCTest.Nested();
点运算符用于引用嵌套类。
$ java com.zetcode.SNCTest This is a static nested class; x:5
Java 内部类
普通类或顶级类的实例可以独立存在。 相比之下,内部类的实例无法在不绑定到顶级类的情况下进行实例化。 内部类也称为成员类。 它们属于封闭类的实例。 内部类可以访问封闭类的成员。
package com.zetcode;
public class InnerClassTest {
private int x = 5;
class Inner {
@Override
public String toString() {
return "This is Inner class; x:" + x;
}
}
public static void main(String[] args) {
InnerClassTest nc = new InnerClassTest();
InnerClassTest.Inner inner = nc.new Inner();
System.out.println(inner);
}
}
嵌套类在 InnerClassTest 类中定义。 它可以访问成员变量 x。
class Inner {
@Override
public String toString() {
return "This is Inner class; x:" + x;
}
}
Inner 类在 InnerClassTest 类的正文中定义。
InnerClassTest nc = new InnerClassTest();
首先,我们需要创建顶级类的实例。 内部类不能在没有封闭类实例的情况下存在。
InnerClassTest.Inner inner = nc.new Inner();
实例化顶级类后,我们可以创建内部类的实例。
$ java com.zetcode.InnerClassTest This is Inner class; x:5
这是 com.zetcode.InnerClassTest 程序的输出。
Java 局部类
局部类是内部类的一种特殊情况。 局部类是在块中定义的类。(块是花括号之间的一组零个或多个语句。)局部类可以访问其封闭类的成员。
此外,如果局部变量声明为 final,则局部类可以访问这些变量。 造成这种情况的原因是技术性的。 局部类的实例的生存期可能比定义该类的方法的执行时间长得多。 为了解决这个问题,局部变量被复制到局部类中。 为了确保以后不更改它们,必须将它们声明为 final。
局部类不能是 public、private、protected 或 static。 不允许将它们用于局部变量声明或局部类声明。 除了声明为 static 和 final 的常量外,局部类不能包含静态字段、方法或类。
package com.zetcode;
public class LocalClassEx {
public static void main(String[] args) {
final int x = 5;
class Local {
@Override
public String toString() {
return "This is Local class; x:" + x;
}
}
Local loc = new Local();
System.out.println(loc);
}
}
局部类在 main 方法的正文中定义。
@Override
public String toString() {
return "This is Local class; x:" + x;
}
如果将局部变量声明为 final,则局部类可以访问这些变量。
Java 匿名类
匿名类是没有名称的局部类。 它们使我们能够同时声明和实例化一个类。 如果我们只想使用一次该类,则可以使用匿名类。 匿名类在一个表达式中定义和实例化。 匿名内部类也用于事件处理代码仅由一个组件使用,因此不需要命名引用的情况。
匿名类必须实现接口或从类继承。 但是不使用 implements 和 extends 关键字。 如果 new 关键字后面的名称是类的名称,则匿名类是命名类的子类。 如果 new 后面的名称指定了一个接口,则匿名类实现该接口并扩展 Object。
由于匿名类没有名称,因此无法为匿名类定义构造函数。 在匿名类的正文中,我们无法定义任何语句;只能定义方法或成员。
package com.zetcode;
public class AnonymousClass {
interface Message {
public void send();
}
public void createMessage() {
Message msg = new Message() {
@Override
public void send() {
System.out.println("This is a message");
}
};
msg.send();
}
public static void main(String[] args) {
AnonymousClass ac = new AnonymousClass();
ac.createMessage();
}
}
在此代码示例中,我们创建一个匿名类。
interface Message {
public void send();
}
匿名类必须是子类或必须实现一个接口。 我们的匿名类将实现一个 Message 接口。 否则,编译器将无法识别该类型。
public void createMessage() {
Message msg = new Message() {
@Override
public void send() {
System.out.println("This is a message");
}
};
msg.send();
}
匿名类是一个局部类,因此它在方法的正文中定义。 匿名类在表达式中定义;因此,封闭的右括号后跟一个分号。
来源
在本文中,我们讨论了 Java 类。
作者
列出所有Java教程。