Appearance
面向对象基础
Java 是一门面向对象的编程语言。面向对象编程(OOP)是一种程序设计思想,它将程序中的数据和操作数据的方法封装成对象。
面向对象概述
面向对象 vs 面向过程
text
┌─────────────────────────────────────────────────────────────────┐
│ 面向对象 vs 面向过程 │
├─────────────────────────────────────────────────────────────────┤
│ 面向过程: │
│ - 关注"怎么做" │
│ - 以函数为中心 │
│ - 数据和行为分离 │
│ - 示例:C 语言 │
│ │
│ 面向对象: │
│ - 关注"谁来做" │
│ - 以对象为中心 │
│ - 数据和行为封装在一起 │
│ - 示例:Java、Python │
└─────────────────────────────────────────────────────────────────┘面向对象三大特性
text
┌─────────────────────────────────────────────────────────────────┐
│ 面向对象三大特性 │
├─────────────────────────────────────────────────────────────────┤
│ 1. 封装:隐藏实现细节,提供公共访问方式 │
│ 2. 继承:子类继承父类的属性和方法 │
│ 3. 多态:同一行为具有不同表现形式 │
└─────────────────────────────────────────────────────────────────┘类与对象
类的定义
类是对象的模板,定义了对象的属性和行为。
java
/**
* 学生类:定义学生的属性和行为
*/
public class Student {
// 属性(成员变量)
String name; // 姓名
int age; // 年龄
String major; // 专业
double score; // 成绩
// 方法(成员方法)
/**
* 学习方法
*/
public void study() {
System.out.println(name + "正在学习" + major);
}
/**
* 考试方法
* @param subject 科目
* @param examScore 成绩
*/
public void takeExam(String subject, double examScore) {
this.score = examScore;
System.out.println(name + "参加了" + subject + "考试,成绩:" + examScore);
}
/**
* 自我介绍
*/
public void introduce() {
System.out.println("我是" + name + ",今年" + age + "岁,专业是" + major);
}
}对象的创建和使用
java
public class StudentDemo {
public static void main(String[] args) {
// 创建对象:类名 对象名 = new 类名();
Student student1 = new Student();
// 访问属性:对象名.属性名
student1.name = "张三";
student1.age = 20;
student1.major = "计算机科学";
student1.score = 85.5;
// 调用方法:对象名.方法名()
student1.introduce();
student1.study();
student1.takeExam("Java", 92.0);
// 创建多个对象
Student student2 = new Student();
student2.name = "李四";
student2.age = 21;
student2.major = "软件工程";
student2.introduce();
}
}对象内存分析
text
┌─────────────────────────────────────────────────────────────────┐
│ 对象内存结构 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 栈内存 堆内存 │
│ ┌──────────────┐ ┌─────────────────────────┐ │
│ │ student1 │─────────────>│ name = "张三" │ │
│ │ (引用地址) │ │ age = 20 │ │
│ └──────────────┘ │ major = "计算机科学" │ │
│ │ score = 85.5 │ │
│ ┌──────────────┐ └─────────────────────────┘ │
│ │ student2 │─────────────>│ name = "李四" │ │
│ │ (引用地址) │ │ age = 21 │ │
│ └──────────────┘ │ major = "软件工程" │ │
│ │ score = 0.0 │ │
│ └─────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘构造方法
构造方法用于创建对象时初始化对象的属性。
构造方法定义
java
public class Person {
String name;
int age;
String gender;
// 无参构造方法
public Person() {
System.out.println("无参构造方法被调用");
}
// 带参构造方法
public Person(String name, int age) {
this.name = name; // this 指当前对象
this.age = age;
System.out.println("两参构造方法被调用");
}
// 全参构造方法
public Person(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
System.out.println("全参构造方法被调用");
}
public void show() {
System.out.println("姓名:" + name + ",年龄:" + age + ",性别:" + gender);
}
}构造方法使用
java
public class ConstructorDemo {
public static void main(String[] args) {
// 使用无参构造
Person p1 = new Person();
p1.name = "张三";
p1.age = 25;
p1.show();
// 使用两参构造
Person p2 = new Person("李四", 30);
p2.show();
// 使用全参构造
Person p3 = new Person("王五", 28, "男");
p3.show();
}
}构造方法注意事项
java
public class ConstructorNote {
public static void main(String[] args) {
// 1. 如果没有定义构造方法,系统提供默认无参构造
// 2. 如果定义了有参构造,系统不再提供无参构造
// 3. 构造方法可以重载
// 4. 构造方法没有返回值,连 void 都没有
}
}
class Book {
String title;
double price;
// 构造方法重载
public Book() {
// 调用另一个构造方法(必须放在第一行)
this("未命名", 0.0);
}
public Book(String title) {
this(title, 0.0);
}
public Book(String title, double price) {
this.title = title;
this.price = price;
}
}封装
封装是隐藏对象的属性和实现细节,仅对外提供公共访问方式。
封装实现
java
public class BankAccount {
// 私有属性:外部无法直接访问
private String accountNumber; // 账号
private String owner; // 户主
private double balance; // 余额
// 无参构造
public BankAccount() {
}
// 全参构造
public BankAccount(String accountNumber, String owner, double balance) {
this.accountNumber = accountNumber;
this.owner = owner;
this.balance = balance;
}
// 公共的 getter 方法:获取属性值
public String getAccountNumber() {
return accountNumber;
}
public String getOwner() {
return owner;
}
public double getBalance() {
return balance;
}
// 公共的 setter 方法:设置属性值
public void setAccountNumber(String accountNumber) {
this.accountNumber = accountNumber;
}
public void setOwner(String owner) {
this.owner = owner;
}
// 余额设置需要验证
public void setBalance(double balance) {
if (balance >= 0) {
this.balance = balance;
} else {
System.out.println("余额不能为负数");
}
}
// 存款方法
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
System.out.println("存款成功,当前余额:" + balance);
} else {
System.out.println("存款金额必须大于0");
}
}
// 取款方法
public void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
System.out.println("取款成功,当前余额:" + balance);
} else {
System.out.println("取款失败,余额不足或金额无效");
}
}
// 显示账户信息
public void showInfo() {
System.out.println("账号:" + accountNumber);
System.out.println("户主:" + owner);
System.out.println("余额:" + balance);
}
}封装使用
java
public class EncapsulationDemo {
public static void main(String[] args) {
BankAccount account = new BankAccount("6222000012345678", "张三", 10000);
// 通过 getter 获取属性
System.out.println("户主:" + account.getOwner());
System.out.println("余额:" + account.getBalance());
// 通过方法操作数据
account.deposit(5000);
account.withdraw(3000);
// 不能直接访问私有属性
// account.balance = -100; // 编译错误
// 通过 setter 设置属性(有验证)
account.setBalance(-100); // 输出:余额不能为负数
}
}访问修饰符
text
┌─────────────────────────────────────────────────────────────────┐
│ 访问修饰符权限 │
├─────────────────────────────────────────────────────────────────┤
│ 修饰符 │ 同一类 │ 同一包 │ 子类 │ 其他包 │
├─────────────────────────────────────────────────────────────────┤
│ public │ ✓ │ ✓ │ ✓ │ ✓ │
│ protected │ ✓ │ ✓ │ ✓ │ ✗ │
│ 默认 │ ✓ │ ✓ │ ✗ │ ✗ │
│ private │ ✓ │ ✗ │ ✗ │ ✗ │
└─────────────────────────────────────────────────────────────────┘java
public class AccessModifier {
public int publicVar = 1; // 公共:任何地方可访问
protected int protectedVar = 2; // 受保护:同类、同包、子类可访问
int defaultVar = 3; // 默认:同类、同包可访问
private int privateVar = 4; // 私有:只有同类可访问
public void show() {
// 同一类中都可以访问
System.out.println(publicVar);
System.out.println(protectedVar);
System.out.println(defaultVar);
System.out.println(privateVar);
}
}this 关键字
this 关键字代表当前对象的引用。
java
public class ThisKeyword {
private String name;
private int age;
// 1. 区分成员变量和局部变量
public ThisKeyword(String name, int age) {
this.name = name; // this.name 是成员变量
this.age = age; // name 是参数
}
// 2. 调用本类的其他构造方法
public ThisKeyword() {
this("未知", 0); // 必须放在第一行
}
public ThisKeyword(String name) {
this(name, 0);
}
// 3. 调用本类的方法
public void method1() {
System.out.println("method1");
}
public void method2() {
this.method1(); // 调用本类的 method1
System.out.println("method2");
}
// 4. 返回当前对象
public ThisKeyword getSelf() {
return this; // 返回当前对象
}
// 5. 作为参数传递
public void print(ThisKeyword obj) {
System.out.println(obj.name);
}
public void show() {
print(this); // 将当前对象作为参数传递
}
}static 关键字
static 关键字用于声明静态成员,属于类而不是对象。
静态变量
java
public class StaticVariable {
// 实例变量:每个对象独立拥有
String name;
// 静态变量:所有对象共享
static int count = 0; // 计数器
public StaticVariable(String name) {
this.name = name;
count++; // 每创建一个对象,计数器加1
}
public static void main(String[] args) {
StaticVariable s1 = new StaticVariable("张三");
System.out.println("创建对象数:" + StaticVariable.count); // 1
StaticVariable s2 = new StaticVariable("李四");
System.out.println("创建对象数:" + StaticVariable.count); // 2
StaticVariable s3 = new StaticVariable("王五");
System.out.println("创建对象数:" + StaticVariable.count); // 3
// 静态变量可以通过类名访问(推荐)
// 也可以通过对象访问(不推荐)
System.out.println(s1.count); // 3
System.out.println(s2.count); // 3
}
}静态方法
java
public class StaticMethod {
// 实例变量
String name = "张三";
// 静态变量
static String school = "清华大学";
// 实例方法:可以访问实例变量和静态变量
public void instanceMethod() {
System.out.println(name); // 可以访问实例变量
System.out.println(school); // 可以访问静态变量
}
// 静态方法:只能访问静态变量和静态方法
public static void staticMethod() {
// System.out.println(name); // 编译错误:不能访问实例变量
System.out.println(school); // 可以访问静态变量
// instanceMethod(); // 编译错误:不能调用实例方法
staticMethod2(); // 可以调用静态方法
}
public static void staticMethod2() {
System.out.println("静态方法2");
}
public static void main(String[] args) {
// 静态方法通过类名调用(推荐)
StaticMethod.staticMethod();
// 也可以通过对象调用(不推荐)
StaticMethod obj = new StaticMethod();
obj.staticMethod();
}
}静态代码块
java
public class StaticBlock {
static String name;
static int age;
// 静态代码块:类加载时执行,只执行一次
static {
System.out.println("静态代码块执行");
name = "张三";
age = 25;
}
// 构造代码块:每次创建对象时执行
{
System.out.println("构造代码块执行");
}
public StaticBlock() {
System.out.println("构造方法执行");
}
public static void main(String[] args) {
System.out.println("main方法开始");
// 类加载时,静态代码块先执行
new StaticBlock();
new StaticBlock();
// 输出顺序:
// 静态代码块执行
// main方法开始
// 构造代码块执行
// 构造方法执行
// 构造代码块执行
// 构造方法执行
}
}静态导入
java
// 静态导入:导入类的静态成员
import static java.lang.Math.PI;
import static java.lang.Math.sqrt;
import static java.util.Arrays.sort;
public class StaticImport {
public static void main(String[] args) {
// 直接使用静态成员,无需类名前缀
System.out.println("PI = " + PI);
System.out.println("sqrt(16) = " + sqrt(16));
int[] arr = {3, 1, 2};
sort(arr); // 直接使用 sort 方法
System.out.println(java.util.Arrays.toString(arr));
}
}代码块
java
public class CodeBlock {
static int staticVar;
int instanceVar;
// 静态代码块:类加载时执行
static {
staticVar = 100;
System.out.println("1. 静态代码块");
}
// 构造代码块:每次创建对象时执行,在构造方法之前
{
instanceVar = 200;
System.out.println("2. 构造代码块");
}
// 构造方法
public CodeBlock() {
System.out.println("3. 构造方法");
}
public static void main(String[] args) {
System.out.println("创建第一个对象:");
new CodeBlock();
System.out.println("\n创建第二个对象:");
new CodeBlock();
// 执行顺序:
// 1. 静态代码块(只执行一次)
// 2. 构造代码块
// 3. 构造方法
}
}小结
本章我们学习了:
- 类与对象:类是模板,对象是实例
- 构造方法:用于初始化对象
- 封装:隐藏实现细节,提供公共访问方式
- this 关键字:代表当前对象
- static 关键字:静态成员属于类
- 代码块:静态代码块、构造代码块
下一章,我们将学习 面向对象进阶,了解继承、多态、抽象类和接口。
