Java反射机制
java反射机制概述
- Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API(反射接口)取得任何类的内部信息,并能直接操作任何对象的内部属性及方法
 
- 加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,我们形象的称为:反射。
 

动态语言 VS 静态语言
- 动态语言
 是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化。通俗点说就是在运行代码可以根据某些条件改变自身结构
 主要静态语言:Object-C、C#、JavaScript、PHP、Python、Erlang 
- 静态语言
 与动态语言相对应的,运行时结构不可变的语言就是静态语言。如Java、C、C++ 
- Java
 Java不是动态语言,但Java可以称之为”准动态语言”。即Java有一定的动态性,我们可以利用反射机制、字节码操作获得类似动态语言的特性。Java的动态性让编程的时候更加灵活 
Java反射机制研究及应用
- 在运行时判断任意一个对象所属的类
 
- 在运行时构造任意一个类的对象
 
- 在运行时判断任意一个类所具有的成员变量和方法
 
- 在运行时获取泛型信息
 
- 在运行时调用任意一个对象的成员变量和方法
 
- 在运行时处理注解
 
- 生成动态代理
 
Java反射相关的主要API
- java.lang.Class:代表一个类
 
- java.lang.reflect.Method:代表类的方法
 
- java.lang.reflect.Field:代表类的成员变量
 
- java.lang.reflect.Constructor:代表类的构造器
 
- ……
 
Java反射之前,类的实例化
Person类,封装了一些方法和构造器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
   | package com.atguigu.java;
  public class Person {     private String name;     public int age;     public Person() {}     @Override     public String toString() {         return "Person{" +                 "name='" + name + '\'' +                 ", age=" + age +                 '}';     }     public Person(String name, int age) {         this.name = name;         this.age = age;     }     private Person(String name){         this.name=name;     }
      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 void show(){         System.out.println("我是一个人");     }     private void showNation(String nation){         System.out.println("我的国籍是"+nation);         return;     } }
 
   | 
 
RefilectionTest类,调用Person类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   | package com.atguigu.java;
  import org.junit.Test;
  public class RefilectionTest {          @Test     public void test1(){                  Person p1 = new Person("Tom",12);                  p1.age=10;         System.out.println(p1.toString());         p1.show();                       } }
 
   | 
 
Java反射之后
Person类,封装了一些公有私有的属性,公有私有的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
   | package com.atguigu.java;
  public class Person {     private String name;     public int age;     public Person() {}     @Override     public String toString() {         return "Person{" +                 "name='" + name + '\'' +                 ", age=" + age +                 '}';     }     public Person(String name, int age) {         this.name = name;         this.age = age;     }     private Person(String name){         this.name=name;     }
      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 void show(){         System.out.println("我是一个人");     }     private void showNation(String nation){         System.out.println("我的国籍是"+nation);         return;     } }
 
   | 
 
RefilectionTest类,通过反射调用其中的属性和方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
   |   @Test  public void test2() throws Exception {            Class clazz = Person.class;      Constructor cons =clazz.getConstructor(String.class,int.class);      Object obj=cons.newInstance("Tom",12);      Person p  = (Person) obj;
                   Field age =clazz.getDeclaredField("age");      age.set(p,10);            Method shows=clazz.getDeclaredMethod("show");      shows.invoke(p);      System.out.println("***************************************");                        Constructor cons1=clazz.getDeclaredConstructor(String.class);      cons1.setAccessible(true);      Person p1=(Person) cons1.newInstance("Jerry");
             Field name=clazz.getDeclaredField("name");      name.setAccessible(true);      name.set(p1,"huangyufeng");      System.out.println(p1);
             Method nation=clazz.getDeclaredMethod("showNation", String.class);      nation.setAccessible(true);      nation.invoke(p1,"中国");        }
 
  | 
 
Java反射-Class类的理解
获取Class实例的四种方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
   |      } @Test public void test3() throws ClassNotFoundException {          Class clazz1 = Person.class;     System.out.println(clazz1);
           Person p1 = new Person();     Class clazz2  = p1.getClass();     System.out.println(clazz2);
           Class clazz3=Class.forName("com.atguigu.java.Person");     System.out.println(clazz3);
           ClassLoader classLoader=RefilectionTest.class.getClassLoader();     Class clazz4=classLoader.loadClass("com.atguigu.java.Person");     System.out.println(clazz4);
   | 
 
class实例对应的结构说明
- class:
 外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类 
- interface:接口
 
- []:接口
 
- enum:枚举
 
- annotation:注解@interface
 
- primitive type:基本数据类型
 
- void
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   |  @Test     public void test4(){         Class c1 = Object.class;         Class c2 = Comparable.class;         Class c3 = String[].class;         Class c4 = int[][].class;         Class<ElementType> c5 = ElementType.class;         Class c6 = Override.class;         Class c7 = int.class;         Class c8 = void.class;         Class c9 = Class.class;
          int[] a = new int[10];         int[] b = new int[100];         Class c10 = a.getClass();         Class c11 = b.getClass();                  System.out.println(c10==c11);
 
  | 
 
理解类的加载过程
当程序主动使用某个类时,如果该类还未被加载到内存中,则系统会通过如下三个步骤来对该类进行初始化

类的加载与ClassLoader的理解
类加载器的作用:
- 类加载器的作用:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口
 
- 类缓存:标准的JavaSE类加载器可以按照要求查找类,但一旦某个类被加载到类加载器中,它将维持加载(缓存)一段时间。不过JVM垃圾回收机制可以回收这些Class对象
 
ClassLoder:
类加载器的作用是用来把类(class)装载进内存的,JVM规范定义如下类似类的加载器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   | package com.atguigu.java;
  import org.junit.Test;
  public class ClassLoderTest {     @Test     public void test1(){                  ClassLoader classLoader=ClassLoderTest.class.getClassLoader();         System.out.println(classLoader);                  ClassLoader parent=classLoader.getParent();         System.out.println(parent);                           ClassLoader classLoader1=parent.getParent();         System.out.println(classLoader1);     } }
   | 
 

使用ClassLoader加载配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
   | 
 
  @Test public void test2() throws IOException {     Properties properties = new Properties();                FileInputStream fis = new FileInputStream("D:\\Documents\\java\\javaweb\\jdbc\\src\\jdbc.properties");      properties.load(fis);
                     InputStream is = ClassLoderTest.class.getClassLoader().getResourceAsStream("jdbc.properties");     properties.load(is);
      String user=properties.getProperty("user");     String password=properties.getProperty("password");     System.out.println(user+","+password); }
 
  | 
 
创建运行时类的实例化对象
通过反射创建对应的运行时类的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
   | 
 
  public class NewInstanceTest {     @Test     public void test1() throws Exception {         Class clazz = Person.class;         
 
 
 
 
 
 
 
 
 
          Person obj = (Person) clazz.newInstance();         System.out.println(obj);         obj.show();
      }
 
  | 
 
举例体会反射的动态性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   |          @Test     public void test2(){
          for(int i = 0;i < 100;i++){             int num = new Random().nextInt(3);             String classPath = "";             switch(num){                 case 0:                     classPath = "java.util.Date";                     break;                 case 1:                     classPath = "java.lang.Object";                     break;                 case 2:                     classPath = "com.atguigu.java.Person";                     break;             }
              try {                 Object obj = getInstance(classPath);                 System.out.println(obj);             } catch (Exception e) {                 e.printStackTrace();             }         }
 
      }
      
 
 
      public Object getInstance(String classPath) throws Exception {        Class clazz =  Class.forName(classPath);        return clazz.newInstance();     }
  }
   | 
 
运行时,会对于内存中的运行时类,做出不同的判断来对此进行操作
获取运行时类的完整结构
获取运行时类的属性结构与内部结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
   | public class FieldTest {     @Test     public void test1() throws InstantiationException, IllegalAccessException {         Class clazz = Person.class;         Person p1 = (Person) clazz.newInstance();         System.out.println(clazz);         System.out.println(p1);
                            Field[] fields = clazz.getFields();         for (Field f : fields) {             System.out.println(f);         }         System.out.println("*********************************");
                   Field[] declaredFields = clazz.getDeclaredFields();         for (Field f : declaredFields) {             System.out.println(f);         }     }
      @Test     public void test2() {         Class clazz = Person.class;         Field[] declaredFields = clazz.getDeclaredFields();         for (Field f : declaredFields) {             System.out.println(f);                          int modifiers=f.getModifiers();             System.out.println(modifiers);             System.out.println(Modifier.toString(modifiers));                          Class type=f.getType();             System.out.println(type+"\t");                          String name = f.getName();             System.out.println(name);         }     }
  | 
 
获取运行时类的方法结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   | 
 
  public class MethodTest {     @Test     public void  test1(){         Class clazz = Person.class;
                   Method[] method =clazz.getMethods();         for (Method m:method){             System.out.println(m);         }         System.out.println("********************");
                   Method[] method2=clazz.getDeclaredMethods();         for (Method method1:method2){             System.out.println(method1);         }     } }
 
  | 
 
获取方法的权限修饰符,返回值类型,方法名(参数类型1 形参名1,……)throws
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
   | 
 
 
   @Test  public void test2(){      Class clazz = Person.class;      Method[] declaredMethods = clazz.getDeclaredMethods();      for(Method m : declaredMethods){                    Annotation[] annos = m.getAnnotations();          for(Annotation a : annos){              System.out.println(a);          }
                     System.out.print(Modifier.toString(m.getModifiers()) + "\t");
                     System.out.print(m.getReturnType().getName() + "\t");
                     System.out.print(m.getName());          System.out.print("(");                    Class[] parameterTypes = m.getParameterTypes();          if(!(parameterTypes == null && parameterTypes.length == 0)){              for(int i = 0;i < parameterTypes.length;i++){
                   if(i == parameterTypes.length - 1){                      System.out.print(parameterTypes[i].getName() + " args_" + i);                      break;                  }
                   System.out.print(parameterTypes[i].getName() + " args_" + i + ",");              }          }
           System.out.print(")");
                     Class[] exceptionTypes = m.getExceptionTypes();          if(exceptionTypes.length > 0){              System.out.print("throws ");              for(int i = 0;i < exceptionTypes.length;i++){                  if(i == exceptionTypes.length - 1){                      System.out.print(exceptionTypes[i].getName());                      break;                  }
                   System.out.print(exceptionTypes[i].getName() + ",");              }          }
 
           System.out.println();      }
 
 
   }
 
  | 
 
获取运行时类的构造器结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   | 
 
  public class OtherTest {
      @Test     public void test1(){         Class clazz = Person.class;                  Constructor[] constructors1 =clazz.getConstructors();         for (Constructor c:constructors1){             System.out.println(c);         }         System.out.println("***********************");
                   Constructor[] constructors2=clazz.getDeclaredConstructors();         for (Constructor constructor:constructors2){             System.out.println(constructor);         }     } }
 
  | 
 
获取运行时类的父类及父类的泛型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
   | public class OtherTest {     
 
      @Test     public void test2(){         Class clazz = Person.class;         Class superclass=clazz.getSuperclass();         System.out.println(superclass);     }
      
 
      @Test     public void test3(){         Class clazz = Person.class;         Type superclass =clazz.getGenericSuperclass();         System.out.println(superclass);     }
      
 
      @Test     public void test4(){         Class clazz = Person.class;         Type superclass =clazz.getGenericSuperclass();         ParameterizedType parameterizedType = (ParameterizedType)superclass;                  Type[] actualTypeArguments= parameterizedType.getActualTypeArguments();         System.out.println(actualTypeArguments[0].getTypeName());     } }
  | 
 
获取运行时类的接口,所在包,注解等
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   | 
 
      @Test     public void test5(){         Class clazz = Person.class;         Class[] classinter=clazz.getInterfaces();         for (Class c :classinter){             System.out.println(c);         }         System.out.println("*******************");                  Class[] interfaces1=clazz.getSuperclass().getInterfaces();         for (Class c1:interfaces1){             System.out.println(c1);         }     }
      
 
      @Test     public void test6(){         Class clazz = Person.class;         Package pack=clazz.getPackage();         System.out.println(pack);     }
      
 
      @Test     public void test7(){         Class clazz = Person.class;         Annotation[] clazzAnnotations =clazz.getAnnotations();         for (Annotation a:clazzAnnotations){             System.out.println(a);         }     }
 
 
  | 
 
调用运行时类的指定结构
调用运行时类中的指定属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
   | 
 
  public class ReflectionTest {     @Test     public void  testField() throws Exception {         Class clazz = Person.class;
                   Person p = (Person) clazz.newInstance();
                            Field id =clazz.getField("id");
                   
 
          id.set(p,1001);
          
 
 
          int pId=(int)id.get(p);         System.out.println(pId);     } 	
 
      @Test     public void testField1() throws Exception{         Class clazz = Person.class;
                   Person p = (Person) clazz.newInstance();
                   Field name=clazz.getDeclaredField("name");
                   name.setAccessible(true);
                   name.set(p,"Tom");         String pName=(String) name.get(p);         System.out.println(pName);     } }
 
  | 
 
调用运行时类中的指定方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   |     
 
      @Test     public void testMethod() throws Exception{         Class clazz = Person.class;
                   Person p=(Person) clazz.newInstance();
          
 
          Method show =clazz.getDeclaredMethod("show",String.class);
                   show.setAccessible(true);
          
 
 
 
          show.invoke(p,"CHN");         Object returnValue=show.invoke(p,"CHN");         System.out.println(returnValue);
          System.out.println("***************如何调用静态方法****************");                  Method showDesc=clazz.getDeclaredMethod("showDesc");         showDesc.setAccessible(true);         showDesc.invoke(Person.class.newInstance());                           Object returnVal = showDesc.invoke(Person.class.newInstance());         System.out.println(returnVal);
 
      } }
   | 
 
调用运行时类的指定构造器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
   |     
 
      @Test     public void testConstructor()throws Exception{         Class clazz = Person.class;
          
 
 
          Constructor constructor =clazz.getDeclaredConstructor(String.class,int.class);
                   constructor.setAccessible(true);
                   Person per = (Person) constructor.newInstance("Tom",12);         System.out.println(per);     } }
   | 
 
代理模式
代理设计模式的原理