java反射机制怎么实现
这篇文章主要介绍“java反射机制怎么实现”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“java反射机制怎么实现”文章能帮助大家解决问题。
1.获取Class对象的三种方式
1. 通过对象的getClass()方法 Class c1=(new User()).getClass(); 2. 通过字节码文件获取 Class c2=User.class; 3. 通过Class类的静态方法获取 Class c3=Class.forName("com.bee.entity.User");
同一个类只会被加载一次
public class Test { public static void main(String[] args) { String path = "demo6.TestBean"; try { Class<?> clazz1 = Class.forName(path); System.out.println(clazz1.hashCode()); Class<?> class2 = Class.forName(path); System.out.println(class2.hashCode()); } catch (Exception e) { e.printStackTrace(); } } }
输出
366712642 366712642
Class对象专门用来存放类的信息。一个类只对应一个Class对象。因为,类的对象虽然可以有多个,但对应的类只有一个。
利用反射获取类的信息
先定义一个类TestBean
public class TestBean { private String name; private int age; public TestBean() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public TestBean(String name, int age) { super(); this.name = name; this.age = age; } }
读取上述类TestBean的信息
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class Test { public static void main(String[] args) { String path = "demo.TestBean"; try { Class<?> clazz = Class.forName(path); // 获取类的名字 System.out.println(clazz.getName()); // 获得包全路径名 System.out.println(clazz.getSimpleName()); // 只获得类名 // 获取属性信息 Field[] fields1 = clazz.getFields(); // 只能获取public属性 Field[] fields2 = clazz.getDeclaredFields(); // 可以获得private属性(可以获得所有的属性) Field field3 = clazz.getDeclaredField("name"); for (Field field : fields2) { System.out.println("属性:" + field); } // 获取方法信息 // clazz.getMethod(name, parameterTypes) 只能获得public方法 Method[] methods = clazz.getDeclaredMethods(); Method method1 = clazz.getDeclaredMethod("getName", null); // 如果方法有参数,必须传递参数类型对应的Class对象。 Method method2 = clazz.getDeclaredMethod("setName", String.class); for (Method method : methods) { System.out.println("方法:" + method); } // 获得构造器信息 // Constructor[] constructors=clazz.getConstructors() 只能获得public构造方法 Constructor[] constructors = clazz.getDeclaredConstructors(); for (Constructor constructor : constructors) { System.out.println("构造器:" + constructor); } // 获取无参构造器 Constructor cons1 = clazz.getDeclaredConstructor(null); System.out.println("无参构造器:" + cons1); // 获取有参构造器 Constructor cons2 = clazz.getDeclaredConstructor(String.class, int.class); System.out.println("有参构造器:" + cons2); } catch (Exception e) { e.printStackTrace(); } } }
通过反射动态操作构造器,方法,属性
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class Test { public static void main(String[] args) { String path = "demo.TestBean"; try { Class<TestBean> clazz = (Class<TestBean>) Class.forName(path); // 通过反射构造对象 TestBean tb = clazz.newInstance(); // 调用TestBean的无参构造方法 // 对于JavaBean/POJO/DTO必须要配置一个无参构造器,以便框架使用newInstance()构建对象实例。 System.out.println(tb); // 调用有参构造器 Constructor<TestBean> cons1 = clazz.getDeclaredConstructor(String.class, int.class); TestBean tb1 = cons1.newInstance("黄忠", 83); System.out.println(tb1.getName() + tb1.getAge() + "岁"); // 通过反射调用普通方法 TestBean tb2 = clazz.newInstance(); tb2.setName("云长"); // 等效于下边的invoke()方法 tb2.setAge(57); // 等效于下边的invoke()方法 TestBean tb3 = clazz.newInstance(); Method method1 = clazz.getDeclaredMethod("setName", String.class); Method method2 = clazz.getDeclaredMethod("setAge", int.class); method1.invoke(tb3, "玄德"); method2.invoke(tb3, 66); System.out.println(tb3.getName() + tb3.getAge() + "岁"); // 通过反射操作属性 TestBean tb4 = clazz.newInstance(); Field f1 = clazz.getDeclaredField("name"); Field f2 = clazz.getDeclaredField("age"); // 报错不能访问私有属性的解决方法(属性可以设置,方法也可以这样设置) f1.setAccessible(true); f2.setAccessible(true); f1.set(tb4, "紫龙"); f2.set(tb4, 33); System.out.println(tb4.getName() + f2.get(tb4) + "岁"); } catch (Exception e) { e.printStackTrace(); } } }
反射机制的性能
setAccessible
是访问安全检查的开关。设置true表示反射的对象在使用时应该取消Java语言访问检查。
禁止安全检查可以提高反射的运行速度。
可以考虑使用cglib/javaassist字节码操作提升反射操作的速度。
反射操作泛型(Generic)
Java使用泛型擦除机制来引入泛型。Java中的泛型仅仅是给编译器javac使用的。泛型用于确保数据的安全性和免去强制类型转换带来的不便。Java一旦编译完成,所有和泛型有关的类型将全部擦除。
Java新增了ParameterizedType,GenericArrayType,TypeVariable和WildcardType几种类型来代表不能被归一到Class类中的类型,但又和原始类型保持一致。
ParameterizedType:表示一种参数化的类型,比如:Collection
GenericArrayType:表示一种元素类型是参数化类型或者类型变量的数组类型
TypeVariable:是各种类型变量的公共父接口
WildcardType:代表一种通配符类型表达式,比如:?,? extends Number,? super Integer。
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 Test { public void test1(Map<String, TestBean> map, List<TestBean> list) { System.out.println("Test.test1()"); } public Map<Integer, TestBean> test2() { System.out.println("Test.test2()"); return null; } public static void main(String[] args) { try { // 获得指定方法参数泛型信息 Method m = Test.class.getMethod("test1", Map.class, List.class); Type[] t = m.getGenericParameterTypes(); for (Type type : t) { System.out.println("#" + type); if (type instanceof ParameterizedType) { Type[] genericTypes = ((ParameterizedType) type).getActualTypeArguments(); for (Type genericType : genericTypes) { System.out.println("泛型类型:" + genericType); } } } System.out.println("-------------------"); // 获得指定方法返回值泛型信息 Method m2 = Test.class.getMethod("test2", null); Type returnType = m2.getGenericReturnType(); System.out.println("#" + returnType); if (returnType instanceof ParameterizedType) { Type[] genericTypes = ((ParameterizedType) returnType).getActualTypeArguments(); for (Type type : genericTypes) { System.out.println("返回值泛型类型:" + type); } } } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } } }
关于“java反射机制怎么实现”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注蜗牛博客行业资讯频道,小编每天都会为大家更新不同的知识点。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:niceseo99@gmail.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
评论