【Java零基础·第6章】面向对象(二):构造器、封装、对象数组
一、类与对象的复习
在Java世界里,类就像一个模板,定义了一类事物的共同特征和行为;而对象则是这个模板的具体实例。比如"汽车"是一个类,而你家的那辆红色小轿车就是一个对象。
包的作用
包(Package)就像文件夹,主要作用是:
- 避免类名冲突
- 便于管理大量类
- 控制访问权限
定义包的语法很简单:
package com.example.myapp; // 通常是公司域名倒写+项目名
成员变量的分类
特性 | 静态变量(类变量) | 实例变量(对象变量) |
---|---|---|
修饰符 | 有static | 无static |
存储位置 | 方法区 | 堆内存 |
初始化时机 | 类加载时 | 创建对象时(new) |
访问方式 | 类名.变量名 | 对象.变量名 |
示例:
public class Student {// 静态变量(所有学生共享的学校名称)public static String schoolName = "阳光中学";// 实例变量(每个学生独有的属性)public String name; // 姓名public int age; // 年龄
}
使用方式:
// 访问静态变量
System.out.println(Student.schoolName);// 访问实例变量
Student student = new Student();
student.name = "张三";
System.out.println(student.name);
成员方法的分类
特性 | 静态方法 | 实例方法 |
---|---|---|
修饰符 | 有static | 无static |
能否用this | 不能 | 能 |
访问成员 | 只能访问静态成员 | 可访问所有成员 |
调用方式 | 类名.方法名() | 对象.方法名() |
示例:
public class Calculator {// 静态方法(工具方法)public static int add(int a, int b) {return a + b;}// 实例方法(需要对象状态的方法)private int result;public void accumulate(int num) {this.result += num; // 使用this访问实例变量}
}
二、构造器:对象的"出生证明"
构造器是一种特殊的方法,专门用于创建对象时初始化对象。
构造器的特点
- 名称必须与类名完全相同(包括大小写)
- 没有返回值类型(连void都不能写)
- 当你没写任何构造器时,编译器会自动生成一个无参构造器
- 一旦手动编写了构造器,默认的无参构造器就会消失
构造器示例
package com.example.oop;public class Book {private String title; // 书名private String author; // 作者private double price; // 价格// 无参构造器public Book() {// 可以在这里设置默认值this.title = "未知书名";this.author = "未知作者";}// 有参构造器public Book(String title, String author) {this.title = title;this.author = author;}// 全参构造器public Book(String title, String author, double price) {this.title = title;this.author = author;this.price = price;}// getter和setter方法public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}// 其他getter和setter省略...public String getInfo() {return "《" + title + "》 作者:" + author + " 价格:" + price + "元";}
}
使用构造器创建对象:
public class TestBook {public static void main(String[] args) {// 使用无参构造器Book book1 = new Book();System.out.println(book1.getInfo());// 使用有参构造器Book book2 = new Book("Java编程思想", "Bruce Eckel");book2.setPrice(108.0);System.out.println(book2.getInfo());// 使用全参构造器Book book3 = new Book("深入理解Java虚拟机", "周志明", 89.0);System.out.println(book3.getInfo());}
}
三、封装:对象的"隐私保护"
封装是面向对象的三大特征之一,就像我们用快递盒包装物品一样,隐藏内部细节,只暴露必要的接口。
为什么需要封装?
- 保护数据安全,防止不合理的修改
- 隐藏实现细节,便于维护
- 控制访问权限,明确边界
四种权限修饰符
Java提供了四种权限修饰符,控制类和成员的可见范围:
修饰符 | 本类 | 本包其他类 | 其他包的子类 | 其他包的非子类 |
---|---|---|---|---|
private | √ | × | × | × |
缺省(默认) | √ | √ | × | × |
protected | √ | √ | √ | × |
public | √ | √ | √ | √ |
封装的实现方式
- 将属性私有化(使用private修饰)
- 提供公共的getter和setter方法
示例:
package com.example.encapsulation;public class BankAccount {// 属性私有化private String accountNumber; // 账号private double balance; // 余额// 构造器public BankAccount(String accountNumber) {this.accountNumber = accountNumber;this.balance = 0.0; // 新账户初始余额为0}// 存款方法(带业务逻辑的setter)public void deposit(double amount) {if (amount > 0) {balance += amount;System.out.println("存款成功!存入:" + amount + "元,当前余额:" + balance + "元");} else {System.out.println("存款金额必须大于0!");}}// 取款方法public void withdraw(double amount) {if (amount <= 0) {System.out.println("取款金额必须大于0!");return;}if (amount > balance) {System.out.println("余额不足!当前余额:" + balance + "元");return;}balance -= amount;System.out.println("取款成功!取出:" + amount + "元,当前余额:" + balance + "元");}// getter方法(只允许获取,不允许直接修改)public String getAccountNumber() {return accountNumber;}public double getBalance() {return balance;}
}
使用示例:
public class TestBankAccount {public static void main(String[] args) {BankAccount account = new BankAccount("6222021234567890123");// 尝试直接访问私有属性(编译错误)// System.out.println(account.balance);// 通过公共方法操作account.deposit(1000);account.withdraw(300);account.withdraw(800); // 余额不足的情况account.deposit(-500); // 存入负数的情况System.out.println("账号:" + account.getAccountNumber());System.out.println("最终余额:" + account.getBalance() + "元");}
}
四、标准JavaBean:规范的Java类
JavaBean是一种遵循特定规范的Java类,就像生产标准零件一样,让类的使用更加统一和方便。
JavaBean规范
- 属性私有化(private)
- 提供公共的无参构造器
- 为每个属性提供公共的getter和setter方法
- 重写toString()方法(方便打印)
- 重写equals()和hashCode()方法(方便比较)
示例:
package com.example.bean;import java.util.Objects;public class User {// 属性私有化private Long id;private String username;private String email;private int age;private boolean vip;// 无参构造器public User() {}// 有参构造器(可选)public User(String username, String email) {this.username = username;this.email = email;}// 全参构造器(可选)public User(Long id, String username, String email, int age, boolean vip) {this.id = id;this.username = username;this.email = email;this.age = age;this.vip = vip;}// getter和setter方法public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}// 其他getter和setter省略...// 注意:boolean类型的getter通常以is开头public boolean isVip() {return vip;}public void setVip(boolean vip) {this.vip = vip;}// 重写toString()方法@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", email='" + email + '\'' +", age=" + age +", vip=" + vip +'}';}// 重写equals()方法@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;User user = (User) o;return age == user.age && vip == user.vip && Objects.equals(id, user.id) && Objects.equals(username, user.username) && Objects.equals(email, user.email);}// 重写hashCode()方法@Overridepublic int hashCode() {return Objects.hash(id, username, email, age, vip);}
}
使用示例:
public class TestUser {public static void main(String[] args) {User user1 = new User();user1.setId(1L);user1.setUsername("张三");user1.setEmail("zhangsan@example.com");user1.setAge(25);user1.setVip(true);User user2 = new User(1L, "张三", "zhangsan@example.com", 25, true);User user3 = new User(2L, "李四", "lisi@example.com", 30, false);System.out.println(user1); // 自动调用toString()System.out.println("user1和user2是否相等:" + user1.equals(user2));System.out.println("user1和user3是否相等:" + user1.equals(user3));}
}
五、对象数组:批量管理对象
对象数组就是存储对象引用的数组,就像一个存放多个对象的容器。
对象数组的创建和使用
package com.example.objectarray;public class Product {private String id;private String name;private double price;public Product() {}public Product(String id, String name, double price) {this.id = id;this.name = name;this.price = price;}// getter和setter方法省略...@Overridepublic String toString() {return "商品ID:" + id + ",名称:" + name + ",价格:" + price + "元";}public double getPrice() {return price;}
}
使用对象数组:
public class TestProductArray {public static void main(String[] args) {// 1. 静态初始化Product[] products1 = {new Product("p001", "笔记本电脑", 5999.0),new Product("p002", "智能手机", 3999.0),new Product("p003", "平板电脑", 2999.0)};// 2. 动态初始化Product[] products2 = new Product[3];products2[0] = new Product("p004", "无线鼠标", 99.0);products2[1] = new Product("p005", "机械键盘", 299.0);products2[2] = new Product("p006", "蓝牙耳机", 499.0);// 3. 遍历对象数组System.out.println("所有商品:");for (int i = 0; i < products1.length; i++) {System.out.println(products1[i]);}for (Product p : products2) { // 增强for循环System.out.println(p);}// 4. 对象数组排序(按价格从低到高)System.out.println("\n按价格排序后:");Product[] allProducts = new Product[products1.length + products2.length];// 合并数组System.arraycopy(products1, 0, allProducts, 0, products1.length);System.arraycopy(products2, 0, allProducts, products1.length, products2.length);// 冒泡排序for (int i = 0; i < allProducts.length - 1; i++) {for (int j = 0; j < allProducts.length - 1 - i; j++) {if (allProducts[j].getPrice() > allProducts[j + 1].getPrice()) {// 交换对象引用Product temp = allProducts[j];allProducts[j] = allProducts[j + 1];allProducts[j + 1] = temp;}}}// 打印排序结果for (Product p : allProducts) {System.out.println(p);}}
}
总结
本文介绍了Java面向对象编程的几个重要概念:
- 构造器:用于初始化对象,是创建对象的重要途径
- 封装:通过权限修饰符和getter/setter方法保护数据
- JavaBean:规范的Java类,便于统一管理和使用
- 对象数组:用于批量管理对象,提高代码效率
这些概念是Java面向对象编程的基础,掌握它们有助于编写更规范、更安全、更易维护的代码。在实际开发中,我们会大量使用这些概念,特别是JavaBean和对象数组,它们在处理数据和业务逻辑时非常有用。