6.Java基础知识:面向对象02
1、封装
1.1 概念: 封装,就是包装的意思
1.2 用法:
- java中的封装:
函数:封装了一段实现功能的代码;
类:封装了函数和成员变量;
如果外界需要访问被封装的成员变量,就需要在类中提供公开的get和set方法
封装的好处:提高代码复用性;隐藏内部实现细节,提高安全性;
private
关键字
一个访问权限修饰符,表示被修饰的成员(成员变量、函数)是私有的,只能在定义它的类中使用,不能被其他地方使用;
修饰成员变量,直接将private关键字写在成员变量的数据类型前面;
修饰函数,写在函数最前面;
public
关键字
一个访问权限修饰符,表示被修饰的成员是公开的,所有地方都能使用;
public可以修饰成员变量、函数和类;如果修饰类,这个类的类名必须和java的文件名一致;所以一个java文件中可以写多个类,但最多只能由一个public的类;
set
和get
函数
格式:
set的方法名:set + 变量名(变量名首字母大写)
get的方法名:get + 变量名(变量名首字母大写)
2、构造函数
2.1 概念和作用
概念:构造函数,又叫做构造器,就是在对象创建的时候由JVM自动调用的函数;
作用:构造函数就是用来在创建对象的时候给对象的成员变量赋值用的
2.2 写法
修饰符: 可以使用访问权限修饰符,不能使用static关键字修饰;
返回值类型: 构造函数没有返回值类型;void都不能写;(要区分普通函数和构造函数,就看有没有返回值类型)
函数名: 构造函数的函数名,必须和类名完全一致;
参数列表: 构造函数可以重载,参数列表根据需求,需要怎么写就怎么写;
return语句: 有return语句,也是通过return语句结束出栈;一般都不需要写;
2.3 过程
1.JVM执行时遇到new关键字,首先要到堆内存中开辟对象空间,然后将类中的成员变量加载到对象空间中,分配变量空间,赋默认值;
2.根据new关键字后面的代码,调用相应的构造函数进栈执行;
3.构造函数进栈执行,先执行隐藏步,然后执行构造函数中的代码,等构造函数结束出栈,对象创建完成
隐藏步:
1.执行super()语句,调用父类构造函数;
2.给对象空间中的成员变量显示赋值;
3.如果有构造代码块,要执行构造代码块;
- 默认构造函数
实际上,在java中,每一个类都至少有一个构造函数;一个类要创建对象,都必须要调用构造函数;
如果一个类中没有直接书写构造函数,编译器编译时会帮我们添加一个无参的构造函数,这个构造函数就是默认构造函数
一旦类中书写了构造函数,就不会再有默认构造函数;
- 使用注意
构造函数可以调用一般函数;
一般函数不能调用构造函数;
构造函数可以调用构造函数,不能通过函数名调用,必须通过this关键字调用;
在构造函数中使用this语句调用其他构造函数,this语句必须写在构造函数的第一行;
构造函数之间相互调用,不能出现交叉调用(递归调用);
如果一个类中的所有构造函数全部私有化,就不能再其他类中创建对象,只能在本类中创建对象
2.4 构造函数与一般函数区别:
- 从书写格式上看:
构造函数: 没有返回值类型,连void都不能写;构造函数的函数名必须和类名一样;不能用static关键字修饰;
一般函数: 必须有一个返回值类型(是和构造函数最主要的区别);一般函数名不要和类名一样;可以用static修饰,也可以不要;
如果一个函数函数名和类名一样,是否是构造函数,就要看有没有返回值类型;没有,就是构造函数;
- 从调用方式上看:
构造函数: 创建对象时由JVM调用的;一般函数不能调用构造函数;
一般函数: 哪里需要哪里就可以调用;构造函数里面也可以调用一般函数;
- 从作用上看:
构造函数: 主要用来在创建对象的时候,给对象的成员变量赋值用的;
一般函数: 实现某个具体功能;
- 从一个对象可以调用次数上看:
构造函数: 只有创建对象时会调用一次;
一般函数: 没有次数限制
2.5 部分问题
1、什么时候需要使用构造函数?
只要创建对象,都要使用构造函数;
2、什么时候需要自定义构造函数?
如果希望在创建对象时就给成员变量赋值,就需要自定义构造函数;
3、使用构造函数,可以在创建对象的时候就给对象的成员变量赋初始值,那么,有了构造函数,还需要提供get和set方法吗?
需要;
因为构造函数只能在创建对象的时候赋值一次;如果以后想要改变这个值,就需要用到set函数;如果需要获取被封装的值,就需要用到get函数;
3、this
关键字
3.1 概念:表示对自身所属对象的引用,哪个对象调用this,this就指向那个对象;
3.2 应用:
- 实现构造函数之间的相互调用;
- 在函数中区分成员变量和局部变量;
- 实际上,一个类中,所有没有使用static关键字修饰的函数,里面都有隐藏的this关键字
4、static
关键字
static
:静态的,可以修饰类的成员变量和一般函数(不能修饰构造函数),表示被修饰的成员都是静态的,和类的对象无关,可以直接通过类名访问;
4.1 概念
静态的,可以修饰类的成员变量和一般函数(不能修饰构造函数),表示被修饰的成员都是静态的,和类的对象无关,可以直接通过类名访问;
4.2 静态成员变量
概念:使用static关键字修饰的成员变量叫做静态成员变量
格式:直接将static关键字写在成员变量的数据类型前面
private static String key = "KEY";
使用方法:静态成员变量和类的对象无关,直接通过类名调用
内存原理
java的内存分布: 栈内存;堆内存;方法区;本地方法区;寄存器;
方法区:就是用来保存class和静态的成员的,还有常量池等
JVM加载一个类到方法区的时候,首先会分别将这个类中的静态成员变量加载到静态区域,非静态成员加载到非静态区域;
然后为所有静态成员变量再静态区域中分配空间,赋默认值;
所有静态成员变量赋完默认值,就开始为他们显示赋值,所有静态成员变量显示赋值结束,就表示加载完成,可以使用了。
特点
1、和类的对象无关,直接通过类名调用;
2、保存在方法区的静态区域,被该类的所有对象共享;
3、在类加载完成时就完成空间分配和赋值;
4.3 静态成员变量和非静态成员变量:
- 从保存位置:
静态成员变量: 保存在方法区的静态区域
非静态成员变量: 保存在堆内存的对象空间中
- 从书写格式上看:
静态成员变量: 需要使用static关键字修饰,将static关键字直接写在数据类型前面;
非静态成员变量: 不需要使用static关键字修饰;
- 从生命周期上看:
静态成员变量:类加载的时候就分配空间和赋值;直到这个类被卸载(或者整个程序结束);
非静态成员变量: 创建对象的时候才分配空间和赋值;对象成为垃圾空间被回收的时候;
- 从使用方法上看:
静态成员变量:可以直接通过类名使用,和类的对象无关;
非静态成员变量: 必须通过类的对象使用;
- 从修改后的影响范围上看:
静态成员变量:所有对象都收到影响;
非静态成员变量:只对这一个对象有影响;
4.4 静态函数
概念:被static关键字修饰的函数就是静态函数;
格式:直接将static关键字写在函数的返回值类型前面;
使用方法:静态函数和类的对象无关,直接通过类名调用
使用注意
1、静态函数不能调用非静态函数和非静态成员变量
2、非静态函数可以调用静态函数和静态成员变量
3、构造函数不能是静态的
4、静态函数中不能使用和对象有关的关键字
因为有些关键字,例如this,就是表示一个对象的引用的,而静态函数是没有对象就可以直接使用的,所以不能在静态函数里面使用this等关键字;
还有一个关键字:super;
特点:
1、和类的对象无关,可以直接通过类名调用
2、只能调用静态函数和静态成员变量,不能使用和类的对象有关的成员(this关键字;super关键字;非静态成员变量;非静态函数;)
3、非静态函数可以调用静态函数和非静态函数,也可以使用静态成员变量和非静态成员变量;
4.5 部分问题
1.什么时候应该使用静态函数和静态成员变量?
不需要对象,和对象无关的时候,就需要定义为静态成员;
(静态成员变量又叫做类变量、类字段;静态函数又叫做类函数、类方法)
2.什么时候不能将函数定义为静态的?
如果一个函数中使用了非静态成员,就不能将其定义为静态的函数;
3.为什么main函数需要定义为静态的、公开的?
因为非静态函数必须通过对象使用;而main函数时java程序的入口,再执行main函数之前时没有对象的,所以只能将他定义为静态的;
因为只有公开的访问权限,才能再任意地方被使用;
而main函数是由JVM调用的,JVM和main函数不在一个类,也不在一个文件夹, 要能够访问main函数,只能将其定义为public的;