文章目录
3.2.1 类的定义
在Java中,类的定义是创建对象的基础。类定义了对象的属性(成员变量)和方法(成员函数),以及对象的行为和状态。以下是类定义的基本步骤和组成部分:
1. 类的声明
使用class
关键字来声明一个类。类名通常采用大驼峰命名法(首字母大写,不使用下划线)。
public class ClassName {
// 类体
}
2. 成员变量
成员变量是类的一部分,用于存储对象的状态。它们可以是私有的(private
)或公有的(public
),具体取决于访问权限的需求。
private int age; // 私有成员变量
public String name; // 公有成员变量
3. 构造方法
构造方法是在创建对象时用于初始化对象的特殊方法。它的名称必须与类名相同,并且没有返回类型。
public ClassName(int initialAge) {
age = initialAge;
}
4. 方法
方法定义了对象的行为。它们可以是公有的或私有的,具体取决于是否需要在类的外部调用。
public void displayInfo() {
System.out.println("Name: " + name + ", Age: " + age);
}
5. 静态变量和静态方法
静态变量和方法属于类本身,而不是类的任何特定对象。它们可以通过类名直接访问。
public static int count = 0; // 静态变量
public static void displayCount() {
System.out.println("Number of objects: " + count);
}
6. 访问修饰符
Java提供了四种访问修饰符来控制成员的可见性:
public
:可以被任何其他类访问。private
:只能被定义它的类访问。protected
:可以被同一包内的类或不同包中的子类访问。- 默认(无修饰符):可以被同一包内的类访问。
7. 完整的类定义示例
public class Person {
private String name;
private int age;
// 构造方法
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 公有方法
public void displayInfo() {
System.out.println("Name: " + name + ", Age: " + age);
}
// 私有方法
private void think() {
System.out.println(name + " is thinking.");
}
// 静态方法
public static void main(String[] args) {
Person person1 = new Person("Alice", 30);
person1.displayInfo();
}
}
在这个示例中,Person
类有两个私有成员变量name
和age
,一个构造方法,一个公有方法displayInfo
,一个私有方法think
,以及一个静态方法main
。main
方法用于创建Person
对象并调用其方法。
3.2.2 对象的创建与使用
好的,让我们更详细地探讨Java中对象的创建和使用。
对象的创建
- 定义类:首先,你需要定义一个类,这个类将作为创建对象的基础。
public class Car {
// 属性(成员变量)
private String brand; // 品牌
private int year; // 生产年份
// 构造方法
public Car(String brand, int year) {
this.brand = brand;
this.year = year;
}
// 方法
public void start() {
System.out.println(brand + " starts.");
}
public void stop() {
System.out.println(brand + " stops.");
}
// Getter和Setter方法
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
}
- 实例化对象:使用
new
关键字和类的构造方法来创建对象。这将分配内存并初始化对象。
public class Main {
public static void main(String[] args) {
// 创建Car类的对象
Car myCar = new Car("Toyota", 2020);
}
}
对象的使用
- 调用方法:一旦对象被创建,就可以使用它的公有方法。
myCar.start(); // 输出: Toyota starts.
myCar.stop(); // 输出: Toyota stops.
- 访问属性:可以通过公有的getter和setter方法来访问和修改对象的私有属性。
// 访问属性
String carBrand = myCar.getBrand(); // 获取品牌
int carYear = myCar.getYear(); // 获取生产年份
// 修改属性
myCar.setBrand("Honda");
myCar.setYear(2019);
- 对象的内存管理:Java使用自动垃圾回收机制来管理对象的内存。当对象没有任何引用指向它时,垃圾回收器会在适当的时候回收其占用的内存。
封装
封装是面向对象编程的一个核心概念,它允许隐藏对象的内部状态和实现细节,只通过方法暴露接口。
public class Car {
private String brand; // 私有属性,外部无法直接访问
// 构造方法
public Car(String brand) {
this.brand = brand;
}
// 公有方法
public void start() {
System.out.println(brand + " starts.");
}
// Getter方法
public String getBrand() {
return brand;
}
// Setter方法
public void setBrand(String brand) {
this.brand = brand;
}
}
构造方法的重载
构造方法的重载允许你为类定义多个构造方法,每个构造方法可以有不同的参数列表。
public class Car {
private String brand;
private int year;
// 无参构造方法
public Car() {
this.brand = "Unknown";
this.year = 0;
}
// 带品牌参数的构造方法
public Car(String brand) {
this.brand = brand;
this.year = 0;
}
// 带品牌和年份参数的构造方法
public Car(String brand, int year) {
this.brand = brand;
this.year = year;
}
}
创建多个对象
可以创建多个对象,每个对象都有自己的属性和方法。
public class Main {
public static void main(String[] args) {
Car car1 = new Car("Toyota", 2020);
Car car2 = new Car("Honda", 2019);
car1.start();
car2.start();
}
}
总结
通过这些步骤,可以在Java中创建和使用对象,实现面向对象编程的各种功能。对象的创建和使用涉及到类的实例化、属性的访问和修改、方法的调用,以及内存管理等方面。封装、构造方法的重载和垃圾回收是Java中对象创建和使用过程中的重要概念。
3.2.3 对象的引用传递
在Java中,对象的引用传递是指在方法调用时,对象的引用(而不是对象本身)被传递给方法。这意味着方法接收的是对象引用的副本,而这个副本指向原始对象。因此,当方法内部对对象进行修改时,这些修改会影响到原始对象。
引用传递的概念
在Java中,所有的变量都是通过引用传递的。这意味着无论是基本数据类型(如int、double等)还是对象,都是通过它们的引用来传递的。对于基本数据类型,传递的是值的副本,而对于对象,传递的是引用的副本。
示例解释
下面是一个简单的示例,说明对象的引用传递:
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
// 修改对象的状态
public void changeName(String newName) {
name = newName;
}
}
public class Main {
public static void main(String[] args) {
Person person = new Person("Alice");
System.out.println("Before: " + person.name); // 输出: Before: Alice
changePersonName(person, "Bob");
System.out.println("After: " + person.name); // 输出: After: Bob
}
public static void changePersonName(Person person, String newName) {
person.changeName(newName);
}
}
在这个例子中:
Person
类有一个私有属性name
和一个修改这个属性的方法changeName
。- 在
main
方法中,创建了一个Person
对象,并初始化其name
为"Alice"。 changePersonName
方法接收一个Person
对象的引用和一个新的名字。在这个方法内部,调用了changeName
方法来修改对象的name
属性。- 因为对象是通过引用传递的,所以当
changePersonName
方法修改了传入的Person
对象的name
属性时,原始对象的name
也被修改了。
引用传递的影响
由于Java中对象是通过引用传递的,所以在方法内部对对象属性的任何修改都会反映到原始对象上。这允许方法能够修改对象的状态,而不仅仅是返回一个新的状态。
注意事项
- 不可变性:如果你希望对象在方法调用后保持不变,可以考虑使用不可变对象。不可变对象一旦创建,其状态就不能被改变。
- 深拷贝与浅拷贝:在处理对象的引用传递时,需要考虑深拷贝和浅拷贝的问题。浅拷贝只复制对象的引用,而深拷贝会复制对象及其所有子对象。
通过理解引用传递的概念,你可以更有效地控制对象在方法调用中的行为,以及如何设计方法来处理对象的状态。
3.2.4 访问控制权限
在Java中,访问控制权限是面向对象编程的一个重要概念,它决定了类、方法、构造方法和变量(成员变量)可以被哪些其他代码访问。Java提供了四种访问级别:public
、protected
、private
和默认(无修饰符)。
1. public
- 访问级别:可以被任何其他类访问,无论它们是否在同一个包中。
- 使用场景:当希望类的成员或方法能够被任何其他类访问时使用。
public class MyClass {
public int publicVariable; // 公有变量,任何地方都可以访问
public void publicMethod() { // 公有方法,任何地方都可以访问
// ...
}
}
2. protected
- 访问级别:可以被同一包内的类访问,也可以被不同包中的子类访问。
- 使用场景:当希望类的成员或方法能够被子类访问,但不希望其他包中的类访问时使用。
protected class MyClass {
protected int protectedVariable; // 受保护变量,同一包内或子类可以访问
protected void protectedMethod() { // 受保护方法,同一包内或子类可以访问
// ...
}
}
3. private
- 访问级别:只能在定义它的类内部访问。
- 使用场景:当希望类的成员或方法只被该类自身访问时使用,这是实现封装的一种方式。
class MyClass {
private int privateVariable; // 私有变量,仅在本类中可以访问
private void privateMethod() { // 私有方法,仅在本类中可以访问
// ...
}
}
4. 默认(无修饰符)
- 访问级别:可以被同一包内的类访问,但不能被不同包中的类访问。
- 使用场景:当没有明确指定访问级别,且希望类的成员或方法仅在同一包内可见时使用。
class MyClass {
int defaultVariable; // 默认访问级别变量,同一包内可以访问
void defaultMethod() { // 默认访问级别方法,同一包内可以访问
// ...
}
}
访问控制权限的注意事项
- 封装性:通过使用
private
修饰符,可以隐藏类的内部实现细节,只暴露必要的接口给外部,这是封装的核心。 - 继承:
protected
修饰符允许子类访问父类的成员,这在实现继承时非常有用。 - 接口设计:
public
修饰符常用于定义类的公共接口,确保其他类可以按照预期的方式与类交互。 - 包访问:默认访问级别允许类在同一个包内被访问,这有助于组织代码和控制访问权限。
注意:外部类的访问权限只能是public或default,所以Test类只能使用public修饰或者不写修饰符。局部成员是没有访问权限控制的,因为局部成员只在其所在的作用域内起作用,不可能被其他类访问到,如果在程序中这样编写代码,编译器会报错。