Java 中类的组成成分有哪些?
Java 中类的组成成分有哪些?

在 Java 中,类是构成程序的基本单元。类由以下几个部分组成:
类名:用于标识类的名称。
修饰符:用于控制类的访问权限。
成员变量:用于存储类的数据。
成员方法:用于定义类的行为。
构造方法(构造器):用于创建类的实例。
内部类:【成员、静态、局部、匿名】可以将一个类的定义放在另外一个类的定义内部。
代码块:【静态、局部、构造、同步】用于在类中定义一段代码,该代码块可以被多个成员方法访问。
1. 类名
类名是类的标识符,必须遵循以下规则:
-
必须以字母、下划线或美元符号开头。
-
只能包含字母、数字、下划线和美元符号。
-
不能使用 Java 关键字。
2. 修饰符
修饰符用于控制类的访问权限。Java 中的修饰符包括:
-
public:公共的,可以在任何地方访问。
-
protected:受保护的,只能在类本身及其子类中访问。
-
package-private:缺省,只有在同一个包中的类才能访问。
-
private:私有的,只能在类内部访问。
3. 成员变量
成员变量用于存储类的数据。成员变量可以是任何 Java 数据类型,包括基本数据类型和引用数据类型。
4. 成员方法
成员方法用于定义类的行为。成员方法可以是任何 Java 数据类型,包括基本数据类型和引用数据类型。
5. 构造方法
构造方法用于创建类的实例。构造方法的名称必须与类名相同,并且不能指定返回值类型。
6.内部类
可以将一个类的定义放在另外一个类的定义内部,可以提高代码的 结构性 和 可维护性。
成员内部类
成员内部类是最常见的内部类,它和外部类的成员变量一样,定义在类的内部,可以声明访问修饰符。
特点:
- 可以访问外部类的所有成员(包括私有成员和静态成员)。
- 不可以定义静态成员和方法,因为内部类是外部类的一个成员,只有当外部类初始化时,内部类才能初始化,静态变量属于类级别,在类加载的时候就初始化,所以两者本身在语法上就有矛盾。
- 但可以定义常量。
public class OuterClass {
private int num = 10;
public class InnerClass {
public void printNum() {
System.out.println(num); // 可以访问外部类的私有成员
}
}
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
innerClass.printNum();
}
}

代码功能:
定义一个 Car 类,用于表示一辆汽车
定义一个 Engine 类,用于表示汽车发动机
创建一辆奥迪 A8L 汽车并设置其属性
创建一辆宝马 X5 汽车并设置其属性
代码特点:
使用了成员内部类来定义 Engine 类
Engine 类可以访问 Car 类的所有成员,包括私有成员
使用了链式调用来设置 Car 对象的属性
代码示例:
点击查看代码
public class App {
/**
* 当一个类的内部,包含了一个完整的事物,且这个事物没有必要单独设计时,就可以把这个事物设计成内部类。
*
* 成员内部类 就是类中的一个普通成员,类似前面我们学过的普通的成员变量、成员方法。
*/
public static void main(String[] args) {
// 外部类名.内部类名 对象名 = new 外部类(...).new 内部类(...);
// 创建奥迪汽车
Car audiA8L = new Car()
.brand("奥迪")
.style("A8L")
.price(888888);
Car.Engine engine_A8L = audiA8L.new Engine("黑色", 3.0, 90, "95 辛烷值");
audiA8L.setEngine(engine_A8L);
System.out.println(audiA8L);
// 创建宝马汽车
Car bmwX5 = new Car()
.brand("宝马")
.style("X5")
.price(999999);
Car.Engine engine_X5 = bmwX5.new Engine("白色", 4.0, 95, "98 辛烷值");
bmwX5.setEngine(engine_X5);
System.out.println(bmwX5);
}
}
/**
* 定义一个 `Car` 类,用于表示一辆汽车
*/
class Car {
/**
* 汽车品牌
*/
private String brand;
/**
* 汽车款式
*/
private String style;
/**
* 汽车价格
*/
private double price;
private Engine engine;
/**
* 无参构造函数,创建一个没有任何属性值的汽车对象
*/
public Car() {
}
/**
* 带参构造函数,创建一个指定品牌、款式和价格的汽车对象
*
* @param brand 汽车品牌
* @param style 汽车款式
* @param price 汽车价格
* @param engine 汽车引擎
*/
public Car(String brand, String style, double price, Car.Engine engine) {
this.brand = brand;
this.style = style;
this.price = price;
this.engine = engine;
}
/**
* 获取汽车品牌
*
* @return 汽车品牌
*/
public String getBrand() {
return this.brand;
}
/**
* 设置汽车品牌
*
* @param brand 汽车品牌
*/
public void setBrand(String brand) {
this.brand = brand;
}
/**
* 获取汽车款式
*
* @return 汽车款式
*/
public String getStyle() {
return this.style;
}
/**
* 设置汽车款式
*
* @param style 汽车款式
*/
public void setStyle(String style) {
this.style = style;
}
/**
* 获取汽车价格
*
* @return 汽车价格
*/
public double getPrice() {
return this.price;
}
/**
* 设置汽车价格
*
* @param price 汽车价格
*/
public void setPrice(double price) {
this.price = price;
}
public Engine getEngine() {
return this.engine;
}
public void setEngine(Engine engine) {
this.engine = engine;
}
/**
* 设置汽车品牌并返回当前对象,用于链式调用
*
* @param brand 汽车品牌
* @return 当前对象
*/
public Car brand(String brand) {
setBrand(brand);
return this;
}
/**
* 设置汽车款式并返回当前对象,用于链式调用
*
* @param style 汽车款式
* @return 当前对象
*/
public Car style(String style) {
setStyle(style);
return this;
}
/**
* 设置汽车价格并返回当前对象,用于链式调用
*
* @param price 汽车价格
* @return 当前对象
*/
public Car price(double price) {
setPrice(price);
return this;
}
/**
* 创建一个 `Engine` 对象,并将其设置到当前 `Car` 对象中。
*
* @param color 发动机颜色
* @param displacement 发动机排量(单位:升)
* @param stroke 发动机行程(单位:毫米)
* @param gasolineType 使用的汽油类型
* @return 当前 `Car` 对象
*/
public Engine createEngine(String color, double displacement, int stroke, String gasolineType) {
Engine engine = new Engine(color, displacement, stroke, gasolineType);
this.engine = engine;
return engine;
}
/**
* 重写 `toString()` 方法,定义如何将 `Car` 对象转换为字符串
*
* @return 表示汽车信息的字符串
*/
@Override
public String toString() {
return "{" +
" 汽车品牌='" + getBrand() + "'" +
",汽车款式='" + getStyle() + "'" +
",汽车价格='" + getPrice() + "'" +
",汽车引擎=" + getEngine().toString() + // 调用 getEngine().toString() 输出 Engine 的信息
"}";
}
/**
* 定义一个 `Engine` 类,用于表示汽车发动机
*/
class Engine {
/**
* 发动机颜色
*/
private String color;
/**
* 发动机排量(单位:升)
*/
private double displacement;
/**
* 发动机行程(单位:毫米)
*/
private int stroke;
/**
* 使用的汽油类型
*/
private String gasolineType;
/**
* 创建一个发动机对象,指定其颜色、排量、行程和汽油类型
*
* @param color 发动机颜色
* @param displacement 发动机排量(升)
* @param stroke 发动机行程(毫米)
* @param gasolineType 使用的汽油类型
*/
public Engine(String color, double displacement, int stroke, String gasolineType) {
this.color = color;
this.displacement = displacement;
this.stroke = stroke;
this.gasolineType = gasolineType;
}
/**
* 获取发动机颜色
*
* @return 发动机颜色
*/
public String getColor() {
return color;
}
/**
* 设置发动机颜色
*
* @param color 发动机颜色
*/
public void setColor(String color) {
this.color = color;
}
/**
* 获取发动机排量
*
* @return 发动机排量(升)
*/
public double getDisplacement() {
return displacement;
}
/**
* 设置发动机排量
*
* @param displacement 发动机排量(升)
*/
public void setDisplacement(double displacement) {
this.displacement = displacement;
}
/**
* 获取发动机行程
*
* @return 发动机行程(毫米)
*/
public int getStroke() {
return stroke;
}
/**
* 设置发动机冲程
*
* @param stroke 发动机冲程(毫米)
*/
public void setStroke(int stroke) {
this.stroke = stroke;
}
/**
* 获取使用的汽油类型
*
* @return 使用的汽油类型
*/
public String getGasolineType() {
return gasolineType;
}
/**
* 设置使用的汽油类型
*
* @param gasolineType 使用的汽油类型
*/
public void setGasolineType(String gasolineType) {
this.gasolineType = gasolineType;
}
/**
* 重写 `toString()` 方法,定义如何将 `Engine` 对象转换为字符串
*
* @return 表示发动机信息的字符串
*/
@Override
public String toString() {
return "{" +
"颜色='" + color + '\'' +
",排量=" + displacement + "L" +
",冲程=" + stroke + "mm" +
",汽油类型='" + gasolineType + '\'' +
'}';
}
}
}
静态内部类
静态内部类与成员内部类类似,但它属于外部类的静态成员,与外部类的实例无关。
特点:
-
可以访问外部类的静态成员,但不能访问外部类的非静态成员(包括私有成员)。
-
可以定义静态成员和方法。
public class OuterClass {
private static int num = 10;
public static class InnerClass {
public static void printNum() {
System.out.println(num); // 可以访问外部类的静态成员
}
}
public static void main(String[] args) {
OuterClass.InnerClass.printNum(); // 不需要创建外部类的实例
}
}
局部内部类-鸡肋,食之无味···
局部内部类定义在方法或代码块中,只能在该方法或代码块内访问。
特点:
-
可以访问该方法或代码块中的所有变量,包括局部变量。
-
只能在定义它的方法或代码块内使用。
public class OuterClass {
public void printNum() {
int num = 10;
class InnerClass {
public void print() {
System.out.println(num); // 可以访问局部变量
}
}
InnerClass innerClass = new InnerClass();
innerClass.print();
}
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
outerClass.printNum();
}
}
匿名内部类-重点
匿名内部类是局部内部类的简写形式,没有类名,直接使用 new 操作符创建。
特点:
-
可以访问该方法或代码块中的所有变量,包括局部变量。
-
只需创建一次,不能使用类名引用。
public class App {
public static void main(String[] args) {
Cat cat = new Cat();
cat.eat();// 猫吃鱼~~~
new Animal() {
public void eat() {
System.out.println("猫吃鱼~~~");
}
}.eat();
}
}
abstract class Animal {
public abstract void eat();
}
class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼~~~");
}
}
7.代码块
静态代码块
定义: 使用 static {} 包裹起来的代码片段。
特点:
- 仅执行一次,在类加载时执行,且优先于构造代码块执行。
- 属于类,与对象无关,所有该类的对象共享该代码块中的内容。
- 常用于初始化静态成员变量、注册驱动程序等。
public class StaticCodeBlock {
static {
System.out.println("静态代码块");
}
public StaticCodeBlock() {
System.out.println("构造代码块");
}
public static void main(String[] args) {
new StaticCodeBlock();
new StaticCodeBlock();
}
}
静态代码块
构造代码块
构造代码块
构造代码块
定义: 直接在类中定义且没有加 static 关键字的代码块。
特点:
- 在创建对象时被调用,每次创建对象都会被调用,且优先于类构造函数执行。
- 属于对象,与类无关,每个对象都有自己的代码块副本。
- 常用于初始化成员变量、执行一些初始化操作等。
public class ConstructorCodeBlock {
private int num;
{
num = 10;
System.out.println("构造代码块");
}
public ConstructorCodeBlock() {
System.out.println("构造函数");
}
public static void main(String[] args) {
new ConstructorCodeBlock();
new ConstructorCodeBlock();
}
}
构造代码块
构造函数
构造代码块
构造函数
普通代码块
定义: 在方法或语句中出现的 {} 就称为普通代码块。
特点:
- 作用域仅限于该 {} 内,离开 {} 后其内部的变量空间会被回收。
- 常用于控制流程、局部变量声明等。
public class NormalCodeBlock {
public static void main(String[] args) {
int num = 1;
{
int a = 2;
System.out.println("普通代码块:" + num + ", " + a);
}
// System.out.println(a); // 编译错误,a 无法访问
}
}
普通代码块:1, 2
同步代码块
定义: 使用 synchronized 关键字包裹起来的代码块。
特点:
- 同步代码块中的代码只能由一个线程执行,其它线程试图进入该代码块时会阻塞,直到该线程执行完毕。
- 常用于解决多线程并发访问问题,保证数据的完整性和一致性。
```public class SynchronizedCodeBlock {
private int num = 0;
public void increase() {
synchronized (this) {
num++;
}
}
public static void main(String[] args) {
SynchronizedCodeBlock scb = new SynchronizedCodeBlock();
for (int i = 0; i < 10; i++) {
new Thread(() -> {
for (int j = 0; j < 1000; j++) {
scb.increase();
}
}).start();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(scb.num); // 10000
}
}
10000
浙公网安备 33010602011771号