• 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
  • 相关阅读:
    面试(转)
    Expression Blend实战开发技巧
    Twelve Principles of Agile Software
    Test Software Engineer
    Web开发工程师必读的15个设计博客
    麻省理工的C/C++的课程
    Orchard:处理1对多的关系
    DotNetNuke Switches to C# !!
    我的那个他
    2011 微软MVP全球大会
  • 原文地址:https://www.cnblogs.com/lizeboLB/p/7956390.html
Copyright © 2020-2023  润新知