这篇文章主要介绍“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();
}
}
}
反射机制的性能
是访问安全检查的开关。设置true表示反射的对象在使用时应该取消Java语言访问检查。
禁止安全检查可以提高反射的运行速度。
反射操作泛型(Generic)
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反射机制怎么实现”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注天达云行业资讯频道,小编每天都会为大家更新不同的知识点。