Java反射学习笔记

反射机制:指的是可以在运行时加载,使用编译期间完全未知的类,

程序在于行状态中,可以动态的加载一个只有名称的类,对于任意一个已加载的类,都能够通过反射知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性

如何理解Class对象:在Java中万事万物皆对象,我们都知道类是对象的模板,通过类我们可以创建该类的实例。

那么我们有没有想过类又是谁的实例对象呢?答案是类Class的对象,我们可以这样理解,There have a class named Class,类也是对象。

创建Class的三种方式:例如

  1 Class c = Class.forName("com.xvl.test.student"); 

  2 对象.getClass();

  3 类名.class;

  eg:  Student student = new Student();   //假如这个类在com.xvl.test包里面

  1 Class c = Class.forName("com.xvl.test.student");     //c就是Student类的类类型,也是Class类的实例对象

  2 Class c1 = Student.class;

  3 Class c2 = student.getClass();

  注意:c == c1 == c2

加载完类之后,在堆内存中就产生了一个Class对象(注意:一个类只有一个Class对象)这个对象就包含了完整类的信息结构,就像是一面镜子所以称之为反射。

反射Demo1:

 

 1 package cn.xvl.reflection;
 2 
 3 public class person {
 4     public int id;
 5     private String name;
 6     private int number;
 7     
 8     public person(int id, String name, int number) {
 9         super();
10         this.id = id;
11         this.name = name;
12         this.number = number;
13     }
14     
15     public person() {
16     }
17     
18     public int getId() {
19         return id;
20     }
21     public String getName() {
22         return name;
23     }
24     public int getNumber() {
25         return number;
26     }
27     public void setId(int id) {
28         this.id = id;
29     }
30     public void setName(String name) {
31         this.name = name;
32     }
33     public void setNumber(int number) {
34         this.number = number;
35     }
36     
37 }

 

运用反射操作Person类

 1 package cn.xvl.reflection;
 2 
 3 import java.lang.reflect.Constructor;
 4 import java.lang.reflect.Field;
 5 import java.lang.reflect.InvocationTargetException;
 6 import java.lang.reflect.Method;
 7 
 8 /**
 9  * 通过反射api动态操作:构造器 属性 方法
10  * @author 1
11  *
12  */
13 public class demo03 {
14     public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException {
15         //通过反射创建新对象
16         Class<person> c = (Class<person>) Class.forName("cn.xvl.reflection.person");
17         person p1 =c.newInstance();    //此处调用了person的无参数构造方法 javabean必须有无参构造
18         p1.setId(20);
19         System.out.println(p1.getId());
20         //获取有参构造
21         Constructor<person> con = c.getDeclaredConstructor(int.class,String.class,int.class);
22         //使用有参构造创建对象
23         person p2 =con.newInstance(18,"张三",1);
24         System.out.println(p2.getId()+"-->"+p2.getName()+"-->"+p2.getNumber());
25         
26         
27         //通过反射调用普通方法
28         person p3 =(person)c.newInstance();
29         Method m = c.getDeclaredMethod("setName", String.class);  //有几个参数就传几个因为是可变参数...
30         m.invoke(p1, "张三");  //就相当于p1.setName;  原有方法返回值类型是void则返回null
31         System.out.println(p1.getName());
32         
33         
34         //通过反射操作属性    不能直接操作私有属性  但是可以设置安全检查操作私有属性
35         Field f = c.getDeclaredField("id");
36         f.setAccessible(true);//设置安全检查 意思是这个私有属性不需要做安全检查,可以直接访问
37         f.set(p1, 17); //通过反射直接写属性
38         System.out.println(f.get(p1));//通过反射直接读取属性
39         System.out.println(p1.getId()+"-->"+p1.getName());
40     }
41 }

反射demo2  获取一个类的信息(方法 属性)

 1 package cn.xvl.reflection1;
 2 
 3 import java.lang.reflect.Field;
 4 import java.lang.reflect.Method;
 5 
 6 public class ClassUtil {
 7 
 8     //获取类的全部信息 包括类的成员函数成员变量
 9     public static void  getClassMessage(Object object) {
10         //获取类的类类型
11         Class class1 = object.getClass();
12         //获取类的名称
13         System.out.println("类名:"+class1.getName());
14         //获取类的方法
15         /*
16          * 一个成员方法就是一个method对象
17          * getMethods()   获取的是所有的public函数 包括父类继承而来的方法
18          * getDeclaredMethods() 获取的是所有该类自己声明的方法 包括private方法 不包含父类继承而来的方法
19          */
20         Method[] method = class1.getMethods();
21         for (int i = 0; i < method.length; i++) {
22             //得到方法返回值的*类类型*、
23             Class rt = method[i].getReturnType();
24             System.out.print(rt.getName()+" ");
25             //得到方法的名称
26             System.out.print(method[i].getName()+"(");
27             //获取参数类型 ---->得到的是参数列表的类类型  如果参数是int string  那么得到的是int.class  string.class并将其放在参数数组中
28             Class[] param = method[i].getParameterTypes();
29             for (Class class2 : param) {
30                 System.out.print(class2.getName()+",");
31             }
32             System.out.println(")");
33         }
34         
35         /*
36          * 成员变量也是对象
37          * java.lang.reflect.Field封装了关于成员变量的操作
38          * getFields()获取的是所有的public的成员变量  **注意是public变量 不能获取私有的变量
39          * getDeclaredFields()获取的是所有该类自己声明的成员变量包括private变量
40          */
41         
42         Field[] fields = class1.getFields();
43         for (Field field : fields) {
44             //得到成员变量类型的类类型
45             Class ty = field.getType();
46             //得到成员变量类型的名字
47             String tyName= ty.getName();
48             //得到成员变量的名字
49             String fieldName = field.getName();
50             System.out.println("typename"+"-->"+fieldName);
51         }
52     }
53 }
1 package cn.xvl.reflection1;
2 
3 public class test {
4     public static void main(String[] args) {
5         String string = "张三";
6         ClassUtil.getClassMessage(string);
7     }
8 }

测试结果:

类名:java.lang.String
boolean equals(java.lang.Object,)
java.lang.String toString()
int hashCode()
int compareTo(java.lang.String,)
int compareTo(java.lang.Object,)
int indexOf(java.lang.String,int,)
int indexOf(java.lang.String,)
int indexOf(int,int,)
int indexOf(int,)
java.lang.String valueOf(int,)
java.lang.String valueOf(long,)
java.lang.String valueOf(float,)
java.lang.String valueOf(boolean,)
java.lang.String valueOf([C,)
java.lang.String valueOf([C,int,int,)
java.lang.String valueOf(java.lang.Object,)
java.lang.String valueOf(char,)
java.lang.String valueOf(double,)
char charAt(int,)
int codePointAt(int,)
int codePointBefore(int,)
int codePointCount(int,int,)
int compareToIgnoreCase(java.lang.String,)
java.lang.String concat(java.lang.String,)
boolean contains(java.lang.CharSequence,)
boolean contentEquals(java.lang.CharSequence,)
boolean contentEquals(java.lang.StringBuffer,)
java.lang.String copyValueOf([C,)
java.lang.String copyValueOf([C,int,int,)
boolean endsWith(java.lang.String,)
boolean equalsIgnoreCase(java.lang.String,)
java.lang.String format(java.util.Locale,java.lang.String,[Ljava.lang.Object;,)
java.lang.String format(java.lang.String,[Ljava.lang.Object;,)
void getBytes(int,int,[B,int,)
[B getBytes(java.nio.charset.Charset,)
[B getBytes(java.lang.String,)
[B getBytes()
void getChars(int,int,[C,int,)
java.lang.String intern()
boolean isEmpty()
java.lang.String join(java.lang.CharSequence,[Ljava.lang.CharSequence;,)
java.lang.String join(java.lang.CharSequence,java.lang.Iterable,)
int lastIndexOf(int,)
int lastIndexOf(java.lang.String,)
int lastIndexOf(java.lang.String,int,)
int lastIndexOf(int,int,)
int length()
boolean matches(java.lang.String,)
int offsetByCodePoints(int,int,)
boolean regionMatches(int,java.lang.String,int,int,)
boolean regionMatches(boolean,int,java.lang.String,int,int,)
java.lang.String replace(char,char,)
java.lang.String replace(java.lang.CharSequence,java.lang.CharSequence,)
java.lang.String replaceAll(java.lang.String,java.lang.String,)
java.lang.String replaceFirst(java.lang.String,java.lang.String,)
[Ljava.lang.String; split(java.lang.String,)
[Ljava.lang.String; split(java.lang.String,int,)
boolean startsWith(java.lang.String,int,)
boolean startsWith(java.lang.String,)
java.lang.CharSequence subSequence(int,int,)
java.lang.String substring(int,)
java.lang.String substring(int,int,)
[C toCharArray()
java.lang.String toLowerCase(java.util.Locale,)
java.lang.String toLowerCase()
java.lang.String toUpperCase()
java.lang.String toUpperCase(java.util.Locale,)
java.lang.String trim()
void wait()
void wait(long,int,)
void wait(long,)
java.lang.Class getClass()
void notify()
void notifyAll()
java.util.stream.IntStream chars()
java.util.stream.IntStream codePoints()
typename-->CASE_INSENSITIVE_ORDER

注意:

setAccessible():启用和禁用访问安全检查的开关,置为true表示反射的对象在使用时应该取消Java语言访问检查,值为false表示应该实施Java语言访问检查,禁止安全检查,可以提高反射运行速度。

demo3  反射与普通方法对比

 1 package cn.xvl.reflection;
 2 
 3 import java.lang.reflect.InvocationTargetException;
 4 import java.lang.reflect.Method;
 5 
 6 /*
 7  * 反射性能对比
 8  * 反射会降低性能
 9  */
10 public class demo04 {
11     public static void test01(){
12         person p = new person();
13         long starttime = System.currentTimeMillis();
14         for (int i = 0; i < 1000000000 ; i++) {
15             p.setId(20);
16         }
17         long endtime = System.currentTimeMillis();
18         System.out.println("普通方法耗时"+(endtime-starttime));
19     }
20     public static void test02() throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException{
21         Class clazz = (Class<person>) Class.forName("cn.xvl.reflection.person");
22         Method m = clazz.getDeclaredMethod("setId", int.class);
23         person p =(person) clazz.newInstance();
24         long starttime = System.currentTimeMillis();
25         for (int i = 0; i < 1000000000; i++) {
26             m.invoke(p, 20);
27         }
28         long endtime = System.currentTimeMillis();
29         System.out.println("反射耗时"+(endtime-starttime));
30     }
31     public static void test03() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
32         Class clazz = (Class<person>) Class.forName("cn.xvl.reflection.person");
33         Method m = clazz.getDeclaredMethod("setId", int.class);
34         person p =(person) clazz.newInstance();
35         m.setAccessible(true);
36         long starttime = System.currentTimeMillis();
37         for (int i = 0; i < 1000000000; i++) {
38             m.invoke(p, 20);
39         }
40         long endtime = System.currentTimeMillis();
41         System.out.println("反射不进行安全检查耗时"+(endtime-starttime));
42     }
43     public static void main(String[] args) {
44         test01();
45         try {
46             test02();
47         } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalAccessException
48                 | IllegalArgumentException | InvocationTargetException | InstantiationException e) {
49             // TODO Auto-generated catch block
50             e.printStackTrace();
51         }
52         try {
53             test03();
54         } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException
55                 | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
56             // TODO Auto-generated catch block
57             e.printStackTrace();
58         }
59     }
60 }

测试结果:

普通方法耗时26ms
反射耗时1872ms
反射不进行安全检查耗时1238ms

 

posted @ 2017-11-01 17:44  花l信风  阅读(238)  评论(0编辑  收藏  举报