zoukankan      html  css  js  c++  java
  • JavaWeb_反射

    反射之中包含了一个【反】字,所以想要解释反射就必须先从【正】开始解释。

    一般情况下,我们使用某个类时必定知道它是什么类,是用来做什么的。于是我们直接对这个类进行实例化,之后使用这个类对象进行操作。

    Person p1 = new Person();
    p1.setName("zhangsan");

    上面这个样子进行类对象的初始化,我们可以理解为【正】。

    而反射则是一开始并不知道我们要初始化的类对象是什么,自然也无法使用new关键字来创建对象了。

    这时候,我们使用JDK提供的反射API进行反射调用:

    Class clz = Class.forName("com.study.reflect.Person");
    Method method = clz.getMethod("setName",String.class);
    Constructor constructor = clz.getConstructor();
    Person p1 = (Person) constructor.newInstance();
    method.invoke(p1,"zhangsan");
    System.out.println(p1.getName());

    上面两端代码的执行结果,其实是完全一样的。但是其思路完全不一样,第一段代码在未运行时就已经确定了要运行的类(Person),而第二段代码则是在运行时通过字符串值才得知要运行的类(com.study.reflect.Person)。

    所以说什么是反射?

    反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。

    一个类有多个组成部分,例如:成员变量,方法,构造方法等。反射就是加载类,并解剖出类的各个组成部分。

    编程时什么情况下才需要加载类,并解剖出类的各个组成部分呢?

    反射是用来做框架的。

    从配置文件中解读类的方法等。

    Java中有一个Class类用于代表某一个类的字节码。

    Class类既然代表某个类的字节码,它当然就要提供加载某个类字节码的方法:forName().

    forName方法用于加载某个类的字节码到内存中,并使用class对象进行封装。

    另外两种得到class对象的方式

    类名.class

    对象.getClass()

    因此类的加载方法公有三种:

    1、Class.forName("com.xx.xx")

    2、类名.class

    3、对象.getClass()

    下面看三种类的加载方法

     1 package cn.itcast.reflect;
     2 
     3 public class Demo1 {
     4 
     5     public static void main(String[] args) throws Exception {
     6         // TODO Auto-generated method stub
     7         //加载类的字节码1,常用
     8         Class clazz1 = Class.forName("cn.itcast.reflect.Person");
     9         
    10         //加载类的字节码2
    11         Class clazz2 = Person.class;
    12         
    13         //加载类的字节码3
    14         Class clazz3 = new Person().getClass();
    15 
    16     }
    17 
    18 }

    Class对象提供了如下常用方法:

    1 public Constructor getConstructor(Class<?>... parameterTypes)
    2 public Method getMethod(String name,Class<?>... parameterTypes)
    3 public Field getField(String name)
    4     
    5 public Constructor getDeclaredConstructor(Class<?>... parameterTypes)
    6 public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
    7 public Field getDeclaredField(String name) 

    这些方法分别用于从类中解剖出构造函数、方法和成员变量(属性)。解剖出的成员分别使用Constructor,Method,Field对象表示。

    思考:假设你是一个框架的设计者,出这些成员后你会干什么?

    先看反射类的构造方法。

     1 //Demo1.java
     2 package cn.itcast.reflect;
     3 import java.lang.reflect.Constructor;
     4 import org.junit.Test;
     5 public class Demo1 {
     6 
     7     public static void main(String[] args) throws Exception {
     8         // TODO Auto-generated method stub
     9         //加载类的字节码1,常用
    10         Class clazz = Class.forName("cn.itcast.reflect.Person");
    11         Constructor c = clazz.getConstructor(null);
    12         
    13         Object obj = c.newInstance(null);
    14         
    15         System.out.println(obj);
    16         
    17 
    18     }
    19     
    20     //反射无参的构造函数
    21     @Test
    22     public void test1() throws Exception{
    23         Class clazz = Class.forName("cn.itcast.reflect.Person");
    24         Constructor c = clazz.getConstructor(null);
    25         
    26         Object obj = c.newInstance(null);
    27         
    28         System.out.println(obj);
    29     }
    30     
    31     
    32     //反射有参的构造函数
    33     @Test
    34     public void test2() throws Exception{
    35         Class clazz = Class.forName("cn.itcast.reflect.Person");
    36         Constructor c = clazz.getConstructor(String.class);
    37         
    38         Person p = (Person) c.newInstance("fix");
    39         System.out.println(p);
    40     }
    41     
    42     //反射私有的,有参的构造函数
    43     @Test
    44     public void test3() throws Exception{
    45         Class clazz = Class.forName("cn.itcast.reflect.Person");
    46         Constructor c = clazz.getDeclaredConstructor(int.class);
    47         c.setAccessible(true);//暴力反射
    48         Person p = (Person) c.newInstance(1);
    49         System.out.println(p);
    50     }
    51 }

    下面看反射类的方法

     1 package cn.itcast.reflect;
     2 
     3 import java.lang.reflect.Method;
     4 
     5 import org.junit.Test;
     6 
     7 public class Demo2 {
     8     //反射方法
     9     
    10     //反射不带参数的方法
    11     @Test
    12     public void test1() throws Exception{
    13         Class clazz = Class.forName("cn.itcast.reflect.Person");
    14         
    15         Method method = clazz.getMethod("eat", null);
    16         
    17         method.invoke(clazz.newInstance(), null);
    18     }
    19     
    20     //反射带参数的方法
    21     @Test
    22     public void test2() throws Exception{
    23         Class clazz = Class.forName("cn.itcast.reflect.Person");
    24         
    25         Method method = clazz.getMethod("run", String.class);
    26         
    27         method.invoke(clazz.newInstance(), "上海");
    28     }
    29     
    30     //反射带多个参数的方法
    31     @Test
    32     public void test3() throws Exception{
    33         Class clazz = Class.forName("cn.itcast.reflect.Person");
    34         
    35         Method method = clazz.getMethod("run", String.class,int[].class,String[].class);
    36         
    37         method.invoke(clazz.newInstance(), "上海",new int[]{1,2,3},new String[]{"a","b","c"});
    38     }
    39     
    40     
    41     //反射带返回值的方法
    42     @Test
    43     public void test4() throws Exception{
    44         Class clazz = Class.forName("cn.itcast.reflect.Person");
    45         
    46         Method method = clazz.getMethod("test", String.class);
    47         
    48         String result = (String) method.invoke(clazz.newInstance(), "上海");
    49         System.out.println(result);
    50     }
    51     
    52     
    53     //反射私有方法
    54     @Test
    55     public void test5() throws Exception{
    56         Class clazz = Class.forName("cn.itcast.reflect.Person");
    57         
    58         Method method = clazz.getDeclaredMethod("test2", String.class);
    59         method.setAccessible(true);//暴力反射
    60         String result = (String) method.invoke(clazz.newInstance(), "上海");
    61         System.out.println(result);
    62     }
    63     
    64     
    65     //反射静态方法
    66     @Test
    67     public void test6() throws Exception{
    68         Class clazz = Class.forName("cn.itcast.reflect.Person");
    69         
    70         Method method = clazz.getMethod("test3", String.class);
    71         String result = (String) method.invoke(null, "上海");
    72         System.out.println(result);
    73     }
    74         
    75     //反射main方法
    76     //通过反射调用带数组的方法,要注意处理
    77     @Test
    78     public void test7() throws Exception{
    79         Class clazz = Class.forName("cn.itcast.reflect.Person");
    80         
    81         Method method = clazz.getMethod("main", String[].class);
    82         //method.invoke(null, (Object)new String[]{"1","2"});
    83         method.invoke(null, new Object[]{new String[]{"1","2"}});
    84     }
    85 }

    利用Field访问属性

    Field对象提供了如下方法,用于设置、获取对象属性的值:

    public void set(Object obj,Object value)

    public Object get(Object obj)

     1 package cn.itcast.reflect;
     2 
     3 import java.lang.reflect.Field;
     4 
     5 import org.junit.Test;
     6 
     7 public class Demo3 {
     8 
     9     /**
    10      * 反射类的字段
    11      * @throws Exception 
    12      */
    13     //反射公有成员变量
    14     @Test
    15     public void test1() throws Exception{
    16         
    17         Person p = new Person();
    18         Class clazz = Class.forName("cn.itcast.reflect.Person");
    19         
    20         Field f = clazz.getField("name");
    21         
    22         f.set(p, "flx");
    23         System.out.println(p.getName());
    24         
    25     }
    26     
    27     
    28     //反射公有成员变量
    29     @Test
    30     public void test2() throws Exception{
    31         
    32         Person p = new Person();
    33         p.setName("xxx");
    34         Class clazz = Class.forName("cn.itcast.reflect.Person");
    35         Field f = clazz.getField("name");
    36         String result = (String)f.get(p);
    37         System.out.println(result);
    38         
    39     }
    40     
    41     //反射final成员变量
    42     @Test
    43     public void test3() throws Exception{
    44         
    45         Person p = new Person();
    46         Class clazz = Class.forName("cn.itcast.reflect.Person");
    47         Field f = clazz.getField("password");
    48         String result = (String)f.get(p);
    49         System.out.println(result);
    50         
    51     }
    52     
    53     //反射私有成员变量
    54     @Test
    55     public void test4() throws Exception{
    56         Person p = new Person();
    57         Class clazz = Class.forName("cn.itcast.reflect.Person");
    58         Field f = clazz.getDeclaredField("age");
    59         f.setAccessible(true);
    60         f.set(p, 123);
    61         int result = (Integer)f.getInt(p);
    62         System.out.println(result);
    63     }
    64 }

    Person类如下:

     1 package cn.itcast.reflect;
     2 
     3 public class Person {
     4     
     5     public String name;//字段或成员变量
     6     private int age;
     7     
     8     public final String password="123";
     9     
    10     
    11     public String getName() {
    12         return name;
    13     }
    14 
    15     public void setName(String name) {
    16         this.name = name;
    17     }
    18 
    19     public int getAge() {
    20         return age;
    21     }
    22 
    23     public void setAge(int age) {
    24         this.age = age;
    25     }
    26 
    27     public Person(){
    28         System.out.println("person");
    29     }
    30     
    31     public Person(String name){
    32         System.out.println(name);
    33     }
    34     
    35     private Person(int name){
    36         System.out.println(name);
    37     }
    38     
    39     public void eat(){
    40         System.out.println("eat!!!");
    41     }
    42     
    43     public void run(String address){
    44         System.out.println("跑到"+address);
    45     }
    46     
    47     public void run(String address,int num[],String ss[]){
    48         System.out.println("跑到"+address+"," +num);
    49     }
    50     
    51     public String test(String str){
    52         return str+"aaaaaa";
    53     }
    54     
    55     private String test2(String str){
    56         return str+"aaaaaa";
    57     }
    58     
    59     public static String test3(String str){
    60         return str+"aaaa";
    61     }
    62     
    63     
    64     public static void main(String[] args) {
    65         System.out.println(args[0]);
    66     }
    67 
    68 }

    如上就是反射所有常用的一些方法。

    心再坚强也不要独自飞翔
  • 相关阅读:
    Java基础教程:Java内存区域
    Java基础教程:多线程基础——线程池
    微服务实践:服务治理
    微服务实践:服务设计
    微服务实践:什么是微服务
    SpringBoot学习笔记:读取配置文件
    Java进阶教程:使用Lombok提升开发效率
    Sagas模式
    执行力:Just Do It
    执行力:Just Do It
  • 原文地址:https://www.cnblogs.com/LoganChen/p/6362820.html
Copyright © 2011-2022 走看看