封装
什么是封装?
封装是指将类的属性隐藏在内部,外部不能直接访问和修改,必须通过类提供的方法来完成属性的访问和修改。封装的核心思想就是尽可能把属性都隐藏在内部,对外提供方法来访问,我们可以在这些方法中田间逻辑处理来实现过滤,以屏蔽错误的数据的赋值。
封装的步骤
- 修改属性的访问权限,使得外部不能直接访问
- 提供外部可以直接调用的方法
- 在方法中加入属性控制逻辑
- 所以我们需要将类中的成员变量的访问权限设置为私有(private),既只能在类的内部访问,外部无法直接访问该属性。
- 同时提供外部可以调用的方法,方法同样需要设置访问权限,很显然需要将方法的访问权限设置为 public。
- 在方法中添加确保属性值正确的逻辑代码。
封装完成后每一个属性都添加了两个方法: getter 和 setter,外部通过 getter 获取该属性的值,通过 setter 方法修改该属性的值
static 关键字
Java 程序要运行就必须在某个类中定义一个 main 方法作为程序的入口,我们会发现爱定义 main 方法时,有一个 static 关键字,那 static 表示什么呢? 为什么要用 static 来修饰 main 方法?本节内容为你一一揭晓。
static 表示静态或全局,可以用来修饰成员变量和成员方法以及代码块。
- 要访问类中的成员变量或者成员方法,必须首先创建该类的对象,然后通过对象才能访问成员变量的成员方法,也就是说成员变量和成员方法的访问必须依赖于对象,这是常规的方式。
- 而 static 修饰的成员变量和成员方法独立于该类的任何一个实例对象,访问时不依赖于该类的对象。可以理解为被该类的所有实例对象共用,所以说它是全局。
- 用 static 修饰的成员变量叫作静态变量页脚类变量, static 修饰的成员方法叫作静态方法,也叫作类方法。多个对象共用,内存只有一份。
- 没有被 static 修饰的成员方法叫作实例变量,没有被 static 修饰的成员方法叫作实例方法,一个对象对应一个,内存中有多份。
既然静态成员变量和静态成员方法独立于任何一个实例对象,我们在访问这些静态资源时就无须创建对象,直接通过类即可访问。
class User{
public static String name;
public static void show(){
System.out.println("这是一个User对象")
}
}
public class Test{
public static void main(String[] args){
User.name = "张三";
System.out.println(User.name);
User.show();
}
}
这种写法是没有问题的,不会报错
下面进行几个实例分析
代码 A
public class Test{
private int id;
public static void main(String[] args){
Test test = null;
for(int i = 0; i < 10; i++){
test = new Test();
test.id++;
}
System.out.println(test.id);
}
}
分析:代码 A 的运行结果为1,因为此时的 id 为成员变量,每个实例化对象都拥有一个自己的 id。循环中创建了10个 Test 对象,内存中就会有10个 id,每个 id 都进行了加一操作,由0变为1,并且每次循环都会将新创建的 Test 对象赋给变量 test ,相当于更新了 10 次 test 的引用。 应为每次的 id 值都为 1 ,所以最终的结果也为 1
代码 B
public class Test{
private static int id;
public static void main(String[] args){
Test test = null;
for(int i = 0; i < 10; i++){
test = new Test();
test.id++;
}
System.out.println(test.id);
}
}
分析:代码 B 的运行结果为 10,因为此时的 id 是静态变量,属于类不属于对象,内存中只有一份,所以任何时候对 id 的修改都会作用在同一个变量,循环中共执行了 10 次 id++,所以 id 的值为 10
代码 C
public calss Test{
private static int id;
public static void main(String[] args){
for(int i = 0; i < 10; i++){
Test.id++;
}
System.out.println(Test.id);
}
}
分析: 代码 C 的运行结果为 10 ,具体的原因同代码 B,唯一的却别在于代码 B 是通过实例化对象访问静态变量的, 代码 C 是通过类来访问静态变量的,运行结果没有区别。
我们在使用 static 修饰成员方法时需要注意,静态方法中不能使用 this 关键字,不能直接访问所属类的实例变量和实例方法,可直接访问类的静态变量和静态方法。若要访问类的实例变量和实例方法,必须先实例化类的对象,然后通过对象去访问
static 修饰代码块
重要:
static 除了可以修饰成员变量和成员方法之外,还可以修饰代码块,被 static 修饰的代码块被叫作静态代码块。静态代码块的特点是只执行一次,在什么时候执行呢?当该类被加载到内存时执行,不需要手动调用,他会自动执行,在什么时候类第一次被加载?这里我们需要简单地阐述一下 Java 加载类的机制。我们知道 Java 代码时偶类构成的,但是真正运行时是通过对象和对象之间的相互调用关系来完成需求的。即在程序运行时,需要在内存中创建多个对象,对象怎么创建?需要通过类来创建,类是模板,同时这个模板只需要加载一次,所以程序在运行时,首先会讲程序中用到的类加载到内存中,并且只加载一次。然后通过类来创建多个对象以完成具体的业务。被加载到内存中的类叫作运行时类,静态代码块就是在加载类的时候执行的,因为类只加载一次,所以静态代码块也只执行一次。简单的理解,当代码中第一次出现某个类时,就会执行静态代码块,静态代码块只能访问静态变量和静态方法。
public class User{
public static int num;
static{
num++;
System.out.println("执行了静态代码块");
}
}
public class Test{
public static void main(String[] args){
User user = new User();
User user2 = new User();
User user3 = new User();
System.out.println(user.num);
System.out.println(user2.num);
System.out.println(user3.num);
}
}
运行结果应该为:
执行了静态代码块
1
1
1
通过结果可以得出结论:虽然创建了 3 个 User 对象,但是静态代码块只执行一次。如果有多个静态块同时存在,则按先后顺序执行,类的构造方法用于初始化类的实例,类的静态代码块用于初始化类,给类的静态变量赋值。