反射是Java被视为准动态语言的关键,反射机制允许程序在执行期间借助Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及其方法(包括private关键字修饰的)
想要获取或操作类创建的对象的内部属性及其方法,首先就要获取该类的Class对象,该类的Class对象是在初始化的时候创建的
1、获得类的Class对象
public class TestReflection {
public static void main(String[] args) throws ClassNotFoundException {
//方式一:通过实例化对象获得
Class c1 = new TestReflection().getClass();
//方式二:forName方法获得
Class c2 = Class.forName("com.hu.www.reflection.TestReflection");
//方式三:通过类名获得
Class c3 = TestReflection.class;
//输出并对比它们的hashCode
System.out.println(c1.hashCode() +"\n"+ c2.hashCode() +"\n"+ c3.hashCode());
}
}
得到的3个hashCode都是相同的,说明一个类只有一个Class对象
2、获取运行时类的完整结构
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
//获取类的信息
public class TestReflection {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class aClass = Class.forName("com.hu.www.reflection.User");
//1、获得类的名字
System.out.println(aClass.getName()); //获得包名 + 类名
System.out.println(aClass.getSimpleName()); //获得类名
Field[] declaredFields = aClass.getDeclaredFields(); //可以找到所有的属性,包括私有的
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
//2、获得指定属性值
Field name = aClass.getDeclaredField("name"); //可以找到private修饰的属性
System.out.println(name);
//3、获得类的所有方法
methods = aClass.getDeclaredMethods(); //获得本类的所有方法,包括私有的
for (Method method : methods) {
System.out.println("getDeclaredMethods:\t" + method);
}
//4、获得指定方法
Method getName = aClass.getMethod("getName", null);
Method setName = aClass.getMethod("setName", String.class);
System.out.println(getName);
System.out.println(setName);
//5、获得指定的构造器
Constructor[] constructors = aClass.getConstructors();
Constructor[] declaredConstructors = aClass.getDeclaredConstructors();
Constructor constructor = aClass.getConstructor(String.class, int.class, int.class);
System.out.println(constructor);
}
}
class User{
private String name;
private int id;
private int age;
public User() {
}
public User(String name, int id, int age) {
this.name = name;
this.id = id;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
3、创建运行时类的对象并调用方法和属性
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//通过反射动态地创建对象
public class TestReflection {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
//获得Class对象
Class aClass = Class.forName("com.hu.www.reflection.User");
//1、通过Class对象调用newInstance方法创建对象
User user1 = (User)aClass.newInstance();
System.out.println(user1);
//2、通过Class对象获取构造器对象,构造器对象再调用newInstance方法创建对象
Constructor constructor = aClass.getConstructor(String.class, int.class, int.class);
User user2 = (User)constructor.newInstance("Hu", 001, 18);
System.out.println(user2);
//3、通过反射调用普通方法
User user3 = (User)aClass.newInstance();
//该类的Class对象通过反射获取方法
Method setName = aClass.getMethod("setName", String.class);
//获取到的方法对象调用invoke方法激活
setName.invoke(user3,"Hu");
System.out.println(user3.getName());
//4、通过反射调用属性
User user4 = (User)aClass.newInstance();
//该类的Class对象通过反射获取属性
Field name = aClass.getDeclaredField("name");
//关闭权限检测
name.setAccessible(true);
//获取到的属性对象调用set方法设置,不能直接操作私有属性,需要关闭程序的安全检测
name.set(user4,"hu");
System.out.println(user4.getName());
}
}
class User{
private String name;
private int id;
private int age;
public User() {
}
public User(String name, int id, int age) {
this.name = name;
this.id = id;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
4、反射操作泛型
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
//通过反射获取泛型
public class TestReflection {
public void test01(Map<String,User> map,List<User> list){
System.out.println("test01");
}
public Map<String,User> test02(){
System.out.println("test02");
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
//1、获取参数的泛型信息
//通过反射获取方法
Method method = TestReflection.class.getMethod("test01", Map.class, List.class);
//方法对象调用getGenericParameterTypes方法获取泛型类型
Type[] genericParameterTypes = method.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
//循环输出所有泛型类型
System.out.println(genericParameterType);
//判断泛型的类型是否为ParameterizedType--参数化类型
if (genericParameterType instanceof ParameterizedType){
//泛型类型为参数化类型,强转为ParameterizedType--参数化类型;并使用getActualTypeArguments方法获取它的真实参数信息
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
//循环输出所有泛型的真实类型
System.out.println(actualTypeArgument);
}
}
}
System.out.println("-----------------------------------------------------");
//2、获取返回值的泛型信息
//通过反射获取方法
method = TestReflection.class.getMethod("test02",null);
//方法对象调用getGenericReturnType方法获取泛型类型
Type genericReturnType = method.getGenericReturnType();
//判断泛型的类型是否为ParameterizedType--参数化类型
if (genericReturnType instanceof ParameterizedType){
//泛型类型为参数化类型,强转为ParameterizedType--参数化类型;并使用getActualTypeArguments方法获取它的真实参数信息
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
//循环输出所有泛型的真实类型
System.out.println(actualTypeArgument);
}
}
}
}
5、反射操作注解
package com.hu.www.reflection;
import java.lang.annotation.*;
import java.lang.reflect.Field;
//联系反射操作注解
public class TestReflection12 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
//创建Student2类的Class对象
Class aClass = Class.forName("com.hu.www.reflection.Student");
//通过反射获得注解
Annotation[] annotations = aClass.getAnnotations();
//获得Student2类的注解
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//获得Student2类的注解value的值
TableHu tableHu = (TableHu)aClass.getAnnotation(TableHu.class);
System.out.println(tableHu.value());
//获得类指定属性的注解
Field field = aClass.getDeclaredField("name");
FieldHu annotation = field.getAnnotation(FieldHu.class);
//获得Student2类的name属性的注解信息
System.out.println("列名:" + annotation.columnName());
System.out.println("类型:" + annotation.type());
System.out.println("长度:" + annotation.length());
}
}
@TableHu("db_student")
class Student{
@FieldHu(columnName = "db_id",type = "int",length = 10)
private int id;
@FieldHu(columnName = "db_age",type = "int",length = 10)
private int age;
@FieldHu(columnName = "db_name",type = "varchar",length = 3)
private String name;
public Student(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
}
//类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableHu{
String value();
}
//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldHu{
String columnName();
String type();
int length();
}
|