1 动态语言:
1 Java语言动态性:
2 Java反射机制:
3 Java反射机制应用场景:
4 反射实例代码:
1 bean
public class User {
private int id;
private int age;
private String uname;
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;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public void setUname() {
this.uname = "zm";
}
private void test(){
System.out.println("hadoop5");
}
public User(int id, int age, String uname) {
super();
this.id = id;
this.age = age;
this.uname = uname;
}
//javabean必须要有无参的构造方法! 以方便反射下 User u = clazz.newInstance();
public User() {
}
}
2 反射代码
public static void main(String[] args) {
String path = "com.test.bean.User";
try {
Class<User> clazz = (Class<User>) Class.forName(path);
//通过反射API调用构造方法,构造对象
User u = clazz.newInstance(); //其实是调用了User的无参构造方法
System.out.println(u);
Constructor<User> c = clazz.getDeclaredConstructor(int.class,int.class,String.class);
User u2 = c.newInstance(1001,18,"zm二");
System.out.println(u2);
System.out.println(u2.getUname()); // 通过反射创建实例对象后 可以直接调用对象里的Public方法
//通过反射API调用普通方法
User u3 = clazz.newInstance();
Method method = clazz.getDeclaredMethod("setUname", String.class);// 别人给我传什么方法名 我就调用这个方法 实现动态调用方法
method.invoke(u3, "zm三"); //u3.setUname("zm三");
System.out.println(u3.getUname()); // zm三
//通过反射API操作属性
User u4 = clazz.newInstance();
Field f = clazz.getDeclaredField("uname");
f.setAccessible(true); //这个属性不需要做安全检查了,可以直接访问
f.set(u4, "zm四"); //通过反射直接写属性
System.out.println(u4.getUname()); //通过反射直接读属性的值
System.out.println(f.get(u4));
} catch (Exception e) {
e.printStackTrace();
}
}
5 反射带来的效率下降问题:
反射机制下回导致性能低下, 如果必须使用反射,可以建议 将 setAccessible设置为true,
表示反射的对象在使用时取消Java语言访问检查,
通常,
不使用反射代码效率 = [20,30]*使用反射(setAccessible为false)
使用反射(setAccessible为false)效率 = 4*使用反射(setAccessible为true)
代码测试如下:
/**
* 通过跳过安全检查,提高反射效率
* 三种执行方法的效率差异比较
*
* 结果:
* 普通方法调用,执行10亿次,耗时:4549ms
反射动态方法调用,执行10亿次,耗时:88568ms
反射动态方法调用,跳过安全检查,执行10亿次,耗时:22170ms
*
*/
public class Demo06 {
public static void test01(){
User u = new User();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000L; i++) {
u.getUname();
}
long endTime = System.currentTimeMillis();
System.out.println("普通方法调用,执行10亿次,耗时:"+(endTime-startTime)+"ms");
}
public static void test02() throws Exception{
User u = new User();
Class clazz = u.getClass();
Method m = clazz.getDeclaredMethod("getUname", null);
// m.setAccessible(true);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000L; i++) {
m.invoke(u, null);
}
long endTime = System.currentTimeMillis();
System.out.println("反射动态方法调用,执行10亿次,耗时:"+(endTime-startTime)+"ms");
}
public static void test03() throws Exception{
User u = new User();
Class clazz = u.getClass();
Method m = clazz.getDeclaredMethod("getUname", null);
m.setAccessible(true); //不需要执行访问安全检查
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000L; i++) {
m.invoke(u, null);
}
long endTime = System.currentTimeMillis();
System.out.println("反射动态方法调用,跳过安全检查,执行10亿次,耗时:"+(endTime-startTime)+"ms");
}
public static void main(String[] args) throws Exception {
test01();
test02();
test03();
}
}
6 反射得到方法参数泛型类型和返回值泛型类型
/**
* 通过反射获取泛型信息
*
#java.util.Map<java.lang.String, com.bjsxt.test.bean.User>
泛型类型:class java.lang.String
泛型类型:class com.bjsxt.test.bean.User
#java.util.List<com.bjsxt.test.bean.User>
泛型类型:class com.bjsxt.test.bean.User
返回值,泛型类型:class java.lang.Integer
返回值,泛型类型:class com.bjsxt.test.bean.User
*
*/
public class Demo04 {
public void test01(Map<String,User> map,List<User> list){
System.out.println("Demo04.test01()");
}
public Map<Integer,User> test02(){
System.out.println("Demo04.test02()");
return null;
}
public static void main(String[] args) {
try {
//获得指定方法参数泛型信息
Method m = Demo04.class.getMethod("test01", Map.class,List.class);
Type[] t = m.getGenericParameterTypes();
for (Type paramType : t) {
System.out.println("#"+paramType);
if(paramType instanceof ParameterizedType){
Type[] genericTypes = ((ParameterizedType) paramType).getActualTypeArguments();
for (Type genericType : genericTypes) {
System.out.println("泛型类型:"+genericType);
}
}
}
//获得指定方法返回值泛型信息
Method m2 = Demo04.class.getMethod("test02", null);
Type returnType = m2.getGenericReturnType();
if(returnType instanceof ParameterizedType){
Type[] genericTypes = ((ParameterizedType) returnType).getActualTypeArguments();
for (Type genericType : genericTypes) {
System.out.println("返回值,泛型类型:"+genericType);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
7 反射操作注解 ----> 见 注解定义使用---orm映射注解使用简单介绍
8 反射main函数要注意的事:
Method m = c.getMethod("main",String[].class);
m.invoke(null, (Object)new String[]{});
//由于可变参数是JDK5.0之后才有。 如果在反射main函数时不加上 (Object)强转成一个参数的话 会编译成:m.invoke(null,"aa","bb"),就发生了参数个数不匹配的问题。
//m.invoke(null, (Object)new String[]{}); OK
//因此,必须要加上(Object)转型,避免这个问题。
//public static void main(String[] args)