2.1 类和对象 - 构建你的小宇宙
在 Java 的宇宙中,一切都围绕着类和对象展开。理解这个概念是迈向 Java 大师之路的关键一步。让我们深入挖掘这个概念,探索如何利用它来构建我们自己的编程宇宙。
2.1.1 基础知识
- 类(Class):类是一个蓝图,定义了创建对象(实例)时所需的状态和行为。状态由属性(变量)表示,行为由方法(函数)表示。想象你正在设计一个机器人,你需要决定它有哪些功能(方法)和属性(变量)。
- 对象(Object):对象是根据类的定义创建的实例。如果类是蓝图,那么对象就是根据这个蓝图建造的房子。每个对象都拥有自己的状态,能够执行定义在其类中的操作。
- 实例化:创建对象的过程称为实例化。通过使用
new
关键字和类的构造器(Constructor)来实现。 - 构造器(Constructor):构造器是一种特殊的方法,用于在创建对象时初始化对象的状态。构造器的名称必须与类名完全相同。
2.1.2 重点案例:设计一个简单的图书类
假设我们要在一个图书管理系统中管理图书,我们需要创建一个 Book
类来代表每本图书。
class Book { String title; String author; int yearPublished; // 构造器 public Book(String title, String author, int yearPublished) { this.title = title; this.author = author; this.yearPublished = yearPublished; } // 显示图书信息的方法 public void displayInfo() { System.out.println(title + " by " + author + ", published in " + yearPublished); } } public class Library { public static void main(String[] args) { // 创建 Book 对象 Book myBook = new Book("Effective Java", "Joshua Bloch", 2008); // 调用方法显示图书信息 myBook.displayInfo(); } }
2.1.3 拓展案例 1:学生管理系统
在一个学生管理系统中,我们需要处理学生的信息,如姓名、学号和成绩。
class Student { String name; String studentID; double grade; public Student(String name, String studentID, double grade) { this.name = name; this.studentID = studentID; this.grade = grade; } public void displayStudentInfo() { System.out.println("Student: " + name + " (ID: " + studentID + "), Grade: " + grade); } } public class School { public static void main(String[] args) { Student student1 = new Student("Alice", "S001", 3.5); student1.displayStudentInfo(); } }
2.1.4 拓展案例 2:账户管理系统
在一个账户管理系统中,我们可能需要管理用户的账户,包括账户名、余额和密码。
class Account { String accountName; double balance; String password; public Account(String accountName, double balance, String password) { this.accountName = accountName; this.balance = balance; this.password = password; } public void deposit(double amount) { balance += amount; System.out.println("Deposit successful. New balance: " + balance); } public void withdraw(double amount, String password) { if (this.password.equals(password)) { if (balance >= amount) { balance -= amount; System.out.println("Withdrawal successful. New balance: " + balance); } else { System.out.println("Insufficient funds."); } } else { System.out.println("Invalid password."); } } } public class Bank { public static void main(String[] args) { Account myAccount = new Account("JohnDoe", 1000, "password123"); myAccount.deposit(500); myAccount.with draw(200, "password123"); } }
通过这些案例,我们可以看到类和对象如何成为构建 Java 应用程序的基础。每个案例都展示了如何定义类,创建对象,以及如何使用对象的状态和行为来执行具体的任务。随着你对这些概念的深入了解,你将能够创建更复杂、功能更强大的 Java 程序。
2.2 继承与多态 - 让一切变得更有趣
在 Java 的奇妙世界里,继承和多态是两个让编程变得更加有趣和强大的概念。通过这两个特性,你可以编写出更简洁、更灵活且易于维护的代码。让我们深入探讨这些概念,并通过一些实际案例来展示它们的威力。
2.2.1 基础知识
- 继承(Inheritance):继承允许一个类(子类)继承另一个类(父类)的属性和方法。这意味着你可以创建一个通用的类,然后通过继承来扩展或修改这个类的功能,而不需要从头开始编写。
- 多态(Polymorphism):多态允许你使用一个统一的接口来操作不同类型的对象。在运行时,Java 虚拟机(JVM)会确定对象的实际类型,调用相应类的方法。这使得你可以编写更通用和灵活的代码。
2.2.2 重点案例:动物园管理系统
假设我们正在为一个动物园创建一个管理系统。在这个系统中,我们需要处理各种类型的动物,比如狮子、老虎和鹦鹉。
基类:Animal
abstract class Animal { String name; public Animal(String name) { this.name = name; } abstract void makeSound(); }
子类:Lion
class Lion extends Animal { public Lion(String name) { super(name); } @Override void makeSound() { System.out.println(name + " says: Roar"); } }
子类:Parrot
class Parrot extends Animal { public Parrot(String name) { super(name); } @Override void makeSound() { System.out.println(name + " says: Squawk"); } }
演示多态
public class Zoo { public static void main(String[] args) { Animal myLion = new Lion("Leo"); Animal myParrot = new Parrot("Polly"); myLion.makeSound(); myParrot.makeSound(); } }
在这个案例中,Animal
类是一个抽象基类,定义了一个抽象方法 makeSound()
。Lion
和 Parrot
类继承自 Animal
类,并提供了 makeSound()
方法的具体实现。这个例子展示了如何通过继承和多态来处理不同类型的动物,同时保持代码的简洁和灵活性。
2.2.3 拓展案例 1:图形界面组件
在创建图形用户界面(GUI)时,我们可能需要处理各种类型的组件,比如按钮、文本框和复选框。我们可以定义一个通用的 Component
类,然后让所有具体的组件类继承自这个类。
abstract class Component { abstract void draw(); } class Button extends Component { @Override void draw() { System.out.println("Drawing a button"); } } class TextBox extends Component { @Override void draw() { System.out.println("Drawing a text box"); } }
使用多态来处理不同的组件:
public class GUI { public static void main(String[] args) { Component button = new Button(); Component textBox = new TextBox(); button.draw(); textBox.draw(); } }
2.2.4 拓展案例 2:支付系统
在一个电子商务平台的支付系统中,我们需要处理不同类型的支付方式,比如信用卡支付、PayPal 支付和银行转账。
abstract class PaymentMethod { abstract void pay(double amount); } class CreditCard extends PaymentMethod { @Override void pay(double amount) { System.out.println("Paying $" + amount + " with credit card"); } } class PayPal extends PaymentMethod { @Override void pay(double amount) { System.out.println("Paying $" + amount + " with PayPal"); } }
使用多态进行支付:
public class ECommerce { public static void main(String[] args) { PaymentMethod myCreditCard = new CreditCard(); PaymentMethod myPayPal = new PayPal(); myCreditCard.pay(100.0); myPayPal.pay(75.0); } }
通过这些案例,我们可以看到继承和多态如何使得 Java 编程变得更加灵活和强大。通过使用这些特性,你可以编写出既简洁又易于维护的代码,轻松应对各种编程挑战。
2.3 封装与抽象 - 保持秘密的艺术
在 Java 的世界中,封装和抽象是保持代码整洁、安全和灵活的两个基石。通过这两种机制,我们可以隐藏实现细节,只暴露必要的接口给外界使用。这不仅可以防止数据被不当访问,还能使得代码更易于理解和维护。
2.3.1 基础知识
- 封装(Encapsulation):封装是通过将数据(属性)和操作数据的方法捆绑在一起的编程技术。在 Java 中,通过将类的成员变量设为
private
,然后通过public
方法(getter 和 setter)来访问和修改这些变量,实现封装。 - 抽象(Abstraction):抽象是一种将复杂性隐藏起来,只显示最关键的信息的方法。在 Java 中,抽象类和接口是实现抽象的两种主要方式。抽象类可以包含抽象方法(没有实现的方法),而接口则可以定义一组方法规范,由其他类来实现。
2.3.2 重点案例:银行账户管理系统
假设我们要设计一个银行账户管理系统,这个系统需要处理各种类型的账户,如储蓄账户和支票账户,同时保护账户信息并提供账户操作。
抽象类:Account
abstract class Account { private String accountNumber; private double balance; public Account(String accountNumber, double balance) { this.accountNumber = accountNumber; this.balance = balance; } public String getAccountNumber() { return accountNumber; } public double getBalance() { return balance; } public void deposit(double amount) { balance += amount; } abstract void withdraw(double amount); // 抽象方法 @Override public String toString() { return "Account{" + "accountNumber='" + accountNumber + '\'' + ", balance=" + balance + '}'; } }
具体类:SavingsAccount 和 CheckingAccount
class SavingsAccount extends Account { private double interestRate; public SavingsAccount(String accountNumber, double balance, double interestRate) { super(accountNumber, balance); this.interestRate = interestRate; } @Override void withdraw(double amount) { if (getBalance() >= amount) { System.out.println("Withdrawing from Savings Account"); } } } class CheckingAccount extends Account { private double overdraftLimit; public CheckingAccount(String accountNumber, double balance, double overdraftLimit) { super(accountNumber, balance); this.overdraftLimit = overdraftLimit; } @Override void withdraw(double amount) { if (getBalance() + overdraftLimit >= amount) { System.out.println("Withdrawing from Checking Account"); } } }
2.3.3 拓展案例 1:员工管理系统
在一个公司的员工管理系统中,我们需要处理不同种类的员工,如正式员工和临时员工,同时管理他们的基本信息和薪资。
抽象类:Employee
abstract class Employee { private String id; private String name; public Employee(String id, String name) { this.id = id; this.name = name; } public String getId() { return id; } public String getName() { return name; } abstract double calculateSalary(); // 计算薪资的抽象方法 }
具体类:RegularEmployee 和 TemporaryEmployee
class RegularEmployee extends Employee { private double annualSalary; public RegularEmployee(String id, String name, double annualSalary) { super(id, name); this.annualSalary = annualSalary; } @Override double calculateSalary() { return annualSalary / 12; } } class TemporaryEmployee extends Employee { private double hourlyRate; private int hoursWorked; public TemporaryEmployee(String id, String name, double hourlyRate, int hoursWorked) { super(id, name); this.hourlyRate = hourly Rate; this.hoursWorked = hoursWorked; } @Override double calculateSalary() { return hourlyRate * hoursWorked; } }
2.3.4 拓展案例 2:图形界面组件库
在开发图形用户界面(GUI)时,我们可能需要创建一套组件库,如按钮、文本框等,同时保证这些组件的接口一致,以便于使用和扩展。
接口:Component
interface Component { void draw(); void resize(); }
具体实现:Button 和 TextBox
class Button implements Component { @Override public void draw() { System.out.println("Drawing a Button"); } @Override public void resize() { System.out.println("Resizing a Button"); } } class TextBox implements Component { @Override public void draw() { System.out.println("Drawing a TextBox"); } @Override public void resize() { System.out.println("Resizing a TextBox"); } }
通过这些案例,我们可以看到封装和抽象如何使得代码更加安全、清晰和易于维护。封装保护了数据和实现细节,而抽象则提供了一种高层次的方式来操作对象,使得我们可以轻松地扩展和修改系统,而不会影响到使用这些系统的代码。