一、面向对象概述
1.什么是面向对象
在程序中,使用对象来映射现实中的事物,使用对象的关系来描述事物之间的联系,这种思想就是面向对象。
2.面向对象与面向过程
面向过程:
面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一一实现,使用的时候依次调用就可以了。
面向对象:
面向对象则是把构成问题的事务按照一定规则划分为多个独立的对象,然后通过调用对象的方法来解决问题。
3.面向对象的特点
封装:
封装是面向对象的核心思想,将对象的属性和行为封装起来,不需要让外界知道具体实现细节。
继承:
继承主要描述的就是类与类之间的关系,通过继承,可以在无需重新编写原有类的情况下,对原有类的功能进行扩展。
多态:
多态指的是在一个类中定义的属性和功能被其他类继承后,当把子类对象直接赋值给父类引用变量时,相同引用类型的变量调用同一个方法所呈现出的多种不同行为特性。
二、JAVA中的类与对象
1.类与对象的关系
为了使程序中描述的对象与该事物在现实中的形态保持一致,面向对象的思想中提出了类与对象这两个概念。其中类是对某一类事物的抽象描述,而对象用于表示现实中该类事物的个体。对象是类的具体化,并且一个类可以对应多个对象。
2.类的定义
类(Class)是 Java 中用来描述具有相同属性和方法的对象的模板或蓝图。在类的定义中,我们可以声明对象的属性(称为字段或属性)和方法。
类的定义和结构:
public class MyClass {
// Fields (Instance variables)
private String name;
private int age;
// Constructors
public MyClass(String name, int age) {
this.name = name;
this.age = age;
}
// Methods
public void displayInfo() {
System.out.println("Name: " + name + ", Age: " + age);
}
}
-
成员变量(Fields): 在类中定义的变量,用于描述对象的状态或特征。在上面的例子中,
name
和age
是类MyClass
的字段。 -
构造方法(Constructors): 用于创建类的新实例。在上面的例子中,
MyClass
类有一个带有name
和age
参数的构造方法,用于初始化对象的状态。 -
成员方法(Methods): 在类中定义的函数,用于描述对象的行为或功能。
displayInfo()
是一个方法,用于显示对象的信息。
3.对象的创建与使用
对象(Object)是类的实例化(实例)。通过 new
关键字,可以根据类的定义创建对象。
public class Main {
public static void main(String[] args) {
// 创建 MyClass 的一个对象
MyClass obj1 = new MyClass("Alice", 25);
// 调用对象的方法
obj1.displayInfo();
// 创建另一个对象
MyClass obj2 = new MyClass("Bob", 30);
obj2.displayInfo();
}
}
-
对象创建: 使用
new
关键字,根据类MyClass
的定义创建了两个不同的对象obj1
和obj2
。 -
方法调用: 使用对象的引用
obj1
和obj2
调用displayInfo()
方法来显示对象的信息。
在创建对象时,程序会占用两块内存区域,分别是栈内存和堆内存。如图,其中Person类型的变量p被存放在栈内存中,它是一个引用,会指向真正的对象;通过new Person()创建的对象则放在堆内存中,这才是真正的对象。
4.访问控制符
在Java中,针对类、成员方法和属性提供了四种访问级别,分别是private、default、protected和public。
private(当前类访问级别):如果类的成员被private访问控制符来修饰,则这个成员只能被该类的其他成员访问,其他类无法直接访问。类的良好封装就是通过private关键字来实现的。
default(包访问级别):如果一个类或者类的成员不使用任何访问控制符修饰,则称它为默认访问控制级别,这个类或者类的成员只能被本包中的其他类访问。
protected(子类访问级别):如果一个类的成员被protected访问控制符修饰,那么这个成员既能被同一包下的其他类访问,也能被不同包下该类的子类访问。
public(公共访问级别):这是一个最宽松的访问控制级别,如果一个类或者类的成员被public访问控制符修饰,那么这个类或者类的成员能被所有的类访问,不管访问类与被访问类是否在同一个包中。
三、类的封装
1.为什么需要封装
在编程过程中,有可能会出现语法上没有问题,但是在现实中是不可能发生的情况。为防止出现这种情况,在设计一个Java类时,应该对成员变量的访问作出一些限定,不允许外界随意访问,这就需要实现类的封装。
2.如何实现封装
在定义一个类时,将类中的属性私有化,即使用private关键字来修饰,私有属性只能在它所在类中被访问,如果外界想要访问私有属性,需要提供一些使用public修饰的公有方法,其中包括用于获取属性值的getXxx()方法和设置属性值的setXxx()方法。
四、方法的重载和递归
1.方法的重载
重载(Overloading)是指在同一个类中,允许创建多个同名方法,但这些方法的参数类型或参数个数不同。通过重载,可以根据不同的参数列表来调用不同的方法。
重载的特点和规则:
- 重载的方法必须具有相同的方法名。
- 参数列表必须不同,包括参数的类型、个数或顺序。
- 返回类型可以相同也可以不同,所以不能仅仅通过返回类型来区分重载。
例:
public class Calculator {
// 重载的方法
public int add(int a, int b) {
return a + b;
}
public double add(double a, double b) {
return a + b;
}
public int add(int a, int b, int c) {
return a + b + c;
}
}
调用重载方法的原则:
- 当调用一个重载方法时,Java 编译器会根据提供的参数列表选择最匹配的方法。选择过程是根据参数的数量和类型来确定的。
- 如果找不到匹配的方法(即参数列表不匹配任何已定义的重载方法),则会编译错误。
2.方法的递归
方法的递归是指在一个方法的内部调用自身的过程。递归必须要有结束条件,不然就会陷入无限递归的状态,永远无法结束调用。
五、构造方法
构造方法(Constructor)是一种特殊的方法,在对象被实例化(即创建)时调用,用于初始化对象。
1. 构造方法的命名与特点
构造方法的名称必须与所在类的名称完全相同。
构造方法不声明返回类型,包括void。
每次实例化一个对象时,构造方法都会被调用来初始化对象的状态。
构造方法可以重载,只要它们的参数列表不同。
2.默认构造方法
如果没有为类显式定义任何构造方法,Java编译器会自动提供一个默认构造方法。
默认构造方法不带任何参数,执行默认的对象初始化操作,如初始化成员变量为默认值。
如果已为类定义了构造方法,Java将不会再提供默认的构造方法。
3.构造方法的用途
初始化对象状态:通过构造方法,可以在对象创建时初始化对象的各种属性和状态。
确保对象的一致性:构造方法可以确保对象在创建时具有合适的初始状态,避免对象在使用过程中出现未初始化或者不一致的情况。
六、this关键字
1.通过this关键字调用成员变量,解决与局部变量名称冲突问题
public class Person {
private String name;
public Person(String name) {
// 使用this解决变量名冲突
this.name = name;
}
}
2.通过this关键字调用成员方法
class Person {
public void openMouth() {
……
}
//调用成员方法
public void speak() {
this.openMouth();
}
}
3. 在一个构造方法中调用另一个构造方法
public class Rectangle {
private int width;
private int height;
// 带参数的构造方法
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
// 无参构造方法,调用带参数的构造方法
public Rectangle() {
this(0, 0); // 调用上面定义的带参数的构造方法
}
}
在使用this调用类的构造方法时,应注意以下几点:
只能在构造方法中使用this调用其他的构造方法,不能在成员方法中使用。
在构造方法中,使用this调用构造方法的语句必须是该方法的第一条执行语句,且只能出现一次。
不能在一个类的两个构造方法中使用this互相调用。
七、static关键字
1. 表示静态,在类加载后执行,先于对象存在,只能修饰属性、方法和静态块
2. 修饰属性,属性被该类的所有对象共享
3. 修饰方法,该方法不能被覆盖
4. 修饰的代码块,在类加载后执行,仅仅执行一次,通常用于加载驱动
注意:
1.static修饰的方法或代码块中不能使用this关键字
2.static不能修饰局部变量
3.static修饰的属性和方法,建议通过 类名.xx 的方式调用