面向对象编程
1.面向对象编程的好处
面向对象编程通过封装、继承、多态等机制,提供了强大的代码组织和管理能力,提高了代码的复用性、可维护性、灵活性和扩展性,使得软件系统能够更好地应对复杂性和变化,是现代软件开发中不可或缺的编程范式。
2.万物皆可对象
对象本质上是一种特殊的数据结构
对象是用类new出来的,有了类就可以创建出对象。
this关键字是什么?
this就是一个变量, 可以用在方法中 ,用来拿到当前对象;哪个对象调用方法,this就指向哪个对象,也就是拿到哪个对象。
this关键字在实际开发中常用来干啥?
用来解决对象的成员变量与方法内部变量的名称一样时,导致访问冲突问题的。
面向对象三大特征:继承、封装、多态
1. 封装(Encapsulation):
•封装允许将数据(属性)和操作数据的方法(行为)捆绑在一起,形成一个独立的单元(对象)。通过访问修饰符(如 public、private、protected)控制对象内部数据的可见性和可访问性,隐藏实现细节,保护数据免受外部直接修改,增强代码的安全性和完整性。
•封装使得代码模块化,每个对象负责自身的内部状态管理,降低模块间的耦合度,提高代码的可维护性。
public class Student {
String name;// 姓名
double chinese; // 语文成绩
double math; // 数学成绩
public void printTotalScore(){
System.out.println(name + "同学的各科总分是:" + (chinese + math));
}
public void printAverageScore(){
System.out.println(name + "同学的各科平均分是:" + (chinese + math) / 2.0);
}
}
代码层面如何控对象的成员公开或隐藏?
公开成员,可以使用public(公开)进行修饰。
隐藏成员,使用private(私有,隐藏) 进行修饰。
2. 继承(Inheritance):
•继承允许一个类(子类)继承另一个类(父类)的属性和方法,实现代码的复用。子类不仅可以继承父类的所有公共属性和方法,还可以根据需要添加新属性、覆盖或扩展父类的方法,实现功能的特化或扩展。
•继承形成了类的层次结构,有助于组织代码,减少重复编写相似代码的工作,同时保持代码的一致性。通过继承,可以轻松创建和管理具有相似特性的对象族。
3. 多态(Polymorphism):
•多态表现为“一个接口,多种实现”。同一消息(方法调用)作用于不同对象时,会根据对象的实际类型产生不同的行为。多态主要通过接口继承(Java中的interface)和实现继承(Java中的class继承)实现。
•多态提高了代码的灵活性和扩展性。在编写代码时,可以针对接口编程,而不必关心具体的实现类。在运行时,可以根据实际传入的对象动态决定执行的操作,使得程序能够处理多种类型的数据,适应变化的需求。
多态分为编译时多态和运行时多态
编译时多态(静态多态)
这主要通过**方法重载(Overloading)**来实现,即在同一类中定义多个同名方法,但这些方法的参数列表(包括参数个数、类型或顺序)必须不同。
方法重载
public class MathUtils {
public int add(int a, int b) {
return a + b;
}
public double add(double a, double b) {
return a + b;
}
public String add(String a, String b) {
return a + b;
}
}
public class Main {
public static void main(String[] args) {
MathUtils utils = new MathUtils();
int sumInt = utils.add(10, 20); // 编译时确定调用add(int, int)
double sumDouble = utils.add(3.5, 4.2); // 编译时确定调用add(double, double)
String concatString = utils.add("Hello, ", "World!"); // 编译时确定调用add(String, String)
}
}
运行时多态(动态多态)
它允许在程序运行期间根据对象的实际类型来决定调用哪个方法。运行时多态是通过继承和接口实现,结合**方法重写(Overriding)**来实现的。
1. 继承与方法重写
在Java中,子类可以继承父类,并可以选择重写(使用@Override注解标记)父类中非final的非static方法。当父类引用指向子类对象时,通过该引用调用一个重写的方法时,实际执行的是子类中重写后的方法,而非父类中原有的方法。这种行为在运行时动态确定,故称为运行时多态。
class Animal {
void makeSound() {
System.out.println("The animal makes a sound.");
}
}
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("The dog barks.");
}
}
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Dog(); // 父类引用指向子类对象
myAnimal.makeSound(); // 输出 "The dog barks.",体现了运行时多态
}
}
2. 接口实现
Java中的接口定义了一组方法签名,不提供实现。类可以通过实现接口来声明它支持接口中定义的所有方法。当一个对象被声明为接口类型时,实际的实现类可以是任意实现了该接口的类。调用接口方法时,实际执行的是实现类中对应方法的实现。这也是一种运行时多态。
interface SoundProducer {
void produceSound();
}
class Piano implements SoundProducer {
@Override
public void produceSound() {
System.out.println("The piano plays a tune.");
}
}
class Trumpet implements SoundProducer {
@Override
public void produceSound() {
System.out.println("The trumpet plays a note.");
}
}
public class Main {
public static void main(String[] args) {
SoundProducer instrument = new Piano(); // 接口引用指向实现类对象
instrument.produceSound(); // 输出 "The piano plays a tune."
instrument = new Trumpet(); // 同一接口引用指向不同实现类对象
instrument.produceSound(); // 输出 "The trumpet plays a note."
}
}
方法重载和方法重写
方法重载(Overloading)
方法重载是指在同一类中定义多个同名的方法,但这些方法的参数列表(包括参数个数、类型或顺序)必须不同。编译器根据函数调用时提供的实参类型和数量在编译时确定调用哪个重载版本的方法。
特点:
•同一类中:重载的方法必须在同一类中声明。
•方法名相同:所有重载方法共享相同的方法名。
•参数列表不同:重载方法的区别在于参数列表,可以是参数个数、类型或顺序的不同,但返回类型不能作为重载的依据。
•与返回类型无关:重载方法的返回类型可以相同,也可以不同,但不能仅凭返回类型来区分重载方法。
•编译时多态:编译器在编译阶段就能确定调用哪个重载版本的方法,属于静态绑定。
public class MathUtils {
public int add(int a, int b) {
return a + b;
}
public double add(double a, double b) {
return a + b;
}
public String add(String a, String b) {
return a + b;
}
}
方法重写(Overriding)
方法重写是指子类继承父类时,子类中定义一个与父类中已有的方法具有相同方法名、返回类型和参数列表的方法。子类的重写方法会覆盖父类的同名方法,当父类引用指向子类对象并调用该方法时,实际执行的是子类中重写后的方法。
特点:
•继承关系中:重写的方法必须在子类中声明,并且子类继承自父类。
•方法名、参数列表、返回类型相同:重写的方法与被重写的方法具有完全相同的签名(方法名、参数列表和返回类型)。
•访问权限不能更严:子类重写的方法的访问权限不能低于父类被重写的方法,但可以更高。
•抛出异常范围不能扩大:子类重写的方法抛出的异常类型应与父类被重写的方法相同或为其子类型。
•@Override注解:建议使用@Override注解标记重写方法,以提高代码可读性和编译器对重写正确性的检查。
•运行时多态:当父类引用指向子类对象并调用重写方法时,实际执行的是子类的方法,属于动态绑定。
class Animal {
void makeSound() {
System.out.println("The animal makes a sound.");
}
}
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("The dog barks.");
}
}
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Dog(); // 父类引用指向子类对象
myAnimal.makeSound(); // 输出 "The dog barks.",体现了方法重写
}
}
4.实体类 JavaBean
什么是实体类?
实体类是面向对象编程中用于表示现实世界中的一个具体对象、概念或实体的类。它通常包含属性(对应于对象的状态)、行为(方法)以及可能的标识属性。实体类常用于数据持久化,特别是在与数据库交互的应用程序中,它与数据库表结构相对应,通过ORM工具实现数据的读写。实体类的核心目的是封装业务相关的数据和基本操作,实现业务逻辑的模块化。
实体类开发场景
实体类对应的是软件开发里现在比较流行的开发方式,数据和数据的业务处理相分离
成员变量和局部变量的区别
区别 | 成员变量 | 局部变量 |
类中位置不同 | 类中,方法外 | 常见于方法中 |
初始化值不同 | 有默认值, 不需要初始化赋值 | 没有默认值,使用之前必须完成赋值 |
内存位置不同 | 堆内存 | 栈内存 |
作用域不同 | 整个对象 | 在所归属的大括号中 |
生命周期不同 | 与对象共存亡 | 随着方法的调用而生,随着方法的运行结束而亡 |