一、枚举
- JDK1.5引入了枚举类型,枚举类型的定义包括枚举声明和枚举体
enum 枚举名 {
枚举体 (常量列表);
}
-
枚举实质上是一个类,所有枚举类型隐形的继承自java.lang.Enum(抽象类),其构造函数是私有的,所以不能通过new去产生枚举的实例对象,而事实上每个被枚举的成员实质上就是一个枚举类型的实例,默认被
public static final
修饰,可以直接通过枚举类型名使用它们 -
使用场景
- 当需要定义一组常量时可以使用枚举类型;
- 尽量不要使用枚举的高级特性,高级特性都可以使用普通类来实现;
- 没必要引入枚举增加程序的复杂性。
二、反射机制(reflection)
- class类和反射技术
- 首先在Java中存在两种对象,一种是实例对象,一种是Class对象;
- 实例对象可以通过new关键字得到,但是Class对象不能通过new关键字获取,因为Class对象是JVM生成用来保存对应类的信息的,也就是说当一个类编译成.字节码class文件后,同时还会生成一个Class对象保存在.class文档中;
- Java的反射机制是
在运行状态中:
- 对于任意一个类,都能够知道这个类的属性和方法,
- 对于任意一个方法,都能够调用它的任意一个方法和属性
这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制
- 方法
可以进行反编译从.class逆向到.java,通过反射机制来访问一个java对象的属性和方法
1)首先拿到一个Class对象
得到Class对象的三种方式:
- 直接通过类名.Class的方式得到
- 通过getClass获取Class对象
因为getClass()方法是Object类的方法,所有的类都继承了Object类,因此所有的类的对象也都具有getClass()方法。
- 通过Class对象的forName()静态方法来获取(但可能抛出ClassNotFoundException异常)
获取Class对象:
class Student {
public int age;
public String name;
public Student() {
}
public void fun1() {
System.out.println("Student fun1()");
}
}
public class TestDemo3 {
public static void main(String[] args) throws ClassNotFoundException {
Student student = new Student();
Class class1 = student.getClass();
Class class2 = Student.class;
Class class3 = Class.forName("Student");
System.out.println(class1 == class2);
System.out.println(class2 == class3);
}
}
可以看出一个类只会产生一个Class对象,即不管通过以上三种当中哪种一种方式得到的Class对象,其地址都是唯一的
2)三个重要的类型
- Field
- Method
- Constructor
方法 | 用法 |
---|---|
getName() | 获得类的完整名字 |
getFields() | 获得类的public类型的属性 |
getDeclaredFields() | 获得类的所有属性(包括private) |
getMethods() | 获得类的public类型的方法 |
getDeclaredMethods() | 获得类的所有方法(包括private) |
getMethord(String name,Class[] parameterTypes) | 获得类的特定方法,name参数指定方法名,parameterTypes指定方法的参数类型 |
getConstructors() | 获得类的public类型的构造方法 |
getConstructor(Class[] parameterTypes) | 获得类的特定构造方法,parameterTypes参数指定构造方法的方法名 |
getDeclaredConstructor() | 返回指定参数类型的所有构造方法,包括public和非public |
newInstance() | 通过类的不带参数的构造方法创建这个类的一个对象 |
例如使用getName()得到类名,使用getFields()得到类的public属性,使用getDeclaredFields()得到类的所有属性:
Student student = new Student();
Class class1 = Class.forName("Student");
String classname = class1.getName();
System.out.println(classname);
Field[] field = class1.getFields();
System.out.println(Arrays.toString(field));
Field[] field1 = class1.getDeclaredFields();
System.out.println(Arrays.toString(field1));
运行结果:
- 反射机制性能问题:
- setAccessible
启用和禁用访问安全检查的开关,值为true则表示反射的对象在使用时应该取消Java语言的访问检查,值为false则指示反射的对象应实施访问安全检查,并不是true可以访问而false不能访问;
Field field2 = class1.getDeclaredField("name");
field2.setAccessible(true);
Student stu = (Student)(class1.newInstance());
field2.set(stu,"Daria");
System.out.println(field2.get(stu));
运行结果: