今日任务
1、理解封装的思想,会使用private关键字隐藏类的属性和行为;
2、理解并掌握构造函数的用法;
3、理解并掌握this关键字的用法
4、理解掌握static关键字的用法
面向对象有三个基本特征:
封装、继承、多态
1. 封装
1.1.封装的概念
封装:就是包装的意思;
生活中的包装:食品包装;快递包装;明星包装;
好处:好看;可以保护被包装的东西;
1.2.封装的好处
组装电脑;
台式机主机组成:
主板;硬盘;显卡;内存;电源;CPU;风扇;机箱;
如果没有机箱,将这些原件都直接安装在主板上,连接电源,一样也可以用;
但是里面所有东西都直接暴漏在外面,太不安全,也不美观;使用也不方便;
所以使用包装,可以提高安全性、美观性和易用性;
java代码中的封装:
函数:封装一段具体实现功能的代码;
类:封装了同一类事物的共有的属性(成员变量)和行为(函数);
所以java中的封装还可以提高代码复用性,降低开发和维护的难度;
结论:
封装的好处:
可以隐藏事物的细节,提高安全性、易用性和美观性;还可以提高代码的复用性;
1.3.封装的实现
1.3.1.问题引入
需求:描述学生的信息;
//需求:描述学生的信息;
1、找对象:学生
2、描述对象:
学生{
姓名;
性别;
年龄;
学号;
学习(){}
}
3、测试学生
学生 小明 = new 学生();
小明.姓名= “小明”;
小明.性别 = “男”;
小明.年龄 = 18;
小明.学号 = 34;
小明.学习();
class Student//表示学生信息的类
{
String name;//姓名
int age;//年龄
String sex;//性别
int num;//学号
void study(){
System.out.println("good goodstudy, day day up!");
}
}
//创建一个测试类
class Test
{
public static void main(String[] args)
{
//创建一个学生对象
Student stu = new Student();
//测试学生的属性
stu.name = "小红";
stu.age = 8;
stu.sex = "男";
stu.num = 100;
System.out.println("姓名:"+stu.name+";性别:"+stu.sex+";年龄:"+stu.age+";学号:"+stu.num);
//测试学生的行为
stu.study();
}
}
1.png
问题:如果可以直接操作事物的属性,容易出现错误的数据,造成程序不符合逻辑;
思考解决办法:
可以考虑通过一个函数来给对象的成员变量赋值,在赋值的时候对传入的参数进行检验,如果数据不合法,就给出错误提示,就行了;
结论:使用函数赋值可以解决上面的问题;
但是只有函数还不行,因为可以直接操作类的属性,那么就可以绕过这个函数,不使用它;
所以要彻底解决这个问题,还要作出限制,只能通过这个函数赋值,不能直接操作类的属性;
所以可以考虑使用封装,将这个类的成员变量隐藏起来;
1.3.2.private关键字
private:一个访问权限修饰符,表示被修饰的成员(成员变量、函数)是私有的,只能在定义它的类中使用,不能被其他地方使用;
public:一个访问权限修饰符,表示被修饰的成员是公开的,所有地方都能使用;public可以修饰成员变量、函数和类,如果修饰类,这个类的类名必须和java的文件名一致;所以一个java文件中可以写多个类,但最多只能由一个public的类;
4.jpg
5.jpg
问题:隐藏一个事物的属性之后,外界不能直接来修改,但同时也不能够获取了,那应该怎么办;
所以还需要提供一个公开的方法,用于外界获取这个属性值;
6.jpg 7.jpg
结论:要想将一个类的一个属性隐藏起来,需要使用private关键字修饰;
因为修饰之后只能在本类中使用,别的地方既不能修改,也不能获取,所以为了让其它地方还可以操作,一般要再对外提供两个函数,供外界修改和获取这个属性;
1.3.3.set和get函数
实际上,在开发中,一般一个类的成员变量都应该私有化,同时提供公开的赋值和取值的方法,而且这两个方法的命名都有一个规范:
赋值方法的方法名:set+变量名(变量名首字母大写)
取值方法的方法名:get + 变量名(变量名首字母大写)
8.png
结论:
封装,就是包装,主要用来隐藏事物的实现细节,提高程序的安全性;如果外界需要访问被封装的属性,需要对外提供公开的getter和setter函数;
2. 构造函数
2.1.构造函数的引入
在我们现实生活中,一般一个事物,一旦创建,都具有一些属性值;
要想在java中模拟这种情况,就需要再创建对象的时候直接给对象的成员变量赋值;而要实现这种功能,就需要使用构造函数;
2.1.1.概念
构造函数,又叫做构造器,就是在对象创建的时候由JVM自动调用的函数;
2.1.2.作用
构造函数就是用来在创建对象的时候给对象的成员变量赋值用的;
2.1.3.写法
修饰符: 构造函数,不能使用static关键字修饰,可以使用访问权限修饰符修饰;
返回值类型: 没有返回值类型;(连void都没有)
函数名:只能和类名完全一样(连每个字母的大小写都一样);
参数列表: 构造函数可以重载,具体的参数列表需要根据具体需求确定;
return语句: 构造函数也要通过return语句结束出栈,只是一般都会省略不写;
9.png2.1.4.调用
10.png 11.jpg 12.png再创建对象时,跟在new关键字后面的内容,实际上就是在调用构造函数;
13.png2.2.构造函数的执行过程
14.png2.3.默认构造函数
原来,创建对象时写在new关键字后面的类名加小括号,是在调用构造函数;
实际上,再java中,每一个类都至少有一个构造函数;创建对象都是通过构造函数进行的;
如果一个类中没有直接书写构造函数,编译器编译时会帮我们添加一个无参的构造函数,这个构造函数就是默认构造函数;
15.png
默认构造函数,都是无参的函数;
默认构造函数只在一个类中没有书写构造函数时无参的够着函数才会才会存在;
结论:如果创建对象时调用的构造函数不存在,就会出现编译错误;
要解决这个问题:
1、再类中写一个需要调用的构造函数;
2、不用这个不存在的,而是使用存在的构造函数去创建对象;
2.4.构造函数的使用细节
1、如果使用private修饰构造函数,会有什么结果?
如果使用private[y1] 关键字修饰构造函数,那么再类外面因为不能使用这个构造函数,所以就不能通过这个构造函数创建对象;
如果一个类中所有构造函数都私有化了,就不能再其他类中创建这个类的对象;
可以在这个类里面创建自身的对象;再单例设计模式中会使用到这个特性;
2、构造函数能不能调用一般函数?
16.png3、一般函数能不能调用构造函数?
17.png2.5.构造函数和一般函数的区别
1、从书写格式上看:
a) 构造函数:没有返回值类型,连void都不能写;构造函数的函数名必须和类名一样;不能用static关键字修饰;
b) 一般函数:必须有一个返回值类型(是和构造函数最主要的区别);一般函数名不要和类名一样;可以用static修饰,也可以不要;
如果一个函数函数名和类名一样,是否是构造函数,就要看有没有返回值类型;没有,就是构造函数;
2、从调用方式上看:
a) 构造函数:创建对象时由JVM调用的;一般函数不能调用构造函数;
b) 一般函数:哪里需要哪里就可以调用;构造函数里面也可以调用一般函数;
3、从作用上看:
a) 构造函数:主要用来在创建对象的时候,给对象的成员变量赋值用的;
b) 一般函数:实现某个具体功能;
4、从一个对象可以调用次数上看:
a) 构造函数:只有创建对象时会调用一次;
b) 一般函数:没有次数限制;
2.6.构造函数之间的调用
1、构造函数中可以调用其他构造函数,不能直接通过函数名调用,而是需要使用this关键字来实现;
18.png结论:构造函数之间的相互调用,需要通过this关键字实现;
2、this调用构造函数,必须写在构造函数的第一行;
3、调用其他构造函数,要避免交叉调用(直接或者间接);
递归:一个函数直接或间接的调用自身;
2.7.构造函数总结
概念: 创建对象时由JVM自动调用的函数
作用: 在创建对象的时候给对象的成员变量赋值;
写法:
修饰符:可以用访问权限修饰符(public、private等)修饰;不能用static修饰;
返回值类型:没有返回值类型,连void都没有;
函数名:必须和类名完全一样;
参数列表:可以重载,具体根据要求而定;
return语句:有,但是一般都不需要写;
执行过程:
创建对象时,JVM遇到new关键字,首先要到堆内存中开辟对象空间;然后在对象空间中为成员变量分配空间,赋默认值;
然后再根据new关键字后面的内容,调用相应的构造函数进栈执行;等到构造函数执行结束,对象创建完成;
默认构造函数:
所有类中都至少有一个构造函数,如果一个类中没有书写构造函数,编译器就会帮我们添加一个无参的构造函数,这个构造函数就是默认构造函数;
一旦类中书写了构造函数,就不会再有默认构造函数;
使用细节:
构造函数可以调用一般函数;
一般函数不能调用构造函数;
构造函数可以调用构造函数,不能通过函数名调用,必须通过this****关键字调用;
在构造函数中使用this语句调用其他构造函数,this语句必须写在构造函数的第一行;
构造函数之间相互调用,不能出现交叉调用(递归调用);
1、什么时候需要使用构造函数?
只要创建对象,都要使用构造函数;
2、什么时候需要自定义构造函数?
如果希望在创建对象时就给成员变量赋值,就需要自定义构造函数;
3、使用构造函数,可以在创建对象的时候就给对象的成员变量赋初始值,那么,有了构造函数,还需要提供get和set方法吗?
需要;
因为构造函数只能在创建对象的时候赋值一次;如果以后想要改变这个值,就需要用到set函数;如果需要获取被封装的值,就需要用到get函数;
3. this关键字
3.1.this关键字
this:这个,表示对自身所属对象的引用;
谁调用this,this就指向谁;
this,就相当于现实生活中所说的一个字:我;
3.2.this的应用
1、实现构造函数之间的相互调用;
2、在函数中区分成员变量和局部变量;
20.png
构造函数中给成员变量赋值时不加this的情况:
21.png
函数中通过this关键字调用成员变量的原理:
22.png
3.3.this练习
需求:创建一个描述人的类,并提供比较是否是同龄人的功能;
23.png4. static关键字
4.1.static简介
static:静态
static的作用:可以用来修饰类的成员(除了构造函数),修饰的成员都是静态的;
静态,表示和类的对象无关,直接和类本身有关,静态成员都直接可以使用类名访问;
4.2.静态函数
概念:被static关键字修饰的函数就是静态函数;
格式:直接将static关键字写在函数的返回值类型前面;
使用方法:静态函数和类的对象无关,直接通过类名调用
内存原理:
java程序的内存划分:
寄存器;本地方法区;方法区;栈内存;堆内存;
方法区:主要保存静态成员、class、常量等一些东西;
使用细节:
1、静态函数不能调用非静态函数和非静态成员变量
原因:
非静态函数和非静态成员变量都必须依赖类的对象使用;
而静态函数使用都不需要有对象,所以在静态函数中不能直接调用非静态函数和非静态成员变量;
2、非静态函数可以调用静态函数
原因:
非静态函数只能通过类的对象使用;如果可以调用非静态函数,说明此时已经存在对象;
已经存在对象,说明类已经加载完毕;
类已经加载完毕,所以静态函数肯定可以使用;
3、构造函数不能是静态的
因为构造函数是在创建对象的时候用来给对象的成员变量赋值用的;
如果构造函数可以是静态的,就不需要对象就能使用,就没有意义;
4、静态函数中不能使用和对象有关的关键字
因为有些关键字,例如this,就是表示一个对象的引用的,而静态函数是没有对象就可以直接使用的,所以不能在静态函数里面使用this等关键字;
还有一个关键字:super;
应用练习:
需求:创建一个描述学生的类,并提供学习的功能;
26.png
27.png
结论:如果一个函数中没有使用非静态的成员,这个函数就要声明为静态函数,可以减少内存浪费;
4.3.静态成员变量
概念:使用static关键字修饰的成员变量叫做静态成员变量
格式:直接将static关键字写在成员变量的数据类型前面
使用方法:静态成员变量和类的对象无关,直接通过类名调用;
内存原理:
29.png特点:一个类中的静态成员变量,在这个类的所有对象中共享;
静态成员变量和非静态成员变量的区别:
1、从保存位置:
a) 静态成员变量:保存在方法区的静态区域
b) 非静态成员变量: 保存在堆内存的对象空间中
2、从书写格式上看:
a) 静态成员变量: 需要使用static关键字修饰,将static关键字直接写在数据类型前面;
b) 非静态成员变量: 不需要使用static关键字修饰;
3、从生命周期上看:
a) 静态成员变量: 类加载的时候就分配空间和赋值;直到这个类被卸载(或者整个程序结束);
b) 非静态成员变量: 创建对象的时候才分配空间和赋值;对象成为垃圾空间被回收的时候;
4、从使用方法上看:
a) 静态成员变量: 可以直接通过类名使用,和类的对象无关;
b) 非静态成员变量: 必须通过类的对象使用;
5、从修改后的影响范围上看:
a) 静态成员变量: 所有对象都收到影响;
b) 非静态成员变量: 只对这一个对象有影响;
4.4.static小结
static:静态的,用来修饰成员变量和函数,不能修饰构造函数;
静态函数:被static关键字修饰的函数就是静态函数;
静态函数的格式:将static关键字写在函数的返回值类型前面
静态函数的特点:
1、和类的对象无关,可以直接通过类名调用
2、只能调用静态函数和静态成员变量,不能使用和类的对象有关的成员(this关键字;super关键字;非静态成员变量;非静态函数;)
3、非静态函数可以调用静态函数和非静态函数,也可以使用静态成员变量和非静态成员变量;
静态成员变量:被static修饰的成员变量就是静态成员变量;
静态成员变量的格式:将static关键字写在成员变量的数据类型前面;
静态成员变量的特点:
1、和类的对象无关,直接通过类名调用;
2、保存在方法区的静态区域,被该类的所有对象共享;
3、在类加载完成时就完成空间分配和赋值;
什么时候应该使用静态函数和静态成员变量?
不需要对象,和对象无关的时候,就需要定义为静态成员;
(静态成员变量又叫做类变量、类字段;静态函数又叫做类函数、类方法)
什么时候不能将函数定义为静态的?
如果一个函数中使用了非静态成员变量,就不能将其定义为静态的函数;
网友评论