一般情况下,我们使用某个类时必定知道它是什么类,是用来做什么的,并且能够获得此类的引用。于是我们直接 对这个类进行实例化,之后使用这个类对象进行操作。
反射则是一开始并不知道我要初始化的类对象是什么,自然也无法使用 new 关键字来创建对象了。这时候,我们 使用 JDK 提供的反射 API 进行反射调用。 反射就是在运行状态中 , 对于任意一个类 , 都能够知道这个类的所有属性和 方法 ; 对于任意一个对象 , 都能够调用它的任意方法和属性;并且能改变它的属性(包括私有方法和属性)。是Java 被视为动态语言的关键。 Java反射机制主要提供了以下功能: 在运行时构造任意一个类的对象 在运行时获取或者修改任意一个类所具有的成员变量和方法 在运行时调用任意一个对象的方法(属性) Class 反射始于 Class , Class 是一个类,封装了当前对象所对应的类的信息。 一个类中有属性,方法,构造器等,比如说 有一个 Person 类,一个 Order 类,一个 Book 类,这些都是不同的类,现在需要一个类,用来描述类,这就是 Class,它应该有类名,属性,方法,构造器等。 Class 是用来描述类的类。 Class 类是一个对象照镜子的结果,对象可以看到自己有哪些属性,方法,构造器,实现了哪些接口等等。对于每 个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个类的有关信息。 对象只 能由系统建立对象,一个类(而不是一个对象)在 JVM 中只会有一个 Class 实例。 获得 Class 对象 获取 Class 对象的三种方式 1.通过类名获取 类名.class 2.通过对象获取 对象.getClass() 3.通过全类名获取 Class.forName(全类名) classLoader.loadClass( 全类名 ) 直接获取某一个对象的 class Class > klass = int . class ; Class > classInt = Integer . TYPE ; 调用某个对象的 getClass() 方法 StringBuilder str = new StringBuilder ( "123" ); Class > klass = str . getClass (); 判断是否为某个类的实例 一般地,我们用 instanceof 关键字来判断是否为某个类的实例。同时我们也可以借助反射中 Class 对象的 isInstance() 方法来判断是否为某个类的实例,它是一个 native方法: public native boolean isInstance ( Object obj ); 判断是否为某个类的类型 public boolean isAssignableFrom(Class> cls); 创建实例 通过反射来生成对象主要有两种方式 1.使用Class对象的newInstance方法来创建Class对象对应类的实例 Class > c = String . class ; Object str = c . newInstance (); 这种方法是调用类的无参数构造,如果这个类没有无参构造就会抛出这个异常java.lang.NoSuchMethodException,如果无参构造是私有的则会抛出java.lang.IllegalAccessException: Class com.example.fragmentadaptertest.annotation.AnnotationTest can not access a member of class com.example.fragmentadaptertest.annotation.Student with modifiers "private" 2. 先通过 Class 对象获取指定的 Constructor 对象,再调用 Constructor 对象的 newInstance() 方法来创建实例。这 种方法可以用指定的构造器构造类的实例。 通过这种先获取构造器再去创建实例的方法可以调用私有的构造方法 // 获取 String 所对应的 Class 对象 Class > c = String . class ; // 获取 String 类带一个 String 参数的构造器 Constructor constructor = c . getConstructor ( String . class ); // 根据构造器创建实例 Object obj = constructor . newInstance ( "23333" ); System . out . println ( obj ); 获取构造器 得到构造器的方法 Constructor getConstructor ( Class [] params ) -- 获得使用特殊的参数类型的 public 构造函数 ( 包括父类) Constructor [] getConstructors () -- 获得类的所有公共构造函数 Constructor getDeclaredConstructor ( Class [] params ) -- 获得使用特定参数类型的构造函数 ( 包括私有 ) Constructor [] getDeclaredConstructors () -- 获得类的所有构造函数 ( 与接入级别无关 ) 获取类构造器的用法与上述获取方法的用法类似。主要是通过 Class 类的 getConstructor 方法得到 Constructor 类的一个实例,而Constructor 类有一个 newInstance 方法可以创建一个对象实例 : public T newInstance ( Object ... initargs ) //不同的参数列表对应不同的构造方法 获取类的成员变量(字段)信息 Field getField ( String name ) -- 获得命名的公共字段 Field [] getFields () -- 获得类的所有公共字段 Field getDeclaredField ( String name ) -- 获得类声明的命名的字段 Field [] getDeclaredFields () -- 获得类声明的所有字段 调用方法 Method getMethod ( String name , Class [] params ) -- 使用特定的参数类型,获得命名的公共方法 Method [] getMethods () -- 获得类的所有公共方法 Method getDeclaredMethod ( String name , Class [] params ) -- 使用特写的参数类型,获得类声明的命名的方法 Method [] getDeclaredMethods () -- 获得类声明的所有方法 当我们从类中获取了一个方法后,我们就可以用 invoke() 方法来调用这个方法。 invoke 方法的原型为 : public Object invoke ( Object obj , Object ... args ) //前面的参数是类的实例,后面是方法的参数 附上练习代码public class Student {
int age;
String name;
private String password = "bbbbb";
public static int HEIGHT = 180;
private static int WEIGHT = 130;
public int getAge(){
return age;
}
public Student(int age) {
this.age = age;
}
public Student(int age, String name) {
this.age = age;
this.name = name;
}
private Student() {
}
private void setAge(int age) {
this.age = age;
}
private String getName() {
return name;
}
private void setName(String name) {
this.name = name;
}
private String getPassword() {
return password;
}
private void setPassword(String password) {
this.password = password;
}
}
public static void main(String[] args) {
Class> studentClass = Student.class;
Student student1 = new Student(1,"");
Class> student1Class = student1.getClass();
System.out.println(student1 instanceof Student);
System.out.println(studentClass.isInstance(student1));
System.out.println(studentClass.isAssignableFrom(Student.class));
try {
String studentClassName = Student.class.getName();
System.out.println(studentClassName);
Class> student2Class = Class.forName(studentClassName);
Class> student3Class = ClassLoader.getSystemClassLoader().loadClass(studentClassName);
//通过获取私有构造创建实例
Constructor> constructor = studentClass.getDeclaredConstructor();
//setAccessible这个非常重要只有设置了这个才能动私有的东西
constructor.setAccessible(true);
Object student = constructor.newInstance();
Field passwordField = studentClass.getDeclaredField("password");
String passwordFieldName = passwordField.getName();
String passwordFieldNameFirstWord = passwordFieldName.substring(0, 1).toUpperCase();
String setPassword = "set" + passwordFieldNameFirstWord + passwordFieldName.substring(1,
passwordFieldName.length()
);
//通过反射获取私有方法,通过私有方法改变私有的属性值
Method methodGetPwd = studentClass.getDeclaredMethod("getPassword", new Class[]{});
methodGetPwd.setAccessible(true);
System.out.println(methodGetPwd.invoke(student, new Object[]{}));
Method methodSetPwd = studentClass.getDeclaredMethod(setPassword, String.class);
methodSetPwd.setAccessible(true);
methodSetPwd.invoke(student, "aaaaa");
System.out.println(methodGetPwd.invoke(student, new Object[]{}));
passwordField.setAccessible(true);
passwordField.set(student, "ccccc");
System.out.println(passwordField.get(student));
Field field = student3Class.getField("HEIGHT");
System.out.println( field.get(Student.class));
field.set(Student.class,185);
System.out.println(field.get(Student.class));
field.set(student,190);
System.out.println(field.get(student));
Field field1 = student3Class.getDeclaredField("WEIGHT");
field1.setAccessible(true);
System.out.println(field1.get(Student.class));
field1.set(Student.class,140);
System.out.println(field1.get(Student.class));
field1.set(student,145);
System.out.println(field1.get(student));
} catch (Exception e) {
e.printStackTrace();
}
}
利用反射创建数组
数组在
Java
里是比较特殊的一种类型,它可以赋值给一个
Object Reference
其中的
Array
类为
java.lang.reflflect.Array
类。我们通过
Array.newInstance()
创建数组对象,它的原型是
:
public static
Object
newInstance
(
Class
>
componentType
,
int
length
);
这样使用
Student[] students = (Student[]) Array.newInstance(Student.class,10);
反射获取泛型真实类型



