1.封装
1.1 封装的概念
面向对象程序三大特性:封装、继承、多态。我们今天就来学习三大特性中的封装
问题:究竟什么是封装了?
从封装的字面意思,我们就可以看出封装就是把一个东西封起来,让别人看不见 这其实就是封装
那我们举例说明,让大家对封装大致的认知
我们就拿计算机的主板来举例,我们知道计算机大多硬件都是按装在主板上的,而主板安装在主机箱内的,我们平时是看不到主板的,除非把主机箱打开才可以看到主板。那我们就可以说主板封装在了主机箱内,将内部实现细节给隐藏起来了,提供给用户的只是一些接口,我们通过这些接口就可以使用到整个主板以及主板上硬件的功能。比如:用户通过接口键盘、显示器一些外部设备,让用户能跟计算机进行交互
通过上述的举例相信大家对封装有了大致的了解,那接下来我们就引出封装的概念
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互
1.2 访问限定符
我们经常在成员变量和成员方法前面加上 public ,其实 public 也就是访问限定符
Java中主要通过类和访问权限来实现封装:类可以将数据以及封装数据的方法结合在一起,而访问权限用来控制方法或者字段能否直接在类外使用。
Java中提供了四种访问限定符:
public:公开的,在任何地方都可以使用。可以理解为一个人的外貌特征,谁都可以看得到
protected:主要是用在继承中(先做了解,会面讲)
default: 只能在同一个包中使用。可以理解为对于自己家族中(同一个包中)不是什么秘密,对于其他人来说就是隐私了
private:私有的,只能在同一个包的同一个类中使用。可以理解为只有自己知道,其他人都不知道
注:
什么都不写时的默认权限是 default
访问权限除了可以限定类中成员的可见性,也可以控制类的可见性
一般情况下成员变量设置为private,成员方法设置为public
1.3 封装扩展之包
1.包的概念
包就相当于计算机中的文件夹,假设有一个歌曲的文件夹那么里面肯定都是存放歌曲的, 假设有一个笔记的文件夹那么里面肯定都是存放笔记的。
这样做的目的就是为了更好的文件,把多个相同类型的文件收集在一起成为一组,就变成了文件夹
通过上面的例子,我们就可以引出包的概念了
包的概念:为了更好的管理类,把多个类收集在一起成为一组,称为软件包
在Java中也引用了包,包是对类、接口等的封装机制的体现,是一种对类或者接口等的很好的组织方式。比如:一个包中的类不想被其他包中的类使用
注:在同一个工程中允许存在相同名称的类,只要处在不同的包中即可
2.如何导入包中的类
你们还记得我们之前写代码的时候需要输入,就需要 实例化一个 Scanner ,而 Scanner 这个类是Java提供的,当我们输入Scanner敲回车的时候,编译器会自动在文件顶部自动导入包
import java.util.Scanner;
这句代码就是敲回车时,自动导入的包。这种就是用 import 导入包
除了这个导入包的方法,还可以用完整类名导入包
java.util.Scanner scanner = new java.util.Scanner(System.in);
那么现在我们就知道导入包有两种方式:①使用完整的类名导入包 ②使用 import 语句导入包
① 使用完整的类名导入包
Java 中已经提供了很多现成的类供我们使用. 例如Date类:可以使用 java.util.Date 导入 java.util 这个包中的 Date 类
public class Test { public static void main(String[] args) { java.util.Date date = new java.util.Date(); // 得到一个毫秒级别的时间戳 System.out.println(date.getTime()); } }
Data 这个类是 Java 已经提供的,但是在不同包中类名是可以一样的,所以 Data 这个类,可能在很多包中都存在,但是功能却不一样。我们需要告诉编译器用哪个包中的 Data 类,所以可以使用完整的类名告诉编译器是哪个包中的 Data 类
② 使用 import 语句导入包
上述使用完整的类名,写起来就显得很麻烦,那么我们就可以使用 import 语句去导入包
import java.util.Date; public class Test { public static void main(String[] args) { Date date = new Date(); // 得到一个毫秒级别的时间戳 System.out.println(date.getTime()); } }
在文件的开头用 import 导入 Data 完整类名(import java.util.Date) 或者类所在的包( java.util ),这样当我们使用 Data 类时,就知道用哪个包中的Data 类
如果需要使用 java.util 中的其他类, 可以使用 import java.util.*
但是我们更建议显式的指定要导入完整类名或者直接拿完整类名去使用, 否则还是容易出现冲突的情况
4.自定义包
如何自定义一个包咧?
在 IDEA 中新建一个包:右击 src --》new --》Package , 在弹出的对话框中输入包名,即可生成一个包
如何在包中新建一个类?
右击包名 --》new --》Java class ,在弹出的对话框中输入类名,即可新建一个类
一般在包中新建的类文件,通常文件的的最上方加上一个 package 语句指定该代码在哪个包中
如果一个类没有 package 语句, 则该类被放到一个默认包中
5. private访问权限控制举例
学习了包之后了,我们就可以来理解 private 访问权限控制的举例了
通过 package 后面的包名我们就可以知道他们是两个不同的包中的类, 我们在Test2这个类的主函数中需要实例化 Test1 这个类,就需要用 import 导入它完整的类名。实例化完成之后我们通过对象名使用 age 这个成员变量,会直接报错原因就是 age 是 private 修饰的,它只能在同一个包中的同一个类中直接使用。如果我们想要使用 age 这个成员变量就需要调用 returnAge 这个成员方法,返回 age 成员变量的值。那么 returnAge 就相当于我们之前所说的接口,age 就实现了封装。
2.static成员
2.1 static修饰的成员变量
假设目前我有一个学生类:
public class Student { private String name; private int age; }
我们知道一个类可以实例化多个对象,就相当于一个学生类可以实例化多个学生,假设实例化的学生对象都是属于一个班级里面的,我们现在需要在 Student 类中定一个班级,如果把这个班级定义成了成员变量,那么每次实例化的时候都会班级都会在对象中占空间,但是所有的学生都属于这个班级,这样的话,可以就会造成空间的浪费。那么我们就可以把班级定义为 static 修饰的成员变量
public class Student { private String name; private int age; private static int classRoom = 2131; }
static修饰的成员变量,称为静态成员变量,静态成员变量最大的特性:不属于某个具体的对象,是所有对象所共享的。
【静态成员变量特性】:
不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中
既可以通过对象访问,也可以通过类名访问,但一般更推荐使用类名访问
类变量存储在方法区当中
生命周期伴随类的一生(即:随类的加载而创建,随类的卸载而销毁 )
2.2 static修饰的成员方法
一般类中的数据成员都设置为 private,而成员方法设置为 public,那设置之后,Student类中classRoom属性如何在类外访问呢?
public class Student { private String name; private int age; private static int classRoom = 2131; public static int getClassRoom() { return classRoom; } }
Java中,被static修饰的成员方法称为静态成员方法,是类的方法,不是某个对象所特有的。静态成员一般是通过静态方法来访问的
【静态方法特性】
不属于某个具体的对象,是类方法
可以通过对象调用,也可以通过类名.静态方法名(...)方式调用,更推荐使用后者
不能在静态方法中访问任何非静态成员变量
静态方法中不能调用任何非静态方法,因为非静态方法有this参数,在静态方法中调用时候无法传递this引用
2.3 static成员变量初始化
构造方法中初始化的是与对象相关的实例属性,所有静态成员变量一般不会放在构造方法中来初始化
静态成员变量初始化一共有两种:①就地初始化 ②静态代码块初始化
①就地初始化
就地初始化:在定义静态成员变量的时候直接初始化
private static int classRoom = 2131;
这个就是直接初始化
②静态代码块初始化
说到静态代码块初始化,那么我们就不得不详谈一下什么是代码块