行业知识
【Java之新手基础必备】面向对象(上)
博客主页:Zhui_Yi_
:上期回顾:二叉树
❤️感谢大家点赞收藏⭐评论✍,您的三连就是我持续更新的动力❤️
追当今朝天骄,忆顾往昔豪杰。
文章目录
- 前言
- 一、面向对象思想
- 1.引入
- 2.面向过程和面向对象概述
- ①面向过程
- ②面向对象
- I概述
- II特点
- III开发
- IV设计
- V特征
- 代码示例
- 面向过程
- 面向对象
- 二、类与对象
- 1.类的定义
- 2.对象的创建与使用
- 3.对象的内存图
- ①一个对象的内存图
- ②2个对象的内存图
- ③三个对象的内存图
- 4.局部变量与成员变量的不同
- 5.形式参数的问题
- 6.匿名对象
- 三、封装
- 1.定义
- 2.引入
- 3.private关键字
- 4.应用
- 快捷键
- 应用
- 5.this关键字
- 注意事项
- 6.toString方法
- 四、构造方法
- 1.注意事项
- 2.格式
- 3.举例
- 五、访问控制权限
- 介绍
- 举例示例
- 缺省
- protected
- private
- 总结
- 总结
前言
又见面喽,本篇文章会给大家带来以下内容:面向对象思想、类与对象及其使用对象的内存图、成员变量和局部变量的区别、匿名对象、封装(private)、this关键字、构造方法。
一、面向对象思想
1.引入
我们想一下我们在做数组的时候,当有多个数组都需要遍历时,我们可以将遍历的代码封装到方法中,需要遍历时,就调用相应的方法即可,提高代码的复用性。但是如果我们要再增添一些功能的时候,比如获取最值,数值逆序等,同样需要将这些功能封装到相应的方法中。但是这样继续封装会发现方法越来越多,于是就想能不能将这些方法继续进行封装呢?
当然有了,通过前面的讲解我们知道类是可以存放方法的,所以,我们就考虑使用类封装来这多个方法,将来再做数组的操作时,不用去找具体的方法,先找到这个类,然后使用这个类中的方法。
2.面向过程和面向对象概述
①面向过程
我们在前面写程序的时候,我们需要一步一步去实现,而具体的每一步都需要我们去实现和操作,这其实是面向过程开发,即:
就是面向着具体的每一个步骤和过程,把每一个步骤和过程完成,然后由这些功能方法相互调用,完成需求。
②面向对象
I概述
那么当我们随着需求的更改,功能的增多,发现需要面对每一个步骤很麻烦了,那我们能不能把这些步骤和功能在进行封装,封装时根据不同的功能,进行不同的封装,功能类似的封装在一起。这就是面向对象的思想:
其概述为
面向对象是基于面向过程的编程思想
II特点
是一种更符合我们思想习惯的思想
可以将复杂的事情简单化
将我们从执行者变成了指挥者
III开发
就是不断的创建对象,使用对象,指挥对象做事情
IV设计
其实就是在管理和维护对象之间的关系。
V特征
- 封装(encapsulation)
- 继承(inheritance)
- 多态(polymorphism)
关于各个特征的概念我们会分开详细的讲,在这里不过多阐述。
代码示例
这里以把大象装进冰箱为例:
把大象装进冰箱分三步:打卡冰箱门,把大象装进去,关闭冰箱门。
面向过程
面向过程就是分布用函数实现,代码如下:
public class FaceToProcess { public static void main(String[] args) { open(); in(); close(); } public static void open(){ System.out.println("打开冰箱门"); } public static void close(){ System.out.println("关闭冰箱门"); } public static void in(){ System.out.println("把大象装进冰箱"); }}面向对象
面向对象则是把构成问题的事务按照一定规则划分为多个独立的对象。那么我们思考一下,对于本题,应该划分多少个对象?
两个。
- 大象:被装进冰箱
- 冰箱:打卡冰箱门,关闭冰箱门
那么此时我们就要定义类了:
一个大象类,大象要干什么?被装进冰箱里,要定义一个实现方法:
public class Elephant { public void in(){ System.out.println("把大象装进冰箱"); }}然后是冰箱类,要打卡冰箱门,关闭冰箱门,需要定义两个实现方法:
public class Refrigerator { public void open(){ System.out.println("打开冰箱门"); } public void close(){ System.out.println("关上冰箱门"); }}那么如何实现上述类呢?
需要定义一个测试类Demo,代码实现如下:
public class Demo { public static void main(String[] args) { Refrigerator rg = new Refrigerator(); rg.open(); Elephant elephant = new Elephant(); elephant.in(); rg.close(); }}结果一样。
当然,我们现在看,面向对象不如面向过程简单,but诸君请随我往下看:
二、类与对象
1.类的定义
我们考虑一下我们上边举得一个例子:我们可以从大象类中定义一个方法,让大象被放进冰箱里面,这是从一个抽象到具体。那么反过来就是:
类是对象的抽象,用于描述一组对象的共同特征和行为。
类中可以定义成员变量和成员方法,其中:
- 成员变量用于描述对象的特征,成员变量也被称作对象的属性
- 成员方法用于描述对象的行为,可简称为方法。
- 也就是如下定义:
- class 类名{ 成员变量; 成员方法; }
在这里举出一个例子:
学生类:
成员变量:姓名,年龄,地址等等
成员方法:学习,吃饭,睡觉
在这里代码实现以下:
首先我们需要顶一个学生类,学生类中包含以上信息,即:
但是我们要记住,我们之前声明的变量都是在方法里面,我们称为局部变量,而我们现在声明的都在类的里面,方法的外面,我们称为成员变量(关于两者的区别,我们会在下文给出)。
成员变量定义如下:
String name; int age; String address;
我们可以看出此时也有些区别,成员变量是不用跟局部变量一样赋初值的。
接下我们定义成员方法:
public void study(){ System.out.println(name+"在学习Java"); } public void eat(){ System.out.println(name+"学习饿了,去吃饭"); } public void sleep(){ System.out.println(name+"学习困了,去睡觉"); }整体类如下:
public class Student { String name; int age; String address; public void study(){ System.out.println(name+"在学习Java"); } public void eat(){ System.out.println(name+"学习饿了,去吃饭"); } public void sleep(){ System.out.println(name+"学习困了,去睡觉"); }}接下来定义一个实现类:
在实现类中我们可以先看一下各个变量的初始值:
Student s=new Student(); //访问默认值 System.out.println(s.name+"\t"+s.age+"\t"+s.address);
然后我们再赋初值:
s.name="追忆"; s.age=18; s.address="洛阳";
然后我们再打印一下,看是否被修改:
然后我们再调用方法:
s.study(); s.eat(); s.sleep();
看一下效果:
测试类完整程序:
public class Demo { public static void main(String[] args) { Student s=new Student(); //访问默认值 System.out.println(s.name+"\t"+s.age+"\t"+s.address); s.name="追忆"; s.age=18; s.address="洛阳"; System.out.println(s.name+"\t"+s.age+"\t"+s.address); s.study(); s.eat(); s.sleep(); }}2.对象的创建与使用
在上面使用Student类的时候,我们是如何创建对象的?
类名 对象名称 = new 类名();
会创建了,那么该如何使用对象呢,我们通过.,也就是如下
对象名称.属性名
对象名称.方法名
3.对象的内存图
①一个对象的内存图
如图,左边是代码,右边是内存图,我将讲述,代码如何在内存图中实现:
- 首先,JVM启动会先去找main方法,main方法加载进栈
- 然后执行第一条语句,Phone p,为p赋初值,然后new,存地址,在堆里创建空间,此时Phone中有三个成员变量,所以开辟三个空间,并为三个变量初始化默认值
- 然后再通过p来访问三个变量,对三个变量赋值
- 而对于,三个成员方法,为什么没在堆里面开空间?:方法会在堆空间里开辟空间,存地址,通过地址的访问,来实现加载进栈。
- 而在call方法内,有一个形参,此时就会在栈空间里面,也就是call所在的那一段空间为其开辟空间。
- 在执行成员方法时,执行完一个,释放掉一个,直到在实现到主方法最后,对main方法释放空间。
- 然后p断开与堆空间的联系,堆空间就成为了垃圾,在空闲时释放掉。
②2个对象的内存图
如图,理论同上,不解释。
③三个对象的内存图
4.局部变量与成员变量的不同
在类中的位置不同
成员变量 类中方法外
局部变量 方法内或者方法声明上
在内存中的位置不同
成员变量 堆内存
局部变量 栈内存
生命周期不同
成员变量 随着对象的存在而存在,随着对象的消失而消失
局部变量 随着方法的调用而存在,随着方法的调用完毕而消失
初始化值不同
成员变量 有默认的初始化值
局部变量 没有默认的初始化值,必须先定义,赋值,才能使用。
5.形式参数的问题
在这里我们先给出概念,然后再给出代码,实现:
基本类型:形式参数的改变不影响实际参数。实参应该有确定的值,且其值的数据类型级别不能高于对应的形参数据类型的级别,参数的传递相当于赋值语句,即实参的值赋给形参。
引用类型:形式参数的改变直接影响实际参数。参数的传递相当于赋值语句,实参的地址赋给形参,使得形参和实参指向同一个堆内存空间。
如果你看到一个方法需要的参数是-一个类名,就应该知道这里实际需要的实参是-一个具体的对象。
public class ArgsText { public static void main(String[] args) { int a = 10; int b = 20; Demo d = new Demo(); //参数为基本数据类型 int result=d.sum(a,b); System.out.println(result); }} //形式参数时基本类型 class Demo{ public int sum(int a,int b){ return a+b; }}此时我们将主函数定义的a,b为实参,传递给Demo类中的方法sum做形参。即,赋值调用。
此时我们再举一个例子,形式参数做引用类型:
此时我们先定义一个Student类:
class Student{ public void show(){ System.out.println("我们爱Java"); }}此时Student类型就相当于int
然后我们再让它作为引用类型:
class StudnetDemo{ public void method(Student s){ s.show(); }}我们在实现一下上述代码:
StudnetDemo sd = new StudnetDemo(); //必须先创建一个Student对象作为实参 Student s=new Student(); //参数为引用(类)类型 sd.method(s);
完整函数如下:
public class ArgsText { public static void main(String[] args) { int a = 10; int b = 20; Demo d = new Demo(); //参数为基本数据类型 int result=d.sum(a,b); System.out.println(result); System.out.println("=========="); StudnetDemo sd = new StudnetDemo(); //必须先创建一个Student对象作为实参 Student s=new Student(); //参数为引用(类)类型 sd.method(s); }}//这个Student类型就相当于intclass Student{ public void show(){ System.out.println("我们爱Java"); }}//形式参数是引用(类)类型class StudnetDemo{ public void method(Student s){ s.show(); }} //形式参数时基本类型 class Demo{ public int sum(int a,int b){ return a+b; }}6.匿名对象
这里直接给出定义:
匿名对象:就是没有名字的对象。是对象的一种简化表示形式
匿名对象的两种使用情况
- A:调用方法,仅仅只调用一次的时候。 注意:调用多次的时候,不适合。 那么,这种匿名调用有什么好处吗? 有,匿名对象调用完毕就是垃圾。
B:匿名对象可以作为实际参安传递给形式参数,相当于赋值语句
下面给出示例:
我们先定义一个Student类:
public class Student { public void show(){ System.out.println("我们爱Java!"); }}然后我们定义一个测试类,调用两次:
public class Demo { public static void main(String[] args) { Student s = new Student(); s.show(); s.show(); }}但如果我们只调用一次呢?
可以用下述方法:
new Student().show();
调用如下:
好处是调用完之后,就是垃圾,回收的比较快!
而对于匿名对象可以作为实际参安传递给形式参数,我们给出下述例子:
我们先定义一个StudentDemo类,让Student作为类型
public class StudentDemo { public void method(Student s) { s.show(); }}我们再主函数中实现以下:
StudentDemo sd = new StudentDemo(); sd.method(new Student());
我们再来个更特别的:
new StudentDemo().method(new Student());
结果如上。
三、封装
铺垫了辣么久,终于该讲重点了!!!开森
1.定义
这里直接给出,我相信不用解释了:
封装是指一种将类的实现细节包装、隐藏起来的方法。
它有两层含义,第一层含义是指把对象的属性和行为看成是一个密不可分的整体,将这两者“封装”在一起(即封装在对象中);另外一层含义指“信息隐藏”,将不想让外界知道的信息隐藏起来。
我们为什么需要封装:
就比如我我定义一个学生类的时候,定义了一个成员变量age,如果我不将其封装起来,此时任何人都可以看见,都可以改变。这样可以吗?
当然不可以。
我们在使用这个案例的过程中,发现了一个问题:
通过对象去给成员变量赋值,可以赋值一些非法的数据。
这是不合理的。
应该是这个样子的:在赋值之前,先对数据进行判断。
判断到底在哪里做比较合适呢?
StudentDemo类是-一个测试类,测试类一般只创建对象,调用方法。
所以,这个判断应该定义在Student类中。
而我们在成员变量的位置可不可以进行数据判断呢?
是不可以的,因为做数据校验必须要依靠一 些逻辑语句。
逻辑语句是应该定义在方法中的,所以,我们最终决定在Student类中提供一个方法来对数据进行校验。
2.引入
但是呢,我们能在定义变量时就对其判断嘛?
不能。
所以我们只能给出一个方法来校验。
此时我们先给出一个Student类,类中用名字,年龄两个变量。
我们要给出一个方法来判断即:
public class Student { String name; int age; public void setAge(int a){ if(a System.out.println("年龄输入错误"); }else{ age=a; } }} return age; } private int num=10; public void show(){ System.out.println("num="+num); } private void method(){ System.out.println("私有的method方法"); } public void function(){ method(); }} public static void main(String[] args) { Student s1 = new Student(); s1.setAge(18); s1.setName("追忆"); System.out.println(s1.getName()+"\t"+s1.getAge()); }} this.name = name; } return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } System.out.println("无参构造方法!"); } public Student(String name){ System.out.println("带String参数的构造方法!"); this.name = name; } public Student(int age){ System.out.println("带int参数的构造方法!"); this.age = age; } public Student(String name, int age){ System.out.println("带多个参数的构造方法!"); this.name = name; this.age = age; } double weight; void f2(){ } double f1(double a,double b){ this.weight=23.5; f2(); return a+b; }} public static void main(String[] args) { A a = new A(); a.weight=23.5; System.out.println(a.weight); System.out.println(a.f1(3,5)); }} public static void main(String[] args) { A a = new A(); a.weight=23.5; System.out.println(a.weight); System.out.println(a.f1(3,5)); }} protected double weight; protected void f2(){ } protected double f1(double a,double b){ this.weight=23.5; f2(); return a+b; }} private double weight; private void f2(){ } private double f1(double a,double b){ this.weight=23.5; f2(); return a+b; }}
上一篇:畅行无忧服务器怎么样?
下一篇:stand怎么读英语语音?