目录
一、封装
1.1 封装的概念
面向对象程序三大特性:封装、继承、多态。而类和对象阶段,主要研究的就是封装。封装简单来说就是套壳屏蔽细节。举个例子,手机中都有主板,而产家不会直接将一个主板直接卖给用户,而会对手机进行外壳的包装,将内部实现细节隐藏起来,仅仅对外提供开关机、按键以及插孔等,让用户和手机屏幕、按键交互,实际上手机真正工作的是CPU、内存等元件。
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。例如:被private修饰的成员变量或者方法,就只能在当前类中使用,其他类无法直接调用,但是我们可以通过Getter and Setter方法来间接调用,举个例子:
class Student {
public String name;
public int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public void eat() {
System.out.println(this.name + "在吃饭");
}
}
public class Demo {
public static void main(String[] args) {
Student student = new Student("小蓝",10);
student.name = "小绿";
student.eat();//小绿在吃饭
}
}
上述代码中,可以成功获取到 student 类中的 name 和 eat(),输出“小绿在吃饭”,但若我们将 name 和 eat() 利用 private 封装,会发生什么呢?
我们发现,成员变量和方法被封装后,编译器就开始报错,说明我们无法直接获得 student 类中的 name 和 eat(),但是我们可以想办法间接获取,如上文所说,利用 Getter and Setter 方法:
class Student {
private String name;
public int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void getEat() {
eat();
}
private void eat() {
System.out.println(this.name + "在吃饭");
}
}
public class Demo {
public static void main(String[] args) {
Student student = new Student("小蓝",10);
student.setName("小绿");
System.out.println(student.getName());//小绿
student.getEat();//小绿在吃饭
}
}
这样子我们就成功解决无法直接调用问题,此外,Getter and Setter 方法我们还可以让编译器帮我们实现成员变量的 Get 和 Set 方法, 使用快捷键 Alt+Insert 或点击鼠标右键如下:
注:如上图,也可以单独选择 Getter 或者 Setter 方法。
1.2 访问限定符
Java 中主要通过类和访问权限来实现封装:类可以将数据以及封装数据的方法结合在一起,更符合人类对事物的认知,而访问权限用来控制方法或者字段能否直接在类外使用。Java 中提供了四种访问限定符:
这四种访问限定符中 public 可以理解为公共电话,谁都可以用;default 可以理解为家门口的密码,家里人 (同一个包中) 知道,别人不能知道;private 是只有自己可以用,其他人都不可以用; protected 主要是用在继承中,子类继承父类后,利用 super() 来访问。
注:成员变量没有访问限定符修饰的话,默认为 default 。
1.3 软件包
1.3.1 包的概念
在面向对象体系中,提出了一个软件包的概念,即:为了更好的管理类,把多个类收集在一起成为一组,称为软件包。有点类似于目录。比如:为了更好的管理电脑中的歌曲,一种好的方式就是将相同属性的歌曲放在相同文件下,也可以对某个文件夹下的音乐进行更详细的分类。
1.3.2 导入包中的类
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());
}
}
上述的导入比较麻烦,我们还可以使用import语句导入包,如下:
import java.util.Date;
public class Test {
public static void main(String[] args) {
Date date = new Date();
System.out.println(date.getTime());
}
}
注:若我们还想使用 java.util 中的其他类,可以使用 import java.util.* 。
1.3.3 自定义包
在Java中也引入了包,包是对类、接口等的封装机制的体现,是一种对类或者接口等的很好的组织方式,比如:一个包中的类不想被其他包中的类使用。包还有一个重要的作用:在同一个工程中允许存在相同名称的类,只要处在不同的包中即可。那我们该如何建包呢?如下图:
注:包的名称一般使用域名的倒置,包即是文件夹。
二、static成员
2.1 static修饰成员变量
static修饰的成员变量,称为静态成员变量,静态成员变量最大的特性:不属于某个具体的对象,是所有对象所都具有的。
【静态成员变量特性】
1、不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中。
2、推荐通过类名访问,用对象访问也可以,但是不推荐。
3、被 static 修饰后,该静态成员变量的值存储在方法区当中。
4、生命周期伴随类的一生 (即:随类的加载而创建,随类的卸载而销毁)。
类的成员变量有2种:
1、静态成员变量
(1)属于类,不属于对象,只有一份。
(2)类名 + 点号来访问静态成员变量才是合理的,对象来访问不合理。
(3)不依赖对象。
2、非静态成员变量
(1)属于对象,每实例化一个对象,都会有一个对应的非静态成员变量,每个对象都有。
(2)对象的引用 + 点号来访问。
(3)依赖对象。
2.2 static修饰成员方法
Java 中,被 static 修饰的成员方法称为静态成员方法,是类的方法,不是某个对象所特有的。静态成员一般是通过静态方法来访问的。静态方法中不能访问任何非静态成员变量,也不能直接调用任何非静态方法,例如:
上图中成员变量 name 和方法 sleep() 都无法成功编译,就是因为 name 和 sleep()都是非静态的,若我们加上 static 修饰,就可以成功编译,如下:
【静态方法特性】
1. 不属于某个具体的对象,是类方法。
2. 可以通过对象调用,也可以通过类名.静态方法名(...)方式调用,更推荐使用后者。
3. 不能在静态方法中访问任何非静态成员变量。
4. 静态方法中不能调用任何非静态方法,因为非静态方法有this参数,在静态方法中调用时候无法传递this引用。
三、代码块
1、普通代码块
普通代码块是直接使用 {} 定义在方法中的代码块,不需要条件,永远都会被执行,很少使用。
2、构造代码块
构造代码块是使用 {} 定义在类中的代码块(不加修饰符),也叫实例代码块。构造代码块一般用于初始化实例成员变量。
3、静态代码块
使用 static{} 定义的代码块称为静态代码块。一般用于初始化静态成员变量。
【代码块特性】
1、静态代码块是最先被执行的,其次是实例代码块,最后是构造方法。
2、静态代码块不管生成多少个对象,其只会执行一次。
3、静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的。
4、如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次执行 (合并) 。
5、实例代码块只有在创建对象时才会执行。
注:合并意思是最后一次定义的值就是该变量的值。
总结
1、成员变量没有访问限定符修饰的话,默认为 default。
2、静态成员变量随类的加载而创建,随类的卸载而销毁。
3、this 不能出现在静态方法中。
4、不能在静态方法中访问任何非静态成员变量。
5、使用 {} 定义的一段代码称为代码块。
6、java.util 是 java 提供的工具程序包,可以用 import java.util.* 导入。
7、静态代码块是最先被执行的,其次是实例代码块,最后是构造方法。