一个类在内存中只有一个Class对象,hashCode值都一样
一个类被加载后,类的整个结构都会被封装在Class对象中
实体类:pojo,entity以及自定义注解
@Table("db_user")
class User{
@Filed(columnName = "db_name",type = "varchar")
private String name;
@Filed(columnName = "db_id",type = "int")
private int id;
@Filed(columnName = "db_age",type = "int")
private int age;
public User() {
}
public User(String name, int id, int age) {
this.name = name;
this.id = id;
this.age = age;
}
@Override
public String toString() {
return "user{" +
"name='" + name + '\'' +
", id=" + id +
", 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;
}
private void love(){
System.out.println("love");
}
}
//自定义注解
@Target(ElementType.TYPE)//表示类名注解
@Retention(RetentionPolicy.RUNTIME)
@interface Table{
String value();
}
@Target(ElementType.FIELD)//表示属性注解
@Retention(RetentionPolicy.RUNTIME)
@interface Filed{
String columnName();
String type();
}
1.Class类的三种创建方式
- Class.forName("xxx");
- 类名.class;
- 对象名.getClass();
public static void main(String[] args) throws ClassNotFoundException { //三种方式:类的Class对象 Class> aClass1 = Class.forName("com.bacon.reflect.User"); ClassaClass2 = User.class; User user = new User(); Class extends User> aClass3 = user.getClass(); //一个类在内存中只有一个Class对象,hashCode值都一样 //一个类被加载后,类的整个结构都会被封装在Class对象中 System.out.println(aClass1.hashCode());//21685669 System.out.println(aClass2.hashCode());//21685669 System.out.println(aClass3.hashCode());//21685669 }
结果
21685669 21685669 21685669
类的加载过程:加载,链接,初始化(这里不细化)
2.获取运行时类的完整结构
- Field 字段
- Method 方法
- Constructor 构造函数
- Superclass 父类
- Inerface 接口
- Annotation 注解
//获得类的名字 String name = aClass1.getName();//包名+类名 String simpleName = aClass1.getSimpleName();//类名 //获得类的属性 Field[] fields = aClass1.getFields();//获得public Field[] declaredFields = aClass1.getDeclaredFields();//可以获得所有包括private //重载,可以字段获取属性 Field name1 = aClass1.getDeclaredField("name"); System.out.println(name1); //获得类的方法 Method[] methods = aClass1.getMethods();//获得本类和父类的public方法 Method[] declaredMethods = aClass1.getDeclaredMethods();//获得本类所有方法 //获得指定方法 Method getName = aClass1.getMethod("getName",null); Method setName = aClass1.getMethod("setName", String.class); System.out.println(getName); //获得构造器 Constructor>[] constructors = aClass1.getConstructors();//空参 Constructor> constructor1 = aClass1.getConstructor(String.class, int.class, int.class); //获得指定的构造器 Constructor> constructor = aClass1.getConstructor(); System.out.println(constructor); //构造一个对象 User user1 = (User) aClass1.newInstance();//做一个强转,本质是调用类的无参构造 System.out.println(user1); //通过构造器创建一个对象 Constructor> constructor2 = aClass1.getConstructor(String.class, int.class, int.class); User user2 = (User) constructor2.newInstance("bacon", 1, 25);//也是一个强转 System.out.println(user2); //调用方法 Method setName1 = aClass1.getMethod("setName", String.class); setName1.invoke(user2,"bacon2");//需要传入一个对象 System.out.println(user2); //私有方法 Method love = aClass1.getDeclaredMethod("love", null); love.setAccessible(true);//私有方法也需要设置权限 love.invoke(user2); //操作属性 //Field name2 = aClass1.getField("name");//私有字段获取不到 Field name2 = aClass1.getDeclaredField("name"); /*String name3 = name2.getName();//name System.out.println(name3);*/ //私有字段通过getDeclaredField,但是字段操作必须通过类中方法啊,如果仍需要操作,可以设置安全检测 name2.setAccessible(true);//默认是关闭的 name2.set(user2,"bacon3"); System.out.println(user2);
结果
private java.lang.String com.bacon.reflect.User.name public java.lang.String com.bacon.reflect.User.getName() public com.bacon.reflect.User() user{name='null', id=0, age=0} user{name='bacon', id=1, age=25} user{name='bacon2', id=1, age=25} love user{name='bacon3', id=1, age=25}
不管private还是public,都会进行权限安全检测,而安全检测会降低程序执行效率,一般效率 new>反射(不安全检测)>反射(安全检测)
3.获取泛型信息
- 基本类型
- 引用类型
- 泛型:一般都是list,map集合
public class TestReflect { public void test01(Mapmap, List list){ System.out.println("test01"); } public Map test02(){ System.out.println("test02"); return null; } public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException { //获取泛型信息 Method test01 = TestReflect.class.getMethod("test01", Map.class, List.class); //得到泛型参数类型 Type[] genericParameterTypes = test01.getGenericParameterTypes(); for (Type genericParameterType : genericParameterTypes) { System.out.println("#"+genericParameterType); //如果泛型参数类型是参数化类型 if(genericParameterType instanceof ParameterizedType){ Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); } } } //获取泛型信息 Method test02 = TestReflect.class.getMethod("test02",null); //得到泛型返回类型 Type genericReturnType = test02.getGenericReturnType(); System.out.println(genericReturnType); if(genericReturnType instanceof ParameterizedType){ Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); } } } }
结果
#java.util.Mapclass java.lang.String class com.bacon.reflect.User #java.util.List class com.bacon.reflect.User java.util.Map class java.lang.String class com.bacon.reflect.User
4.反射操作注解
//反射操作注解 Annotation[] annotations = aClass1.getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation); } Table annotation = aClass1.getAnnotation(Table.class); System.out.println(annotation); String value = annotation.value(); System.out.println(value); Field name3 = aClass1.getDeclaredField("name"); Filed annotation1 = name3.getAnnotation(Filed.class); System.out.println(annotation1); String columnName = annotation1.columnName(); String type = annotation1.type(); System.out.println(columnName+" "+type);
结果
@com.bacon.reflect.Table(value=db_user) @com.bacon.reflect.Table(value=db_user) db_user @com.bacon.reflect.Filed(columnName=db_name, type=varchar) db_name varchar