java反射机制

1.通过例子了解Java反射机制

 1 package java_reflect;
 2 
 3 public class Person {
 4     public String name;
 5     private int age;
 6     
 7 
 8     static{
 9         System.out.println("我是static的静态代码块!!");
10     }
11     public Person(){}
12     public Person(String name,int age){
13         this.name=name;
14         this.age=age;
15     }
16     private Person(String name){
17         this.name=name;
18     }
19     @Override
20     public String toString() {
21         return "Person [name=" + name + ", age=" + age + "]";
22     }
23     public void eat(){
24         System.out.println("人在吃饭!");
25     }
26     private void sleepPrivate(){
27         System.out.println("我正在睡觉!!!!!");
28     }
29     
30     public  boolean action(String name,int age){
31         
32         System.out.println("我是带有参数的方法,通过反射能执行!");
33         return true;
34     }
35     
36     private  void playGame(String name,int age){
37         System.out.println("人在打游戏:"+name+" "+age);
38     }
39     
40 }
View Code

 

 

 1 package java_reflect;
 2 /**
 3  * 获取一个类class文件对象的三种方式:
 4  * 1.类名字
 5  * 2.对象
 6  * 3.class类的静态方法获取
 7  * */
 8 public class ReflectDemo {
 9     
10     public static void main(String[] args) throws ClassNotFoundException {
11         //1.对象获取
12         Person p=new Person();
13         Class c=p.getClass();
14         System.out.println(c);
15         
16         //2.类名获取
17         //每一个类型,包括基本和引用,都会赋予这个类型一个静态的属性,属性名字class
18         Class c1= Person.class;
19         System.out.println(c1);
20         
21         //person这个类的class文件只有一个,虚拟机只会给这个文件创建一个唯一的Class类
22         //所以c1和p的内存地址都是相等的
23         System.out.println(c1==c);//true
24         System.out.println(c1.equals(c));//true
25         
26         //3.Class类的静态方法获取forname(字符串的类名)
27         Class c3=Class.forName("java_reflect.Person");
28         System.out.println(c3);
29         
30         //这三个方法拿到的对象都是唯一的一个对象
31     }
32 }
View Code

 

 

 1 package java_reflect;
 2 
 3 import java.lang.reflect.Constructor;
 4 
 5 /**
 6  * 通过反射获取class文件中的构造方法,运行构造方法
 7  * 运行构造方法,创建对象
 8  *         获取class文件对象
 9  *         从class文件对象中,获取需要的成员
10  * 
11  * Constructor 描述构造方法对象的类
12  * */
13 public class ReflectDemo2 {
14     
15     public static void main(String[] args) throws Exception, NoSuchMethodException {
16         Class c=Class.forName("java_reflect.Person");
17         //使用Class文件对象,获取类中的构造方法,找到类class,获取构造器
18         //getConstructors()获取class文件对象中的所有公共的构造方法
19         System.out.println("获得共有的所有的构造方法:");
20         Constructor[] cons= c.getConstructors();
21         for(Constructor con:cons){
22             System.out.println(con);
23             /**
24              * public java_reflect.Person()
25                 public java_reflect.Person(java.lang.String,int)
26              * */
27         System.out.println("获取指定的构造方法!");
28         //空参数的构造方法
29             System.out.println("空参数:");
30             Constructor conss= c.getConstructor();
31             System.out.println(conss);
32             //运行空参数的构造方法,newInstence
33             Object objPerson=conss.newInstance();
34             System.out.println(objPerson);
35             Object obj1=conss.newInstance();
36             System.out.println(obj1);
37         }
38     }
39 }
View Code

 

 1 package java_reflect;
 2 /**
 3  *关于反射和new:知识点
 4  *1.ram和rom 2.对内存和栈内存的区别,以及数据结构的方式,以及存储的到底是什么
 5  *3.new 和反射是2中不同的设计方式:关键字;动态开辟一个对象和直接开辟多个对象
 6  * 
 7  * */
 8 import java.lang.reflect.Constructor;
 9 
10 public class ReflectDemo3 {
11     
12     public static void main(String[] args) throws Exception {
13         Class c=Class.forName("java_reflect.Person");
14         //Class...parameterTypes基本数据类型的Class文件
15         //1.获取带有参数的构造函数的参数列表
16         Constructor con= c.getConstructor(String.class,int.class);
17         System.out.println(con);
18         //2.运行构造方法:initargs(实际参数)
19         Person p=(Person) con.newInstance("haha",35);
20         System.out.println(p);
21     }
22 }
View Code

 

 

 1 package java_reflect;
 2 /**
 3  * 反射获取构造方法并运行,有快捷的方式
 4  * 有前提:
 5  *         被反射的类,必须是有空参数构造方法
 6  *         构造方法的权限必须是public
 7  * */
 8 public class ReflectDemo4 {
 9     
10     public static void main(String[] args) throws Exception{
11         Class c=Class.forName("java_reflect.Person");
12         //Class类中定义了一个方法,newInstance()
13         
14         //注意这个Class类中的方法newInstance是不能传递参数的
15         //这样也使得构造方法必须是有一个空参数的构造方法
16         //所以我们在写类的时候如果用到反射,最好也是写上空参数构造器
17         Object obj=c.newInstance();
18         System.out.println(obj);
19     }
20 }
View Code

 

 

 1 package java_reflect;
 2 
 3 import java.lang.reflect.Constructor;
 4 
 5 /**
 6  * 反射获取私有的构造方法运行
 7  *     不推荐,破坏了程序的封装性
 8  * 
 9  * 我们可以使用暴力反射,强行打破Java中的类在运行时的权限
10  * */
11 public class ReflectDemo6 {
12     
13     public static void main(String[] args) throws Exception {
14         Class c=Class.forName("java_reflect.Person");
15         //获得私有的构造器getDeclaredConstructors() 
16         Constructor [] cons=c.getDeclaredConstructors();
17         for(Constructor con:cons){
18             System.out.println(con);
19         }
20         System.out.println("私有的指定的一个私有构造器!");
21         Constructor conPrivate=c.getDeclaredConstructor(String.class);
22         System.out.println(conPrivate);
23 //        Person p2=(Person)conPrivate.newInstance("李泽博!");
24         //错误,main中无法访问私有的构造器
25         
26         //1.使用暴力反射
27         /**
28          * AccessibleObject 类是 Field、Method 和 Constructor 对象的基类。它提供了将反射的对象标记为在使用时取消默认 Java 语言访问控制检查的能力。
29          * 对于公共成员、默认(打包)访问成员、受保护成员和私有成员,
30          * 在分别使用 Field、Method 或 Constructor 
31          * 对象来设置或获取字段、调用方法,或者创建和初始化类的新实例的时候,
32          * 会执行访问检查。
33          * */
34         Constructor con=c.getDeclaredConstructor(String.class);
35         con.setAccessible(true);
36         //运行私有的构造器!! 
37         con.newInstance("李泽博!!!!!!!!!");
38     }
39 }
View Code

 

 

 1 package java_reflect;
 2 
 3 import java.lang.reflect.Field;
 4 
 5 public class ReflectDemo7 {
 6 
 7         public static void main(String[] args) throws Exception{
 8             Class  c=Class.forName("java_reflect.Person");
 9             Object obj=c.newInstance();
10             //获取成员变量的Clas变量的方法getField class文件中所有公共的成员变量
11             //返回值是Field[] Fiel类描述成员变量对象的类
12             
13             //拿的是公有的成员变量
14             System.out.println("拿的是私有的成员变量");
15             Field[] fields= c.getFields();
16             for(Field field:fields){
17                 System.out.println(field);
18             }
19             //私有的,公有的一起,也即是声明了的变量
20             System.out.println("私有的 :");
21             Field [] fiels1=c.getDeclaredFields();
22             for(Field fiels:fiels1){
23                 System.out.println(fiels);
24             }
25             //获取指定的一个成员变量
26             System.out.println("获取指定的一个成员变量");
27             Field fieldss=c.getField("name");
28             System.out.println(fieldss);
29             
30             System.out.println("改掉变量值为'王五'");
31             fieldss.set(obj, "王五!!");
32             
33             System.out.println(obj);
34             //这里如果我们不是用obj,上面创建的对象,那么使用c.newInstance()会使得
35             //你创建了2个对象,使得结果是null,0
36         }
37 }
View Code

 

 

 1 package java_reflect;
 2 
 3 import java.lang.reflect.Method;
 4 
 5 public class ReflectDemo8 {
 6 
 7     public static void main(String[] args) throws Exception {
 8         Class c=Class.forName("java_reflect.Person");
 9         Object obj=c.newInstance();
10         //获取到成员方法
11         //Method []getMethods()获取的是Class文件的所有公共的成员方法,包括继承的
12         //Method是描述成员方法的对象类
13         System.out.println("成员方法:");
14         Method [] methods= c.getMethods();
15         for(Method method:methods){
16             System.out.println(method);
17         }
18         System.out.println("利用反射使用method:");
19         Method method= c.getMethod("eat");
20         System.out.println(method);
21         method.invoke(obj);
22     }
23 }
View Code

 

 1 package java_reflect;
 2 
 3 import java.lang.reflect.Constructor;
 4 import java.lang.reflect.Method;
 5 
 6 public class ReflectDemo9 {
 7     
 8     public static void main(String[] args) throws Exception {
 9         Class c=Class.forName("java_reflect.Person");
10         Object obj=c.newInstance();
11         
12         Method method= c.getMethod("action", String.class,int.class);
13         boolean  bool=(Boolean) method.invoke(obj,"李泽博",23);
14         System.out.println(bool);
15         //通过反射获取私有的带参数的方法
16         System.out.println("通过反射获取私有的带参数的方法");
17         Object obj1=c.newInstance();
18         Method method1=c.getDeclaredMethod("playGame", String.class,int.class);
19         //在使用反射式,取消Java中权限
20         method1.setAccessible(true);
21         method1.invoke((Person)obj1, "李泽博sdf",23);
22         
23     }
24 }
View Code

 

反射进行的泛型擦除:

 1 package java_reflect;
 2 
 3 import java.lang.reflect.Method;
 4 import java.util.ArrayList;
 5 
 6 /**
 7  * 定义集合类,泛型String
 8  * 要求向集合中添加Integer类型
 9  * 
10  * 反射方式,获取 出集合ArrayList类的class文件对象
11  * 通过class文件都对象,通过调用add()方法
12  * 
13  *为什么可以使用这种方式:因为在编译器中是没有泛型这种类型的,所以在.class文件对象中可以使用这种方式
14  * */
15 public class ReflectDemo10 {
16     
17     public static void main(String[] args) throws Exception{
18         ArrayList<String> array=new ArrayList<String>();
19         array.add("例子莪");
20         //反射方式进行泛型擦除,在ArrayList源码中其实是一个对象数组,所以可以进行储存各种类型,
21         //但是通过泛型又有了约束
22         Class c=Class.forName("java.util.ArrayList");
23         Method method= c.getMethod("add",Object.class);
24         System.out.println(method);
25         System.out.println("使用反射技术~运行方法");
26         
27         //Object obj=c.newInstance();
28         method.invoke(array, 1500);
29         method.invoke(array, 200);
30         System.out.println(array);
31     }
32 }
View Code

 

 

使用反射可以让代码变得很灵活,比如读取配置文件,只需要修改配置文件的键值对就可以让程序运行不同的类和方法

1 package java_reflect_two;
2 
3 public class Person {
4         
5     public void eat(){
6         System.out.println("人在吃饭~");
7     }
8 }
View Code
1 package java_reflect_two;
2 
3 public class Student {
4     
5     public void study(){
6         System.out.println("学生在学习!");
7     }
8 }
View Code
1 package java_reflect_two;
2 
3 public class Worker {
4     
5     public void job(){
6         System.out.println("上班族在工作!");
7     }
8 }
View Code
1 #className=java_reflect_two.Person
2 #methodName=eat
3 
4 #className=java_reflect_two.Student
5 #methodName=study
6 
7 className=java_reflect_two.Worker
8 methodName=job
View Code
 1 package java_reflect_two;
 2 
 3 import java.io.FileReader;
 4 import java.lang.reflect.Method;
 5 import java.util.Properties;
 6 
 7 /**
 8  * 调用Person方法,调用Student,调用Worker中的方法,也就是说
 9  * 运行哪个类是不确定的,类不清楚,方法也不清楚。
10  * 
11  * 通过配置文件实现此功能,以键值对的形式,写在文本中
12  *     运行那个类,读取配置文集那即可
13  *     实现步骤:
14  *             1.准备配置文件,键值对
15  *             2.IO流读取配置文件 Reader
16  *             3.文件中的价值对存储到集合中:Properties
17  *             4.直接用反射获取指定类的,class文件的对象
18  *             5.获取方法,执行方法
19  */
20 public class Test {
21     
22     public static void main(String args[]) throws Exception{
23     
24         //IO读取配置文件
25         FileReader r=new FileReader("config.properties");
26         //创建集合对象
27         Properties pro=new Properties();
28         pro.load(r);
29         r.close();
30         //通过键获取值
31         
32         String className=pro.getProperty("className");
33         String methodName=pro.getProperty("methodName");
34         //测试:System.out.println(className+": "+methodName);
35         
36         Class c=Class.forName(className);
37         Object obj=c.newInstance();
38         Method method=c.getMethod(methodName);
39         method.invoke(obj);
40     }
41 }
View Code

 

posted @ 2017-12-02 23:23  物是人非12758  阅读(159)  评论(0编辑  收藏  举报