类(class)可以看作一个模版,系统根据类的定义来创造对象(object/instance)。
类是对一类事物的抽象,定义了该类事物的属性和行为。对象是类的实例化,是具体存在的个体。
面向对象编程的基本原则包括封装、继承和多态,这些原则都是基于类和对象的概念来实现的。
基本结构
- 属性(field):也称为成员变量,是类中定义的变量,用来描述对象的状态或特征
- 方法(method):也称为成员方法,是类中定义的函数,用来描述对象的行为或功能
- 构造器(constructor):是一种特殊的方法,用来初始化对象的属性
- 内部类(inner class 可选):是定义在另一个类内部的类,可以访问外部类的成员变量和方法
修饰符
访问修饰符
- public:公共的,任何类都可以访问
- protected:受保护的,只有同一个包中的类和不同包中的子类可以访问
- 默认(default):没有修饰符,只有同一个包中的类可以访问
- private:私有的,只有本类可以访问
| 访问修饰符 |
同一类 |
同一包 |
子类(不同包) |
其他包 |
| public |
✅ |
✅ |
✅ |
✅ |
| protected |
✅ |
✅ |
✅ |
❌ |
| default |
✅ |
✅ |
❌ |
❌ |
| private |
✅ |
❌ |
❌ |
❌ |
其他修饰符
- static:静态的,属于类而不是对象,可以直接通过类名访问
- final:最终的,不能被继承或重写
- abstract:抽象的,不能被实例化,必须由子类来实现
- synchronized:同步的,用于线程安全的访问控制
- transient:短暂的,表示该属性不需要被序列化
- volatile:易变的,表示该属性可能被多个线程同时访问,禁止指令重排序优化
类属性
- 成员变量:定义在类中方法外的变量,属于对象的属性,每个对象都有自己的成员变量副本
- 静态变量:定义在类中方法外,并且使用static修饰的变量,属于类的属性,所有对象共享同一个静态变量副本
1 2 3
| class MyClass { [访问修饰符] [static] 数据类型 变量名; }
|
类方法
- 成员方法:定义在类中,并且没有使用static修饰的方法,属于对象的行为,每个对象都有自己的成员方法副本
- 静态方法:定义在类中,并且使用static修饰的方法,属于类的行为,所有对象共享同一个静态方法副本,可以直接通过类名访问
1 2 3 4 5
| class MyClass { [访问修饰符] [其他修饰符] 返回类型 方法名(参数列表) { // 方法体 } }
|
构造器
构造器是一种特殊的类方法,用于初始化对象的属性(构造之前对象已经创建好了)。
构造器的名称必须与类名相同,并且没有返回类型。
构造器可以有参数,也可以没有参数,如果没有定义任何构造器,Java会提供一个默认的无参构造器。
如果定义了带参数的构造器,Java将不再提供默认的无参构造器,需要手动定义一个无参构造器。
1 2 3 4 5 6 7 8 9 10
| class MyClass { // 无参构造器 public MyClass() { // 初始化代码 } // 带参数的构造器 public MyClass(参数列表) { // 初始化代码 } }
|
this 关键字
this是一个引用变量,指向当前对象的实例,可以用来访问当前对象的成员变量和成员方法,常用于区分成员变量和局部变量,以及在构造器中调用其他构造器。
在构造器中调用时必须放在第一行,否则编译错误。
this不能用于静态方法中,因为静态方法属于类而不是对象,没有当前对象的实例。
super 关键字
super是一个引用变量,指向当前对象的父类实例,可以用来访问父类的成员变量和成员方法,常用于子类重写父类方法时调用父类的方法,以及在子类构造器中调用父类的构造器。
在子类构造器中调用父类构造器时必须放在第一行,否则编译错误。
如果子类构造器没有显式调用父类构造器,Java会默认调用父类的无参构造器,如果父类没有无参构造器,则编译错误。
super不能用于静态方法中,因为静态方法属于类而不是对象,没有当前对象的实例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class TestClass04 { public int val = 0; public void print() { System.out.println("trigger on print method"); System.out.println(val); } public TestClass04(int val) { this.val = val; } public TestClass04() { this(123); this.print(); } }
|
代码示例
1 2 3 4 5 6 7 8
| package pk.pk2;
public class TestClass03 { public String i1 = "i1"; protected String i2 = "i2"; String i3 = "i3"; private String i4 = "i4"; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| package pk.pk1;
import pk.pk2.TestClass03;
public class TestClass01 { public String i1 = "i1"; protected String i2 = "i2"; String i3 = "i3"; private String i4 = "i4"; static String i5 = "i5";
String name;
void print() { System.out.println(i1); System.out.println(i2); System.out.println(i3); System.out.println(i4); System.out.println("name: " + name); }
public TestClass01() { this.name = "default constructor"; }
public TestClass01(String name) { this.name = name; } }
class TestSubClass01 extends TestClass03 { void print() { System.out.println(i1); System.out.println(i2); } }
class TestClass02 { public static void main(String[] args) { TestClass01 tc1 = new TestClass01(); System.out.println(tc1.i1); System.out.println(tc1.i2); System.out.println(tc1.i3); tc1.print(); System.out.println(TestClass01.i5);
TestClass01 tc2 = new TestClass01("custom constructor"); tc2.print();
TestSubClass01 tc3 = new TestSubClass01(); System.out.println(tc3.i1); tc3.print(); } }
|
类和对象是面向对象编程的核心概念,类定义了对象的属性和行为,而对象则是类的具体实例。通过类和对象,我们可以更好地组织代码,提高代码的复用性和可维护性。
面向过程编程则是以函数为中心,强调程序的流程和步骤,而面向对象编程则是以对象为中心,强调数据和行为的封装。