java 反射
1.获取类基本信息
String path = "com.been.Reflect";
Class clazz1 = Class.forName(path);
Class clazz2 = Class.forName(path);
//Class 虚拟机把类加载到内存,Class是一种类型
System.err.println(clazz1.hashCode() == clazz2.hashCode());
//获取类信息
System.err.println("完全限定类名:"+clazz1.getName());
System.err.println("类名:"+clazz1.getSimpleName());
结果:
true
完全限定类名:com.been.Reflect
类名:Reflect
2.获取属性(字段)基本信息
//获取属性字段
//getField | getFields 只能获取访问方式为public的属性
System.err.println("获取public声明的属性"+clazz1.getFields().length);
System.err.println("获取public声明的属性"+clazz1.getField("phone"));
//getDeclaredFields | getDeclaredField 可以获取所有属性 不区分权限
System.err.println("获取所有属性:"+clazz1.getDeclaredFields().length);
System.err.println("获取所有属性:"+clazz1.getDeclaredField("name"));
for (Field field :clazz1.getDeclaredFields()){
System.err.println("属性:"+field);
}
结果:
获取public声明的属性2
获取public声明的属性public java.lang.String com.been.Reflect.phone
获取所有属性:4
获取所有属性:private java.lang.String com.been.Reflect.name
属性:private java.lang.String com.been.Reflect.name
属性:private java.lang.Integer com.been.Reflect.age
属性:public java.lang.String com.been.Reflect.phone
属性:public java.util.Map com.been.Reflect.map
3.获取方法基本信息
//获取方法的信息
Method[] methods = clazz1.getDeclaredMethods();
for (Method m : methods){
System.err.println("方法:"+m+"--参数类型:"+ Arrays.toString(m.getParameterTypes()));
}
//第二个参数 是方法的参数类型,是一个可变参数
System.err.println(clazz1.getDeclaredMethod("setAge",Integer.class));
结果:
方法:public java.lang.String com.been.Reflect.getName()--参数类型:[]
方法:public void com.been.Reflect.setName(java.lang.String)--参数类型:[class java.lang.String]
方法:public void com.been.Reflect.setAge(java.lang.Integer)--参数类型:[class java.lang.Integer]
方法:public java.lang.Integer com.been.Reflect.getAge()--参数类型:[]
public void com.been.Reflect.setAge(java.lang.Integer)
4.获取构造函数基本信息
//获取构造器
System.err.println("构造器:"+Arrays.toString(clazz1.getDeclaredConstructors()));
System.err.println("构造器:"+clazz1.getDeclaredConstructor(String.class,Integer.class));
结果:
构造器:[public com.been.Reflect(), public com.been.Reflect(java.lang.String,java.lang.Integer)]
构造器:public com.been.Reflect(java.lang.String,java.lang.Integer)
5.反射创建对象
//动态创建对象
//无参创建对象
Reflect reflect = (Reflect) clazz1.newInstance();
//使用有参构造器创建对象
Constructor c = clazz1.getDeclaredConstructor(String.class,Integer.class);
Reflect reflect1 = c.newInstance("小米",12);
System.err.println("reflect"+reflect+" reflect1"+reflect1);
结果:
reflectcom.been.Reflect@6822ed4b reflect1com.been.Reflect@4d090c56
6.通过反射调用方法
//通过反射调用方法
Method method = clazz1.getMethod("setName", String.class);
method.invoke(reflect1,"qwertyu");
System.err.println("reflect1 getName"+reflect1.getName());
结果:
reflect1 getNameqwertyu
7.通过反射操作属性
//通过反射操作属性
Field f = clazz1.getDeclaredField("name");
//java.lang.IllegalAccessException: Class com.reflect.BaseReflect can not access a member of class com.been.Reflect with modifiers "private"
f.setAccessible(true); // 不需要安全检查 可以直接访问 同时设置为true 能提高反射的效率
f.set(reflect1,"ppqqcc");
System.err.println("reflect1 setPropt name"+reflect1.getName());
System.err.println("reflect1 setPropt name"+f.get(reflect1)); //通过反射获取属性值
结果:
reflect1 setPropt nameppqqcc
reflect1 setPropt nameppqqcc
8.通过反射获取泛型类型
//获取泛型类型 方法中带有 Generic 则与获取泛型有关
Field field = clazz1.getField("map");
System.err.println("获取属性类型:"+field.getType().getName());
//获取反射类型 <String,Array> ParameterizedType 反射类型实体类
Type type = field.getGenericType();
//判断
if(type instanceof ParameterizedType){
Type[] types = ((ParameterizedType)type).getActualTypeArguments();
for (Type t:types) {
System.err.println("泛型类型:"+t);
}
}
结果:
java.util.Map
泛型类型:class java.lang.String
泛型类型:interface java.sql.Array
总结:带Declared的都是访问所有的,如 getDeclaredField,带
Generic的与泛型有关。ParameterizedType 是一个字段是否带有泛型的类型。
f.setAccessible(true):操作私有属性要关闭安全检查,关闭安全检查会提升反射的速度。