一,前言
今天是第九天,开始学面向对象编程。
二,面向对象编程
1.什么是面向对象
Java 是一种面向对象的编程语言,它基于 "对象" 的概念来组织代码。面向对象编程 (OOP) 有四个主要特性:封装、继承、多态和抽象。
2.方法的回顾与补充
静态方法和非静态方法
在 Java 中,方法可以分为静态方法和非静态方法,它们在使用方式、内存分配和功能特性上有明显区别。理解这些区别对于编写高效、可维护的 Java 代码至关重要。
静态方法
静态方法是属于类的方法,不需要创建类的实例就可以调用。使用static
关键字修饰。
特点:
-
通过类名直接调用,无需创建对象
-
只能访问类的静态成员(静态变量和静态方法)
-
不能使用
this
和super
关键字 -
通常用于工具类方法或不需要实例状态的功能
public class MathUtils {
// 静态方法:计算两个数的和
public static int add(int a, int b) {
return a + b;
}
// 静态方法:计算阶乘
public static int factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
// 静态变量
private static final double PI = 3.14159;
// 静态方法访问静态变量
public static double calculateCircleArea(double radius) {
return PI * radius * radius;
}
}
// 使用静态方法
public class Main {
public static void main(String[] args) {
// 直接通过类名调用静态方法,无需创建对象
int sum = MathUtils.add(5, 3);
System.out.println("5 + 3 = " + sum);
double area = MathUtils.calculateCircleArea(2.0);
System.out.println("半径为2的圆的面积:" + area);
}
}
非静态方法
非静态方法是属于类的实例的方法,必须通过创建类的对象才能调用。
特点:
-
通过对象实例调用
-
可以访问类的所有成员(静态和非静态)
-
可以使用
this
和super
关键字 -
通常用于需要访问对象状态或执行与特定实例相关的操作
示例:
public class Person {
// 非静态变量(实例变量)
private String name;
private int age;
// 构造方法
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 非静态方法:获取个人信息
public String getInfo() {
return "姓名:" + name + ",年龄:" + age;
}
// 非静态方法:增加年龄
public void growOlder() {
this.age++;
}
// 非静态方法可以访问静态变量
public void displayClassInfo() {
System.out.println("这是一个Person类的实例");
}
}
// 使用非静态方法
public class Main {
public static void main(String[] args) {
// 创建对象
Person person = new Person("张三", 25);
// 通过对象调用非静态方法
System.out.println(person.getInfo());
// 调用修改对象状态的方法
person.growOlder();
System.out.println("一年后:" + person.getInfo());
}
}
何时使用静态方法或非静态方法
-
使用静态方法的场景:
-
工具类方法(如字符串处理、数学计算)
-
不依赖对象状态的通用功能
-
单例模式中的工厂方法
-
主方法
main()
必须是静态的
-
-
使用非静态方法的场景:
-
需要访问或修改对象状态
-
实现类的行为或业务逻辑
-
方法需要多态特性
-
需要使用
this
或super
关键字
-
this关键字
在 Java 中,this
是一个引用变量,它指向当前对象。它在面向对象编程中非常重要,用于引用当前实例的成员(变量、方法和构造函数)。
引用当前对象的成员变量
当方法参数或局部变量与成员变量同名时,使用this
来区分它们:
public class Person {
private String name;
private int age;
// 构造方法
public Person(String name, int age) {
// 使用this引用成员变量,区分同名的参数
this.name = name;
this.age = age;
}
// 方法
public void setName(String name) {
// 使用this引用成员变量
this.name = name;
}
public void introduce() {
System.out.println("我是" + this.name + ",今年" + this.age + "岁。");
}
}
3.类对象的创建
一个项目应该只存在一个main方法.
类和对象的关系
比如动物就是类,猫狗就是对象,类是抽象的,对象是具体的.
类和对象的创建
类里面只有属性和方法
// 定义一个Person类
static class Person {
// 成员变量(属性)
private String name;
private int age;
// 构造方法
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 成员方法
public void introduce() {
System.out.println("我是" + name + ",今年" + age + "岁。");
}
}
// 创建并使用Person对象
public class Main {
public static void main(String[] args) {
// 创建对象
Person person = new Person("张三", 25);
// 调用对象的方法
person.introduce();
}
}
4.构造器
Java 中的构造器
构造器(也称为构造函数或构造方法)是 Java 中一种特殊的方法,用于创建和初始化对象。它在对象创建时自动调用,确保对象在使用前已正确初始化。
构造器的特点
-
名称必须与类名相同
-
没有返回类型(连
void
也不写) -
不能被继承、重写,但可以重载
-
默认情况下会调用父类的无参构造器
-
可以使用
this()
或super()
调用其他构造器
构造器的作用
-
创建对象:为对象分配内存空间
-
初始化对象:设置对象的初始状态
-
注意点:定义有参构造之后,如果想使用无参构造,显示的定义一个无参的构造.
构造器的类型
1. 默认构造器
如果类中没有定义任何构造器,Java 编译器会自动提供一个无参的默认构造器:
public class Person {
private String name;
private int age;
// 编译器自动添加的默认构造器
// public Person() {
// super(); // 调用父类的无参构造器
// }
public void displayInfo() {
System.out.println("姓名:" + name + ",年龄:" + age);
}
}
注意:一旦类中定义了任何构造器,默认构造器就不会自动提供。
2. 无参构造器
显式定义的无参构造器,用于创建默认状态的对象:
public class Student {
private String name;
private int age;
private String school;
// 无参构造器
public Student() {
name = "未知";
age = 0;
school = "未入学";
System.out.println("创建了一个默认学生对象");
}
public void displayInfo() {
System.out.println("姓名:" + name + ",年龄:" + age + ",学校:" + school);
}
}
3. 带参数的构造器
接受参数的构造器,用于创建具有特定初始状态的对象:
public class Book {
private String title;
private String author;
private double price;
// 带参数的构造器
public Book(String title, String author, double price) {
this.title = title;
this.author = author;
this.price = price;
System.out.println("创建了一本名为《" + title + "》的书");
}
public void displayInfo() {
System.out.println("书名:《" + title + "》");
System.out.println("作者:" + author);
System.out.println("价格:" + price + "元");
}
}
4. 构造器重载
在同一个类中定义多个具有不同参数列表的构造器:
public class Rectangle {
private int width;
private int height;
// 无参构造器
public Rectangle() {
this(10, 20); // 调用带参数的构造器
System.out.println("创建了一个默认大小的矩形");
}
// 带一个参数的构造器(正方形)
public Rectangle(int size) {
this(size, size); // 调用带两个参数的构造器
System.out.println("创建了一个边长为" + size + "的正方形");
}
// 带两个参数的构造器
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
System.out.println("创建了一个" + width + "x" + height + "的矩形");
}
public int getArea() {
return width * height;
}
}
构造器的调用规则
-
构造器链:构造器可以通过
this()
或super()
相互调用 -
this():调用本类的其他构造器,必须是构造器中的第一条语句
-
super():调用父类的构造器,默认会自动调用父类的无参构造器
-
避免循环调用:构造器之间的调用不能形成循环
5,创建对象内存分析
内存分配示例图解
假设我们有以下代码:
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void sayHello() {
System.out.println("Hello, I'm " + name);
}
}
public class Main {
public static void main(String[] args) {
Person p1 = new Person("Alice", 25);
Person p2 = new Person("Bob", 30);
p1.sayHello();
p2.sayHello();
}
}
内存分配情况如下:
-
方法区:
-
存储
Person
类和Main
类的类结构信息 -
存储类的方法字节码
-
存储常量池 ("Alice", "Bob", "Hello, I'm")
-
-
堆:
-
为
p1
分配内存,包含name
(引用) 和age
(25) -
为
p2
分配内存,包含name
(引用) 和age
(30) -
为字符串对象 "Alice" 和 "Bob" 分配内存
-
-
栈:
-
main
方法栈帧:-
局部变量
p1
(引用指向堆上的Person
对象) -
局部变量
p2
(引用指向堆上的Person
对象)
-
-
三,小结
偷个懒。