Java是一门纯面向对象的语言,在面向对象的世界里,一切都为对象。它是解决问题的一种思想,主要依靠对象之间的交互完成一件事情。类与对象是我们学习面向对象最基础的知识,是面向对象实现的基石,可见它是有多么重要
面向对象是一种编程思想,与之相对的还有面向过程,我们就拿炒菜这件事来解释一下这两者之间的区别

面向过程:准备食材 — 打开油烟机 — 热锅加油 — 油热放入食材翻炒 — 加入调味品 — 出锅
面向对象:食材、自动炒菜机、人、调味品,由这几个对象,我们就能完成炒菜这一件事
在这个例子中,我们能够看出来面向过程跟面向对象,是两种不同的思维方式,处理问题的思考的角度不一样。面向过程中,我们注重的是炒菜这个过程是如何进行的;但在面向对象中,我们只需要注重完成炒菜需要哪些对象,通过对象之间的交互来完成,将它们组合在一起就行,完全不需要管具体的实现过程
在Java中,一切皆对象,一切都围绕对象进行,我们只需要关心找对象、建对象,用对象等
类:是用来对一个物体的属性和功能进行描述的。像生活中我们经常使用的手机,在Java中就可以看成一个类,手机品牌,型号,外观,材料都是它的属性;而打电话,上网,刷视频就是它的功能;这样我们就可以在Java中创建一个手机类
对象:某个类的一个实体。我们可以用手机类创建出一部华为手机,此时这部手机就可以称之为一个对象,创建好了对象后,我们就可以来操作手机的属性和功能
- // 创建类
- class ClassName{
- field; // 成员变量/字段/属性
- method; // 成员方法/行为
- }
注意事项:
类的实例化指的就是用类创建对应的对象,在Java中我们采用new关键字,配合类来实例化对象
- 类名称 引用名称 = new 类名称( )
- 例如:
- Person person = new Person( );
在上面的例子中,我们使用Person这个类创建了一个person对象,要注意的是,所有类的对象都是引用数据类型。所以person就是引用变量,变量名可以根据自己的需求命名
我们可以把上面的例子再扩充一下,想一下人会有什么属性,有什么行为?
- class Person{
- //成员变量
- String name; //姓名
- int age; //年龄
- String gender; //性别
-
- //成员方法
- void run(){
- System.out.println(name+"在跑步~~~");
- }
-
- void print(){
- System.out.println("姓名:"+name+" 年龄:"+age+" 性别:"+gender);
- }
- }
-
- public class Test {
- public static void main(String[] args) {
- //创建一个实例化对象
- Person A = new Person();
- //通过对象来给对象的成员变量进行赋值,并使用成员方法
- A.name = "小A";
- A.age = 18;
- A.gender = "男";
- A.print();
- A.run();
- System.out.println("=========");
- //创建对象后不给成员变量赋值
- Person B = new Person();
- B.print();
- }
- }
输出结果如下:

我们可以用一个图来理解上面的代码
从上面的例子中可以看到:在创建好类后,我们可以通过new来实例化多个对象,使用“对象名.”给成员变量一一赋值,也可以调用类中的成员方法实现各种功能;当我们没有初始化对象时,成员变量都会有各自类型对应的默认值
我们可以把类看成一张产品设计图,在设计图上面有产品的各种属性,还有产品附带的各种功能
有了设计图,我们就可以根据设计图生产大量产品,生产出来的产品也附带有各种功能
这种拿产品设计图来生产产品就等同于类实例化对象,一个类可以实例化出多个对象,而且实例化出来的对象也要占据内存空间,用来存储各自的成员变量
下图展示的就是创建对象以及使用对象在计算机中的执行原理
从图中我们可以得知:
this就是一个变量,可以用在方法中,来拿到当前对象;哪个对象调用方法,this就指向哪个对象,也就是拿到哪个对象。我们来看一下具体的例子
- class Student {
- public void printThis() {
- System.out.println(this);
- }
- }
-
- public class Test {
- public static void main(String[] args) {
- Student student = new Student();
- System.out.println(student);
- student.printThis();
- }
- }
在上面的代码中,我们创建了一个学生类,并在里面定义了printThis方法,打印this的值;在Test主类中我们new了一个学生对象student,直接打印了student,同时也调用了printThis方法。
在前面我们有讲到“创建出来的对象在栈内存当中,变量里面记住的是对象的地址”,那现在student里面装的就是对象的地址,我们来看一下运行结果

通过结果我们可以看到:student和this打印出来的结果一模一样,都是对象的地址,也就是说:this指向的就是对象,它就是对象在方法中的分身
我们还是用上面的学生类来举例子,假设有一个学生,他在一次考试中考了59分,而及格分数要求不小于60分,我们用代码来实现一下这个情景
- class Student {
- double score;
-
- public void printfPass(double score) {
- if(score >= score) {
- System.out.println("通过考试~~~");
- } else {
- System.out.println("考试不及格~~~");
- }
- }
- }
-
- public class Test {
- public static void main(String[] args) {
- Student student = new Student();
- student.score = 59; //考试成绩
- student.printfPass(60); //及格分数
- }
- }
运行结果如下

为什么会出现这种情况呢?
原因在于:我们的成员变量名和方法的形参名相同,导致考试成绩59压根就没有进入到方法里,本质上是及格分数60分在自己和自己比较,60肯定是不小于60,故输出“通过考试~~~”
因此,我们需要在第一个score前面加上“this.”,这样就是避免变量名冲突产生的问题
- class Student {
- double score;
-
- public void printfPass(double score) {
- if(this.score >= score) { //第一个score前面加上this.
- System.out.println("通过考试~~~");
- } else {
- System.out.println("考试不及格~~~");
- }
- }
- }
-
- public class Test {
- public static void main(String[] args) {
- Student student = new Student();
- student.score = 59; //考试成绩
- student.printfPass(60); //及格分数
- }
- }
这就是this引用所发挥的作用,除了this引用成员变量外,this还可以引用成员方法。当我们创建多个对象后,它们要使用同一个方法时,就可以在前面加上this引用,这样可以让编译器知道是哪个对象调用的方法
总结一下:
在前面的学习中,我们明白了如何去创建一个对象,但是在初始化对象的时候,我们使用对象引用成员变量一个一个初始化的,这未免有些麻烦
- //创建一个实例化对象
- Person A = new Person();
- //通过对象来给对象的成员变量进行赋值,并使用成员方法
- A.name = "小A";
- A.age = 18;
- A.gender = "男";
- A.print();
- A.run();
哎,这时候,构造方法就能发挥作用了
构造方法,也叫做构造器。它是一种特殊的成员方法,它可以帮助我们更加方便地去初始化对象。而且构造方法的名字必须跟类名一样,我们在使用new创建对象时,实际上就是调用了当前类的构造方法。下面就是一个Student类的构造方法
- class Student {
- double score;
-
- //构造方法
- public Student(double score) {
- this.score = score;
- }
- }
- class Student {
- String name;
- int age;
- String gender;
-
- //编译器默认给的无参构造方法
- public Student() {
-
- }
-
- //自己创建的有参构造方法
- public Student(String name, int age, String gender) {
- this.name = name;
- this.age = age;
- this.gender = gender;
- }
- }
- public class Test {
- public static void main(String[] args) {
- Student student = new Student();
- Student student1 = new Student("张三",19,"男");
- }
- }
通过构造方法,我们就可以在创建对象的时候边给它赋值,省去了一个一个变量赋值的麻烦
如果我们不自己定义构造方法,那么编译器就会生成一份默认的无参构造方法,但如果我们自己定义了构造方法,编译器就不会生成了,说白了就是“救急不救穷”
关于构造方法的重载,我们得先来认识什么是重载?
重载:就是方法名称相同,但是参数列表不相同(顺序、个数、类型)的情形,这样的同名不同参数的方法之间,就称之为方法的重载
- //编译器默认给的无参构造方法
- public Student() {
-
- }
-
- //自己创建的有参构造方法
- public Student(String name, int age, String gender) {
- this.name = name;
- this.age = age;
- this.gender = gender;
- }
重载的好处在于:它方便了程序员可以根据不同的参数顺序、个数、类型来自动匹配方法,减少写多个方法名的重复步骤。所以我们在创建对象时,可以根据需要选择是否要初始化对象
在idea中,它给我们提供了快速生成构造方法的途径



这样就能让idea自动帮你生成有参构造方法啦
封装是面向对象的三大特征之一,其余两项分别是继承和多态,今天我们着重讲一下封装
封装:就是当我们用类去设计对象去处理某一个事物的数据时,应该把要处理的数据,以及处理数据的方法,设计到应该对象中去。简单来说——将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互,就是封装
合理隐藏、合理暴露。我们在设计封装的时候要牢记这“八字真言”。就像一辆汽车,它的内部是由很多成员的,比如发动机、油箱等器件,汽车设计者会用外壳把这些内部元器件都隐藏起来,只暴露出方向盘、刹车、油门这些器件供司机使用。这就是所谓的合理隐藏、合理暴露
如果我们想要公开成员,可以使用public来修饰,如果想要隐藏成员,可以使用private来修饰

我们可以发现,成员变量name是用public修饰的,那在我们创建好student对象后,可以用对象引用直接调用它并赋值;而成员变量age是用private修饰的,我们用同样的方法却会报错。这是因为,public是公开的,面向任意包的任意类;而private就只能在当前类使用
如果我们就是想要调用成员变量age,那要怎么做呢?
我们可以在Student类里定义getAge和setAge方法,用来得到age和给age赋值。这两个方法使用public修饰的,相当于age的经纪人,它们可以让对象间接的接触到age,这样就能解决上面的问题了。而成员方法也是同理,用public就表示公开,用private就表示隐藏

在一般情况下,我们会将成员变量设置为private,成员方法设置为public。诚然,实际情况还得根据业务需求来定,这里只是提供参考
在idea中,它也给我们提供了快速get和set方法的途径



这样就能让idea自动帮你生成get和set方法啦
今天我们一起学习了Java当中的类与对象,还讲解了this关键字、构造方法以及封装的知识,希望大家能喜欢这篇文章,有总结不到位的地方还请多多谅解,若有出现纰漏,希望大佬们看到错误之后能够在私信或评论区指正,博主会及时改正,共同进步!