1.反射机制是什么

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

2.反射机制能做什么

反射机制主要提供了以下功能: 

  • 在运行时判断任意一个对象所属的类;

  • 在运行时构造任意一个类的对象;

  • 在运行时判断任意一个类所具有的成员变量和方法;

  • 在运行时调用任意一个对象的方法;

  • 生成动态代理。

3.反射的优缺点

优点:

(1)能够运行时动态获取类的实例,大大提高系统的灵活性和扩展性。
(2)与Java动态编译相结合,可以实现无比强大的功能
缺点:
(1)使用反射的性能较低
(2)使用反射相对来说不安全
(3)破坏了类的封装性,可以通过反射获取这个类的私有方法和属性

4.Class类

Object类中定义了以下的方法,此方法将被所有子类继承:

  public final Class getClass()

以上的方法返回值的类型是一个Class类,此类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称。

对照镜子后可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个类的有关信息。

    Class本身也是一个类
    Class 对象只能由系统建立对象
    一个类在 JVM 中只会有一个Class实例
    一个Class对象对应的是一个加载到JVM中的一个.class文件
    每个类的实例都会记得自己是由哪个 Class 实例所生成
    通过Class可以完整地得到一个类中的完整结构

5.ClassLoader

类加载器是用来把类(class)装载进内存的。JVM 规范定义了两种类型的类加载器:启动类加载器(bootstrap)和用户自定义加载器(user-defined classloader)JVM在运行时会产生3个类加载器组成的初始化加载器层次结构,如下图所示:

// 1.获取一个系统类加载器    ClassLoader loader1 = ClassLoader.getSystemClassLoader();    System.out.println(loader1);// 2.获取系统类加载器的父类加载器,即扩展类加载器    ClassLoader loader2 = loader1.getParent();    System.out.println(loader2);// 3.获取扩展类加载器的父类加载器,即引导类加载器    ClassLoader loader3 = loader2.getParent();    System.out.println(loader3);// 4.测试当前类由哪个类加载器进行加载    Class clazz1 = Person.class;    ClassLoader loader4 = clazz1.getClassLoader();    System.out.println(loader4);// 5.测试String类由哪个类加载器进行加载    String className = "java.lang.String";    Class clazz2 = Class.forName(className);    ClassLoader loader5 = clazz2.getClassLoader();    System.out.println(loader5);// 6.关于类加载器的一个主要方法:getResourceAsStream(String str):获取类路径下的指定文件的输入流    ClassLoader loader = this.getClass().getClassLoader();    InputStream is = loader.getResourceAsStream("com\\ciyo\\java\\jdbc.properties");    // 法二:    // FileInputStream is = new FileInputStream(new    // File("jdbc.properties"));     Properties pros = new Properties();     pros.load(is);     String name = pros.getProperty("user");     System.out.println(name);     String password = pros.getProperty("password");     System.out.println(password);

输出结果:

sun.misc.Launcher$AppClassLoader@18b4aac2sun.misc.Launcher$ExtClassLoader@50cbc42fnullsun.misc.Launcher$AppClassLoader@18b4aac2nullroot123abc

6.实例化Class类对象

 //1.调用运行时类本身的.class属性  Class clazz1 = Person.class;  System.out.println(clazz1.getName()); //2.通过运行时类的对象获取   Person p = new Person();   Class clazz2 = p.getClass();   System.out.println(clazz2.getName()); //3.通过Class的静态方法获取.通过此方式,体会一下,反射的动态性。   String className = "com.ciyo.java.Person";    Class clazz3 = Class.forName(className);   System.out.println(clazz3.getName()); //4.(了解)通过类的加载器   ClassLoader classLoader = this.getClass().getClassLoader();   Class clazz4 = classLoader.loadClass(className);   System.out.println(clazz4.getName());   System.out.println(clazz1 == clazz2);// true   System.out.println(clazz1 == clazz3);// true   System.out.println(clazz1 == clazz4);// true

输出结果:

com.ciyo.java.Personcom.ciyo.java.Personcom.ciyo.java.Personcom.ciyo.java.Persontruetruetrue

7.反射机制实例化一个类的对象

方法一:调用Class对象的newInstance()方法

   要求:1)类必须有一个无参数的构造器。
            2)类的构造器的访问权限需要足够。
方法二:通过Class类的getDeclaredConstructor(Class … parameterTypes)取得本类的指定形参类型的构造器,生成Constructor的实例
方法三:通过Class类的getConstructors获取所有构造方法,生成Constructor的实例

import java.lang.reflect.Constructor;public class TestReflect {    public static void main(String[] args) throws Exception {        Class
 class1 = null;        class1 = Class.forName("com.ciyo.java.User");        // 第一种:调用Class对象的newInstance()方法        User user = (User) class1.newInstance();        user.setAge(20);        user.setName("Rollen");        System.out.println(user);        // 结果 User [age=20, name=Rollen]        // 第二种方法:获取指定的构造函数 使用构造函数赋值        Constructor con = class1.getDeclaredConstructor(int.class, String.class);        //调用setAccessible(true)方法,将可访问private的构造方法。        con.setAccessible(true);        user = (User) con.newInstance(30, "FillKer");        System.out.println(user);        // 结果 User [age=30, name=FillKer]        // 第三种方法:取得全部的构造函数 使用构造函数赋值        Constructor
 cons[] = class1.getConstructors();        // 查看每个构造方法需要的参数        for (int i = 0; i < cons.length; i++) {            Class
 clazzs[] = cons[i].getParameterTypes();            System.out.print("cons[" + i + "] (");            for (int j = 0; j < clazzs.length; j++) {                if (j == clazzs.length - 1)                    System.out.print(clazzs[j].getName());                else                    System.out.print(clazzs[j].getName() + ",");            }            System.out.println(")");        }        // 结果        // cons[0] (int,java.lang.String)        // cons[1] (java.lang.String)        // cons[2] ()        user = (User) cons[0].newInstance(20, "Rollen");        System.out.println(user);        // 结果 User [age=20, name=Rollen]        user = (User) cons[1].newInstance("Rollen");        System.out.println(user);        // 结果 User [age=0, name=Rollen]    }}class User {    private int age;    private String name;    public User() {        super();    }    public User(String name) {        super();        this.name = name;    }    public User(int age, String name) {        super();        this.age = age;        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    @Override    public String toString() {        return "User [age=" + age + ", name=" + name + "]";    }}

8.获取某个类的全部方法

        // 1.获取运行时类的方法 注解 权限修饰符 返回值类型 方法名 形参列表 异常        Class clazz = Person.class;        // 1.getMethods():获取运行时类及其父类中所有的声明为public的方法        Method[] m1 = clazz.getMethods();        // 2.getDeclaredMethods():获取运行时类本身声明的所有的方法        Method[] m2 = clazz.getDeclaredMethods();        for (Method m : m2) {            // 1.注解            Annotation[] ann = m.getAnnotations();            // 2.权限修饰符(public,private...)            String modifier = Modifier.toString(m.getModifiers());            // 3.返回值类型            Class returnType = m.getReturnType();            // 4.方法名            String methodName = m.getName();            // 5.形参列表            Class[] params = m.getParameterTypes();            // 6.异常类型            Class[] exps = m.getExceptionTypes();            for (int i = 0; i < exps.length; i++) {                System.out.println(exps[i].getName());            }        }        // 调用运行时类中指定的方法        // getMethod(String methodName,Class ... params):获取运行时类中声明为public的指定的方法        Method m3 = clazz.getMethod("show");        Person p = (Person) clazz.newInstance();        // 调用指定的方法:Object invoke(Object obj,Object ... obj)        Object returnVal = m3.invoke(p);// 我是一个人!        // getDeclaredMethod(String methodName,Class ...        // params):获取运行时类中声明了的指定的方法        Method m4 = clazz.getDeclaredMethod("display", String.class, Integer.class);        //调用setAccessible(true)方法,将可访问private的方法。        m4.setAccessible(true);        Object value = m4.invoke(p, "CHN", 10);// 我的国籍是:CHN
import static java.lang.annotation.ElementType.CONSTRUCTOR;import static java.lang.annotation.ElementType.FIELD;import static java.lang.annotation.ElementType.LOCAL_VARIABLE;import static java.lang.annotation.ElementType.METHOD;import static java.lang.annotation.ElementType.PARAMETER;import static java.lang.annotation.ElementType.TYPE;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})@Retention(RetentionPolicy.RUNTIME)public @interface MyAnnotation {    String value();}
import java.io.Serializable;public interface MyInterface extends Serializable{}
public class Creature
{    public double weight;        public void breath(){        System.out.println("呼吸!");    }}
@MyAnnotation(value = "person")public class Person extends Creature
 implements Comparable, MyInterface {    public String name;    private int age;    int id;    // 创建类时,尽量保留一个空参的构造器。    Person() {        super();    }    public Person(String name) {        super();        this.name = name;    }    private Person(String name, int age) {        super();        this.name = name;        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    @MyAnnotation(value = "abc123")    public void show() {        System.out.println("我是一个人!");    }    private Integer display(String nation, Integer i) throws Exception {        System.out.println("我的国籍是:" + nation);        return i;    }    @Override    public String toString() {        return "Person [name=" + name + ", age=" + age + "]";    }    @Override    public int compareTo(Object o) {        // TODO Auto-generated method stub        return 0;    }    public static void info() {        System.out.println("中国人!");    }    class Bird {    }}

9.获取某个类的全部属性

        Class clazz = Person.class;        // 1.getFields():只能获取到运行时类中及其父类中声明为public的属性        Field[] fields = clazz.getFields();        // 2.getDeclaredFields():获取运行时类本身声明的所有的属性        Field[] fields1 = clazz.getDeclaredFields();        for (Field f : fields1) {            // 1.获取每个属性的权限修饰符            int i = f.getModifiers();            String str1 = Modifier.toString(i);            // 2.获取属性的类型            Class type = f.getType();            // 3.获取属性名            String name = f.getName();        }        // 1.获取指定的属性        // getField(String fieldName):获取运行时类中声明为public的指定属性名为fieldName的属性        Field name = clazz.getField("name");        // 2.创建运行时类的对象        Person p = (Person) clazz.newInstance();        // 3.将运行时类的指定的属性赋值        name.set(p, "Jerry");        System.out.println(p);        // getDeclaredField(String fieldName):获取运行时类中指定的名为fieldName的属性        Field age = clazz.getDeclaredField("age");        // 由于属性权限修饰符的限制,为了保证可以给属性赋值,需要在操作前使得此属性可被操作。        age.        (true);        age.set(p, 10);        System.out.println(p);

10.获取一个对象的父类与实现的接口

        Class clazz = Person.class;        // 1.获取运行时类的父类        Class superClass = clazz.getSuperclass();        System.out.println(superClass);        // 2.获取父类的泛型        Type type1 = clazz.getGenericSuperclass();        ParameterizedType param = (ParameterizedType) type1;        //获取实际的泛型类型参数数组        Type[] ars = param.getActualTypeArguments();        System.out.println(((Class) ars[0]).getName());        // 3.获取实现的接口        Class[] interfaces = clazz.getInterfaces();        // 4.获取所在的包        Package pack = clazz.getPackage();        // 5.获取注解        Annotation[] anns = clazz.getAnnotations();

通过反射拷贝类对象

例子:

import java.lang.reflect.Field;import java.lang.reflect.Method;public class ReflectTester{    public Object copy(Object object) throws Exception    {        // 获得对象的类型        Class
 classType = object.getClass();        System.out.println("Class:" + classType.getName());        // 通过默认构造方法创建一个新的对象        Object objectCopy = classType.getConstructor(new Class[] {}).newInstance(new Object[] {});        // 获得对象的所有属性        Field fields[] = classType.getDeclaredFields();        for (int i = 0; i < fields.length; i++)        {            Field field = fields[i];            String fieldName = field.getName();            String firstLetter = fieldName.substring(0, 1).toUpperCase();            // 获得和属性对应的getXXX()方法的名字            String getMethodName = "get" + firstLetter + fieldName.substring(1);            // 获得和属性对应的setXXX()方法的名字            String setMethodName = "set" + firstLetter + fieldName.substring(1);            // 获得和属性对应的getXXX()方法            Method getMethod = classType.getMethod(getMethodName, new Class[] {});            // 获得和属性对应的setXXX()方法            Method setMethod = classType.getMethod(setMethodName, new Class[] { field.getType() });                        // 调用原对象的getXXX()方法            Object value = getMethod.invoke(object, new Object[] {});            System.out.println(fieldName + ":" + value);            // 调用拷贝对象的setXXX()方法            setMethod.invoke(objectCopy, new Object[] { value });        }        return objectCopy;    }    public static void main(String[] args) throws Exception    {        Customer customer = new Customer("Tom", 21);        customer.setId(new Long(1));        Customer customerCopy = (Customer) new ReflectTester().copy(customer);        System.out.println("Copy information:" + customerCopy.getId() + " " + customerCopy.getName() + " "                + customerCopy.getAge());    }}class Customer{    private Long id;    private String name;    private int age;    public Customer()    {    }    public Customer(String name, int age)    {        this.name = name;        this.age = age;    }    public Long getId()    {        return id;    }    public void setId(Long id)    {        this.id = id;    }    public String getName()    {        return name;    }    public void setName(String name)    {        this.name = name;    }    public int getAge()    {        return age;    }    public void setAge(int age)    {        this.age = age;    }}

11.动态代理

import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;//动态代理的使用,体会反射是动态语言的关键interface Subject {    void action();}// 被代理类class RealSubject implements Subject {    public void action() {        System.out.println("我是被代理类,记得要执行我哦!么么~~");    }}class MyInvocationHandler implements InvocationHandler {    Object obj;// 实现了接口的被代理类的对象的声明    // ①给被代理的对象实例化②返回一个代理类的对象    public Object blind(Object obj) {        this.obj = obj;        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj                .getClass().getInterfaces(), this);    }    //当通过代理类的对象发起对被重写的方法的调用时,都会转换为对如下的invoke方法的调用    @Override    public Object invoke(Object proxy, Method method, Object[] args)            throws Throwable {        //method方法的返回值时returnVal        Object returnVal = method.invoke(obj, args);        return returnVal;    }}public class TestProxy {    public static void main(String[] args) {        //1.被代理类的对象        RealSubject real = new RealSubject();        //2.创建一个实现了InvacationHandler接口的类的对象        MyInvocationHandler handler = new MyInvocationHandler();        //3.调用blind()方法,动态的返回一个同样实现了real所在类实现的接口Subject的代理类的对象。        Object obj = handler.blind(real);        Subject sub = (Subject)obj;//此时sub就是代理类的对象                sub.action();//转到对InvacationHandler接口的实现类的invoke()方法的调用    }}

12.马士兵老师动态代理实现代码

(1)首先创建一个接口

package com.alan.proxy.dynamic1;    public interface Flyable {            void fly() ;  }

(2)创建这个接口的一个实现类

package com.alan.proxy.dynamic1;    public class Plane implements Flyable{     @Override   public void fly() {    System.out.println("Plane is Flying....");   }    }

(3)创建一个动态的代理类

package com.alan.proxy.dynamic1;    import java.io.File;  import java.io.FileWriter;  import java.io.IOException;  import java.lang.reflect.Constructor;  import java.lang.reflect.Method;  import java.net.URL;  import java.net.URLClassLoader;    public class Proxy {        public static Object newInstance(Class intefc, InvocationHandler h) throws Exception {          String rt = "\r\t" ;          String methodStr = "" ;          // 首先实现这个接口的所有方法          Method[] methods = intefc.getMethods();          for (Method m : methods) {              methodStr += "@Override"+rt+                          "public void "+m.getName()+"(){"+rt+                          "    try{"+rt+                          "        Method md = "+intefc.getName()+".class.getMethod(\""+m.getName()+"\");" + rt +                          "        h.invoke(this,md);" +rt+                          "    }catch(Exception ex){}" +rt+                          "}" ;                                    }          String clazzStr =  "package com.alan.proxy.dynamic1;"+rt+                             "import java.lang.reflect.Method;"+rt+                             "public class $Proxy1 implements "+intefc.getName()+"{"+rt+                             "    public $Proxy1(InvocationHandler h){"+rt+                             "        this.h=h;"+rt+                             "    }"+rt+                             "private com.alan.proxy.dynamic1.InvocationHandler h ;"+rt+                              methodStr +rt+                             "}";          //写入到一个java文件里面                    File file = new File("D:/workspace/JAVA_Pattern/src/com/alan/proxy/dynamic1/$Proxy1.java") ;          FileWriter writer = null ;          try {              writer = new FileWriter(file);              writer.write(clazzStr) ;              writer.flush() ;          } catch (IOException e) {              e.printStackTrace();          }finally{              try {                  if(writer !=null){                      writer.close() ;                  }              } catch (IOException e) {                  e.printStackTrace();              }          }          //将这个Java文件加载到内存,并返回一个Object对象          URL[] urls = new URL[] {new URL("file:/" + "D:/workspace/JAVA_Pattern/src/")};          URLClassLoader ul = new URLClassLoader(urls);          Class c = ul.loadClass("com.alan.proxy.dynamic1.$Proxy1");          System.out.println(c);          //返回一个代理对象          Constructor ctr = c.getConstructor(InvocationHandler.class);          Object m = ctr.newInstance(h);            return m;      }  }

(4)创建一个代理的处理器接口

package com.alan.proxy.dynamic1;    import java.lang.reflect.Method;    public interface InvocationHandler {      void invoke(Object o, Method m) ;  }

(5)创建这个处理器的一个实现类

package com.alan.proxy.dynamic1;    import java.lang.reflect.Method;    public class CheckInvocationHandler implements InvocationHandler{            private Object target ;      public CheckInvocationHandler(Object target){          this.target = target ;      }      @Override      public void invoke(Object o, Method m) {          try {              //调用被代理对象的方法              System.out.println("飞行器  起飞前检查......");              m.invoke(target) ;              System.out.println("飞行器起飞后 检查........");          }catch (Exception e) {              // TODO Auto-generated catch block              e.printStackTrace();          }      }    }

(6)创建一个类

package com.alan.proxy.dynamic1;    public class Client {      public static void main(String[] args) {                    try {              Flyable o = (Flyable)Proxy.newInstance(Flyable.class, new CheckInvocationHandler(new Plane())) ;              o.fly() ;          } catch (Exception e) {              e.printStackTrace();          }      }  }

运行的结果:

class com.alan.proxy.dynamic1.$Proxy1  飞行器  起飞前检查......  Plane is Flying....  飞行器起飞后 检查........

总结:

Proxy的主要功能是:动态的创建某个接口的代理类,通过调用处理器的处理方法来实现对某个接口的代理。

XXXInvocationHandler:实现对某个被代理对象的处理。