访问控制权限
Java中的访问控制权限:4个
public
公开的
protected
受保护的
default
默认
private
私有的
按照权限从大到小依次为:
public
-> protected
-> default
(没有权限修饰词)-> private
。
访问控制修饰符 | 本类 | 同包 | 子类 | 任意位置 |
---|---|---|---|---|
public | ✔ | ✔ | ✔ | ✔ |
protected | ✔ | ✔ | ✔ | ✘ |
默认 | ✔ | ✔ | ✘ | ✘ |
private | ✔ | ✘ | ✘ | ✘ |
类的成员不写访问修饰时默认为default
。
默认对于同一个包中的其他类相当于公开(public),对于不是同一个包中的其他类相当于私有(private)。
受保护(protected)对子类相当于公开,对不是同一包中的没有父子关系的类相当于私有。
Java中,外部类的修饰符只能是public或默认,类的成员(包括内部类)的修饰符可以是以上四种。
结论
-
封装性是指
private
、default
、protected
三个权限的使用。 -
对于封装来说,90%使用的都是
private
、只有10%的情况下会使用protected
,一般不会使用default
。
通过反射机制获取Filed
Student.java
public class Student {
// 4个Field分别采用不同的访问控制权限
// 按照权限从大到小排序:public -> protected -> default(没有权限修饰词)-> private
public int no; // 公开的
protected String name; // 受保护的
int age; // 默认的
private boolean sex; //私有的
}
ReflectTest04.java
public class ReflectTest04 {
public static void main(String[] args) throws Exception {
// 获取整个类
Class studentClass = Class.forName("com.hk.javase.Student");
System.out.println("完整类名:" + studentClass.getName()); //com.hk.javase.Student
System.out.println("简类名:" + studentClass.getSimpleName()); //Student
// 获取类中所有的public修饰的Filed
Field[] fields = studentClass.getFields();
System.out.println(fields.length); //1
System.out.println(fields[0].getName()); //no
// 获取所有的Filed
Field[] declaredFields = studentClass.getDeclaredFields();
System.out.println(declaredFields.length); //4
// 遍历
for (Field declaredField : declaredFields) {
// 获取属性的修饰符
int modifiers = declaredField.getModifiers(); //返回的修饰符是一个数字,每个数字是修饰符的代号
String modifierString = Modifier.toString(modifiers); //把数字代号转换成字符串
System.out.print(modifierString + " ");
// 获取属性的类型
System.out.print(declaredField.getType().getSimpleName() + " ");
// 获取属性的名字
System.out.println(declaredField.getName());
}
}
}
使用反射机制反编译Filed
ReflectTest05.java
public class ReflectTest05 {
public static void main(String[] args) throws Exception {
StringBuilder stringBuilder = new StringBuilder();
Class studentClass = Class.forName("com.hk.javase.Student");
stringBuilder.append(Modifier.toString(studentClass.getModifiers()) + " class " + studentClass.getSimpleName() + " { \n");
Field[] declaredFields = studentClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
stringBuilder.append("\t");
stringBuilder.append(Modifier.toString(declaredField.getModifiers()) + " " +
declaredField.getType().getSimpleName() + " " +
declaredField.getName() + "; \n");
}
stringBuilder.append("}");
System.out.println(stringBuilder);
}
}
运行结果:
public class Student {
public int no;
protected String name;
int age;
private boolean sex;
}
使用反射机制赋值(重点)
有局限性,私有的属性访问不了,需要暴力访问,这样不安全。
public class ReflectTest06 {
public static void main(String[] args) throws Exception {
// 不使用反射机制赋值
Student student = new Student();
student.no = 123;
System.out.println(student.no); //123
// 使用反射机制赋值
Class studentClass = Class.forName("com.hk.javase.Student");
// obj就是Student对象
Object obj = studentClass.newInstance();
// 根据no属性名称来获取Field
Field noFiled = studentClass.getDeclaredField("no");
// 给obj对象的no属性赋值
noFiled.set(obj,1);
// 获取no属性的值
System.out.println(noFiled.get(obj)); //1
// 私有的属性访问不了,需要使用sexFiled.setAccessible(true);暴力访问
Field sexFiled = studentClass.getDeclaredField("sex");
// 打破封装(不安全)
sexFiled.setAccessible(true);
sexFiled.set(obj,true);
System.out.println(sexFiled.get(obj)); //true
}
}