1.“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl、Python、Ruby是动态语言,C++、Java、C#不是动态语言,但是Java有着一个非常突出的动态相关机制,Reflection,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的class。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造,并生成其对象实体,或对其属性赋值、或调用其里面的方法。
2.Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态地获取信息以及动态调用对象的方法的功能Java语言的反射机制。【简单来说,反射机制就是将类的各个组成部分(属性、方法、构造器)封装为其它对象。】
3.反射提供的功能有:①在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。②反编译:.class–>.java。③通过反射机制访问Java对像的属性、方法、构造方法、注解等。
4.反射的相关类
java.lang.Class 类
java.lang.reflect.Constructor 构造方法
java.lang.reflect.Field 成员属性
java.lang.reflect.Method 成员方法
java.lang.reflect.Modifier 修饰符
5.Java类加载的三个阶段
①源代码(source)—经过编译器编译后生成的.class字节码文件。
②类加载(class)—.class字节码文件经过类加载器classloader加载到虚拟机内存,类加载器解析.class文件生成Class类型的对象。
③运行时(runtime)—newInstance()根据Java类型生成对象。
图解:
6.代码示例
package com.cyl.reflect;
public class User {
private String name;
public Integer age;
public String address;
Boolean flag;
protected Long id;
public static Integer a = 100;
public final static Integer b = 200;
public User() {
System.out.println("new User()");
}
private User(Boolean flag) {
this.flag = flag;
System.out.println("new User(flag)");
}
User(String name) {
this.name = name;
System.out.println("new User(name)");
}
public User(String name, Integer age) {
this.name = name;
this.age = age;
System.out.println("new User(name,age)");
}
public String say(String msg) {
System.out.println(msg);
return msg;
}
@Deprecated
public void show() {
System.out.println("show time...");
}
private void method1() {
System.out.println("method1...");
}
void method2() {
System.out.println("method2...");
}
protected void method3() {
System.out.println("method3...");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Boolean getFlag() {
return flag;
}
public void setFlag(Boolean flag) {
this.flag = flag;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + ", flag=" + flag + ", id=" + id + "]";
}
}
package com.cyl.reflect;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
public class ReflectDemo {
public static void main(String[] args)
throws ClassNotFoundException, NoSuchFieldException, SecurityException, NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// Class对象获取方式①源代码阶段
Class<?> class1 = Class.forName("com.cyl.reflect.User");
// Class对象获取方式②Class对象阶段
Class<User> class2 = User.class;
// Class对象获取方式③对象阶段
Class<? extends User> class3 = new User().getClass();
System.out.print(class1 == class2 && class2 == class3);// true
System.out.println();
System.out.println(class1.getName());// com.cyl.reflect.User 获取完全限定类名
System.out.println(class1.getSimpleName());// User 获取类名
System.out.println("----------");
// 构造方法--start
// 获取公有的(public)构造方法
Constructor<?> constructor = class1.getConstructor();
Constructor<?> constructor2 = class1.getConstructor(String.class, Integer.class);
Constructor<?>[] constructors = class1.getConstructors();
// 获取构造方法(忽略修饰符)
Constructor<?> declaredConstructor = class1.getDeclaredConstructor();
Constructor<?> declaredConstructor2 = class1.getDeclaredConstructor(String.class);
Constructor<?> declaredConstructor3 = class1.getDeclaredConstructor(Boolean.class);
Constructor<?>[] declaredConstructors = class1.getDeclaredConstructors();
//打破访问权限
declaredConstructor3.setAccessible(true);
//1--public 2--private 4--protected 0--无修饰
int modifiers = declaredConstructor.getModifiers();
System.out.println(modifiers);
//调用构造方法
Object newInstance = declaredConstructor.newInstance();
Object newInstance2 = declaredConstructor2.newInstance("lucy");
Object newInstance3 = declaredConstructor3.newInstance(true);
System.out.println(newInstance3);//User [name=null, age=null, flag=true, id=null]
// 构造方法--end
System.out.println("----------");
// 成员变量--start
// 根据属性名获取公有的(public)属性对象,若‘非公有’或‘属性名不存在’报java.lang.NoSuchFieldException;
// Field nameField = class1.getField("name");//java.lang.NoSuchFieldException
// Field name2Field = class1.getField("name2");//java.lang.NoSuchFieldException
Field ageField = class1.getField("age");
System.out.println(ageField);// public java.lang.Integer com.cyl.reflect.User.age
// 获取所有公有的(public)属性对象
Field[] fields = class1.getFields();
System.out.println(Arrays.asList(fields));// [public java.lang.Integer com.cyl.reflect.User.age, public
// java.lang.String com.cyl.reflect.User.address]
// 根据属性名获取属性对象(忽略修饰符)
Field nameDeclaredField = class1.getDeclaredField("name");
System.out.println(nameDeclaredField);
// 获取所有属性对象(忽略修饰符)
Field[] declaredFields = class1.getDeclaredFields();
System.out.println(Arrays.asList(declaredFields));
for (Field field:declaredFields) {
//成员属性修饰符--类型--名称
System.out.println(field.getModifiers()+"--"+field.getType()+"--"+field.getName());
}
System.out.println();
//打破访问权限
nameDeclaredField.setAccessible(true);
//给newInstance3里面的name属性赋值tom
nameDeclaredField.set(newInstance3, "tom");
//给newInstance3里面的age属性赋值18
ageField.set(newInstance3, 18);
System.out.println(newInstance3);//User [name=tom, age=18, flag=true, id=null]
// 成员变量--end
System.out.println("----------");
// 成员方法--start
// 获取公有的(public)成员方法
Method method1 = class1.getMethod("show");
Method method2 = class1.getMethod("say", String.class);
Method[] methods = class1.getMethods();
// 获取成员方法(忽略修饰符)
Method declaredMethod = class1.getDeclaredMethod("method1");
Method[] declaredMethods = class1.getDeclaredMethods();
for (Method method : declaredMethods) {
//成员方法修饰符--返回类型--方法名称--参数个数
System.out.println(method.getModifiers()+"--"+method.getReturnType()+"--"+method.getName()+"--"+"--"+method.getParameterCount());
}
System.out.println();
//调用newInstance3里的方法
Object invoke = method1.invoke(newInstance3);
System.out.println(invoke);//返回值 null
Object invoke2 = method2.invoke(newInstance3, "hello");
System.out.println(invoke2);//返回值 hello
//打破private访问权限
declaredMethod.setAccessible(true);
declaredMethod.invoke(newInstance3);
//获取方法上注解
Method show = class1.getDeclaredMethod("show");//@Deprecated
Annotation[] annotations = show.getAnnotations();
for(Annotation annotation:annotations) {
System.out.println(annotation.annotationType());//interface java.lang.Deprecated
}
// 成员方法--end
}
}