类加载机制和反射

jdk:包含javac编译器,以及一些开发java的小工具  

jre: jvm+基本库

jvm:类加载器(讲javac编译后的.class文件以二进制读入内存) 

java文件通过编译器变成了.class文件,接下来类加载器又将这些.class文件加载到JVM内存中。并为之生成对应的Class对象,直接使用java.exe命令来运行某个主类,其中类装载器的作用其实就是类的加载

//=========================================================================

JAVA反射机制是在运行状态,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制.

## 要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象

    方式一: 通过Object类中的getClass()方法    new Person().getClass();

    方式二:通过 类名.class 获取到字节码文件对象(任意数据类型都具备一个class静态属性) Class c2 = Person.class;

    方式三: 通过Class类中的方法(将类名作为字符串传递给Class类中的静态方法forName即可)。

                      Class c3 = Class.forName("Person");          //扩展性强

##  在反射机制中,把类中的成员(构造方法、成员方法、成员变量)都封装成了对应的类进行表示,可通过Class类中提供的方法获取相对应的构造方法、成员变量,成员方法对象。

        构造方法使用类Constructor表示,成员属性使用类 Field表示成员方法实用类Method表示,

        AccessibleObject 类是 Field、Method 和 Constructor 对象的父类。它提供了将反射的对象标记为在使用时取消默认 Java 语言访问控制检查的能力--  public void setAccessible(boolean flag) throws SecurityException   参数值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。参数值为 false 则指示反射的对象应该实施 Java 语言访问检查,我们编写的代码默认为false:   解释,就是我们要突破私有方法的限制就要暴力反射,setAccessible(true);

       //1,获取到Class对象

        Class c = Class.forName("cn.gllm.Person");//包名.类名

          // 2.1 Class类中提供的方法获取指定的构造方法对象

        构造方法对象 ------------                             

                        获取指定的构造方法   获取指定的public修饰的构造方法

                         public Constructor<T> getConstructor(Class<?>... parameterTypes)

                         获取指定的构造方法,包含私有的

                         public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)

                        获取所有的构造方法

                         public Constructor<?>[]  getConstructors()                  获取所有的public 修饰的构造方法

                         public Constructor<?>[]  getDeclaredConstructors()     获取所有的构造方法,包含私有的

                           

                         获取了制定的构造方法对象就可以获取对象()

                              public T newInstance(Object... initargs)

                       ###eg:     

                                  Constructor con = c.getConstructor(String.class, int.class, String.class);   //获取该对象制定的构造器对象

                                   Object obj = con.newInstance("小明", 22, "哈尔滨");      //调用构造对象的newinstance()方法创建对象

                                   如果获取的是私有的构造方法

                                   Constructor con = c.getConstructor(String.class, int.class, String.class); 

                                   con.setAccessible(true);// 暴力反射  取消 Java 语言访问检查   (con的获取方法是declared构造方法)

                                   Object obj = con.newInstance("小明", 22, "哈尔滨"); 

         //2.2  Class类中提供的方法获取成员变量对象

         成员变量对象---------------------

                         获取指定的成员变量

                          public Field getField(String name)                获取public修饰的成员变量

                          public Field getDeclaredField(String name)   获取任意的成员变量,包含私有

                          获取所有的成员变量

                          public Field[] getFields()                                获取所有public修饰的成员变量

                          public Field[] getDeclaredFields()                 获取司所有的成员变量,包含私有

 

                         

                         对成员变量赋值\获取值操作

                         public void set(Object obj,  Object value) 赋值

                         public Object get(Object obj) 获取值

 

                          ###eg:

                                    Field ageField = c.getField("age");

                                   Object age =  ageField.get(obj); //获取值          (obj可通过反射获得构造方法类调用newInstance生成对象

                                    ageField.set(obj, 23);  //赋值

                                   如果属性私有,获取的方法与构造方法相同 

         //2.3  Class类中提供的方法获取成员方法对象                                              

         成员方法对象---------------------

                     获取指定方法     

                    public Method getMethod(String name, Class<?>... parameterTypes)    获取指定的public方法                                                        public Method getDeclaredMethod(String name, Class<?>... parameterTypes) 获取指定的任意方法,包含私有的                         

                     获取所有的方法

                     public Method[] getMethods()                         获取本类与父类中所有public 修饰的方法

                     public Method[] getDeclaredMethods()          获取本类中所有的方法,包含私有的

 

                    执行方法 (获得的方法对象调用invoke去执行相对应得方法  )      私有的方法同私有的构造方法

                    public Object invoke(Object obj, Object... args)

                    ###eg:

                               Class c = Class.forName("cn.gllm.Person");

                               Constructor con = c.getConstructor(String.class, int.class, String.class);

                               Object obj = con.newInstance("小明", 23, "哈尔滨");

                               Method m4 = c.getMethod("method4", String.class);

                               Object result = m4.invoke(obj, "itcast");     

 

//======================================================================================

         

泛型擦除:其实程序编译后产生的.class文件中是没有泛型约束的,这种现象我们称为泛型的擦除

   

ArrayList<Integer> list = new ArrayList<Integer>();

        //添加元素到集合

        list.add(new Integer(30));

        list.add(new Integer("12345"));

        list.add(123);

        //list.add("哈哈");//因为有泛型类型的约束

        System.out.println(list);

       

        //通过反射技术,实现添加任意类型的元素

        //1, 获取字节码文件对象

        //Class c = list.getClass();

        //Class c = ArrayList.class;

        Class c = Class.forName("java.util.ArrayList");

       

        //2, 找到add()方法

        // public boolean add(E e)

        Method addMethod = c.getMethod("add", Object.class);

       

        //3  执行add()方法

        addMethod.invoke(list, "哈哈");// list.add("哈哈");

        System.out.println(list);

    }

}

//========================================================================================

 反射配置文件

    

  1. 通过反射配置文件,运行配置文件中指定类的对应方法

        读取Peoperties.txt文件中的数据,通过反射技术,来完成Person对象的创建

            Peoperties.txt文件内容如下:

                className=cn.itcast_01_Reflect.Person

                 methodName=method5

 

// 通过Properties集合从文件中读取数据

        Properties prop = new Properties();

        // 读取文件中的数据到集合中

        prop.load(new FileInputStream("properties.txt"));

        // 获取键所对应的值

        String className = prop.getProperty("className");

        System.out.println(className);

 

        // 1,获取Person.class 字节码文件对象

        Class c = Class.forName(className);

        // 2,获取构造方法

        // public Person(String name, int age, String address)

        Constructor con = c.getConstructor(String.class, int.class, String.class);

 

        // 3,创建对象

        Object obj = con.newInstance("小明", 20, "中国");

        System.out.println(obj);

 

        // 4,获取指定的方法

        // private void method5(){}

        String methodName = prop.getProperty("methodName");

        Method m5 = c.getDeclaredMethod(methodName, null);

        // 5,开启暴力访问

        m5.setAccessible(true);

        // 6,执行找到的方法

        m5.invoke(obj, null);

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值