65. Java 类和对象 - 创建和使用类与对象:摘要
1. 类声明(Class Declaration)
- 语法:
[修饰符] class 类名 [extends 父类] [implements 接口] {
// 类体:字段(fields)、方法(methods)和构造函数(constructors)
}
- 修饰符:像
public修饰的类,在所有地方都能被访问;若不写修饰符,该类就属于包级私有,只能在同一个包内被访问。 - 类体:包含字段(用于表示对象的状态)、方法(用于表示对象的行为)以及构造函数(用于对象的初始化)。
示例:
// 声明一个公共类 Person
public class Person {
// 类体部分
}
在这个例子中,Person 类被声明为 public,意味着它可以被任何包中的代码访问。
2. 字段(Fields)
- 实例变量:没有
static修饰符,属于对象本身。每个对象实例都会有该实例变量的一份独立拷贝。 - 类变量:带有
static修饰符,所有对象共享这一个变量,它属于类本身。 - 访问修饰符:例如
private、public、protected或者包级私有(不写修饰符),这些修饰符控制着其他类对该字段的可见性。
示例:
public class Car {
// 实例变量,每个 Car 对象都有自己的 color
private String color;
// 类变量,所有 Car 对象共享同一个 wheelsCount
public static int wheelsCount = 4;
}
在这个 Car 类中,color 是实例变量,每个 Car 对象都有自己的 color 值;wheelsCount 是类变量,所有 Car 对象共享这个值。
3. 方法(Methods)
- 声明:包含修饰符(如
public、private等)、返回类型(如void、int、自定义类等)、方法名和可选的参数列表。 - 实例方法:没有
static修饰符,必须通过对象引用来调用,例如myObj.methodName()。 - 类方法(
static):属于类本身,可以使用ClassName.methodName()调用,也可以用实例引用调用,但不建议这么做,因为这会混淆类方法和实例方法的区别。 - 访问修饰符:和字段的访问修饰符类似,用于控制方法的可见性。
示例:
public class Calculator {
// 实例方法
public int add(int a, int b) {
return a + b;
}
// 类方法
public static int multiply(int a, int b) {
return a * b;
}
}
// 使用示例
public class Main {
public static void main(String[] args) {
Calculator calc = new Calculator();
// 调用实例方法
int sum = calc.add(2, 3);
// 调用类方法
int product = Calculator.multiply(2, 3);
}
}
在 Calculator 类中,add 是实例方法,需要通过 Calculator 对象来调用;multiply 是类方法,可以直接通过类名调用。
4. 构造函数(Constructors)
-
特征:
- 名称和类名相同。
- 没有返回类型(甚至不是
void)。 - 用于初始化对象的字段。
-
声明:
public ClassName(参数列表) {
// 初始化逻辑
}
- 可以声明多个重载的构造函数,只要参数列表不同,调用时就会根据传入的参数匹配合适的构造函数。
示例:
public class Student {
private String name;
private int age;
// 无参构造函数
public Student() {
this.name = "Unknown";
this.age = 0;
}
// 有参构造函数
public Student(String name, int age) {
this.name = name;
this.age = age;
}
}
在 Student 类中有两个构造函数,一个是无参构造函数,用于将 name 初始化为 "Unknown",age 初始化为 0;另一个是有参构造函数,根据传入的参数来初始化 name 和 age。
5. 访问级别修饰符(Access Modifiers)
- public:在所有地方都可见。
- protected:在同一个包内可见,并且不同包的子类也可见。
- 无修饰符(包级私有):只在同一个包内可见。
- private:只能在类本身内部可见。
示例:
// 包 com.example
package com.example;
public class Parent {
public int publicField;
protected int protectedField;
int packagePrivateField;
private int privateField;
public Parent() {
publicField = 1;
protectedField = 2;
packagePrivateField = 3;
privateField = 4;
}
}
// 同一个包内的类
class SamePackageClass {
public static void main(String[] args) {
Parent parent = new Parent();
System.out.println(parent.publicField);
System.out.println(parent.protectedField);
System.out.println(parent.packagePrivateField);
// 下面这行代码会报错,因为 privateField 只能在 Parent 类内部访问
// System.out.println(parent.privateField);
}
}
// 不同包的子类
package com.another;
import com.example.Parent;
class Child extends Parent {
public void accessParentFields() {
System.out.println(publicField);
System.out.println(protectedField);
// 下面这行代码会报错,因为 packagePrivateField 不在同一个包内
// System.out.println(packagePrivateField);
// 下面这行代码会报错,因为 privateField 只能在 Parent 类内部访问
// System.out.println(privateField);
}
}
这个示例展示了不同访问修饰符的作用范围。
6. 使用 new 创建对象
ClassName objRef = new ClassName(参数列表);
new运算符会分配内存并调用相应的构造函数来初始化对象,然后返回对象的引用。- 可以把返回的引用赋值给变量,也可以直接使用(不保留引用)。
示例:
public class Dog {
private String breed;
public Dog(String breed) {
this.breed = breed;
}
public String getBreed() {
return breed;
}
}
public class Main {
public static void main(String[] args) {
// 创建 Dog 对象并将引用赋值给变量
Dog myDog = new Dog("Golden Retriever");
System.out.println(myDog.getBreed());
// 直接使用对象,不保留引用
System.out.println(new Dog("Poodle").getBreed());
}
}
在这个例子中,使用 new 运算符创建了 Dog 对象,一个将引用赋值给了 myDog 变量,另一个直接使用了创建的对象。
7. 访问实例成员和方法
- 访问实例字段:
objectReference.fieldName
- 调用实例方法:
objectReference.methodName(arguments)
- 如果字段或方法是
public,在类外部就可以通过对象引用访问;如果是private,只能在类内部访问。
示例:
public class Book {
public String title;
private int pages;
public Book(String title, int pages) {
this.title = title;
this.pages = pages;
}
public int getPages() {
return pages;
}
}
public class Main {
public static void main(String[] args) {
Book myBook = new Book("Java Programming", 300);
// 访问 public 字段
System.out.println(myBook.title);
// 调用 public 方法来访问 private 字段
System.out.println(myBook.getPages());
// 下面这行代码会报错,因为 pages 是 private 字段
// System.out.println(myBook.pages);
}
}
在 Book 类中,title 是 public 字段,可以直接通过对象引用访问;pages 是 private 字段,需要通过 getPages 方法来访问。
8. 垃圾回收(Garbage Collection)
- Java 的垃圾回收器会自动回收不再被引用的对象。
- 如果没有任何变量(或其他对象)引用某个对象,该对象就被认为 “可被回收”。
- 也可以通过将某个引用设为
null来显式删除引用,但具体何时进行回收由虚拟机决定。
示例:
public class MyObject {
public void doSomething() {
System.out.println("Doing something...");
}
}
public class Main {
public static void main(String[] args) {
MyObject obj = new MyObject();
obj.doSomething();
// 显式删除引用
obj = null;
// 此时 obj 所引用的对象可能会被垃圾回收器回收
}
}
在这个例子中,将 obj 引用设为 null 后,原本 obj 所引用的 MyObject 对象就可能会被垃圾回收器回收。
关键点总结
- 类为对象提供了蓝图;字段用于表示对象的状态,方法用于表示对象的行为,构造函数用于对象的初始化。
static修饰符:能让字段或方法成为类成员,而不是对象成员。- 访问修饰符:决定了类或成员对外的可见范围。通常遵循最小可见原则来保护实现细节。
- 实例化对象:使用
new加上调用构造函数来创建对象,并返回对象的引用。 - 访问对象成员:通过
objectReference.fieldName或objectReference.methodName()来访问。 - 垃圾回收:不再被使用(没有引用)的对象会被自动回收,无需手动释放内存。