Java之反射

Posted 嫩不嫩上天

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java之反射相关的知识,希望对你有一定的参考价值。

目录

1.什么是反射机制

2.反射机制有什么用

3.Class类对象的三种实例化模式

1.getClass()方法:

2.类.class

3.使用Class类提供的方法

4. 通过反射实例化对象

5.反射主要使用的种类

5.1Class类方法:

5.2Field类方法

5.3:Method方法


1.什么是反射机制

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

2.反射机制有什么用

     通过java语言中的反射机制可以操作字节码文件(可以读和修改字节码文件。)

     通过反射机制可以操作代码片段。(class文件。)

3.Class类对象的三种实例化模式

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

Class类对象的三种实例化模式:

以下分别举例实现: 

1.getClass()方法:

public final native Class<?> getClass()

范例:调用getClass()方法

import  java.util.Date;
public class test 
    public static void main(String[] args) 
        Date date=new Date();
        System.out.println(date.getClass());
    

结果:找到对应的类

2.类.class

范例:通过类名找对应的class 文件

import java.util.Date;

public class test 
    public static void main(String[] args) throws  Exception
        System.out.println(Date.class);

    

结果:

3.使用Class类提供的方法:public static Class forName(String className) throws ClassNotFoundException

范例:使用Class.forName()方法

package 反射;
import  java.lang.Class;
public class test 
    public static void main(String[] args) throws  Exception
        Class<?> date =Class.forName("java.util.Date");
        System.out.println(date);

    

结果:

4. 通过反射实例化对象

以上事例中可以看出除了getClass()方法会实例化对象之外,其他的俩种不会产生实例化对象,所以取得Class类对象的一个最直接的好处就是通过反射实例化对象该方法为:

对象.newInstance()

newInstance()方法内部实际上调用了无参数构造方法,必须保证无参构造存在才可以
否则会抛出java.lang.InstantiationException异常。

范例:

package 反射;
import  java.lang.Class;
import java.util.Date;

public class test 
    public static void main(String[] args) throws Exception
        //通过反射机制,获取Class,通过Class来实例化对象
        Class<?>  cl=Class.forName("java.util.Date");
        //newInstance() 这个方法会调用Date这个类的无参数构造方法,完成对象的创建。
        // 重点是:newInstance()调用的是无参构造,必须保证无参构造是存在的!
        Object object=cl.newInstance();
        System.out.println(object);

    

5.反射主要使用的种类

5.1Class类方法:

举例常见的几种方法:

1.获取类名

import 新特性.泛型.泛型接口.test;
public class demo 
    public static void main(String[] args) throws  Exception 
        Class<?> cl=test.class;
        System.out.println(cl.getName());
        System.out.println(cl.getSimpleName());
    

结果:

 2.获取类中的所有方法(重要)

import java.lang.reflect.Method;
import 新特性.泛型.泛型类方法.test;

public class getMethod 
    public static void main(String[] args) throws Exception 
        //通过反射机制,获取Class,通过Class来实例化对象
        Class<?> cl = test.class;
        //通过getMethods方法获取所有public修饰的普通方法
        Method[] methods = cl.getMethods();
        for (Method i : methods) 
            System.out.println(i.getName());
        
        System.out.println();
        //通过getDeclaredMethods返回类中所有的实例方法
        Method[] methods1 = cl.getDeclaredMethods();
        for (Method i : methods1) 
            System.out.println(i.getName());
        

    

5.2Field类方法

范例:

import java.lang.reflect.Field;

class Person
        public String name;
        public   int age;


class Student extends Person

     public String school;

public class getField 
        public static void main(String[] args)  throws  Exception
                Class<?> cl= Student.class;1

                Field[] fields=cl.getFields();
                //返回public修饰的所有属性
                for (Field field:fields)
                
                        System.out.println(field.getName());
                
                System.out.println();
                //返回本类中的所有属性
                Field[] fie=cl.getDeclaredFields();
                for (Field field:fie)
                
                        System.out.println(field.getName());
                
                //通过反射操作属性-----set/get方法
                Object obj=cl.newInstance();
                Field getFid=cl.getDeclaredField("school");
                getFid.set(obj,"华润希望小学");
                System.out.println(getFid.get(obj));

        

结果:

5.3:Method方法

重点getMethod()方法和invoke方法

范例:在有了反射机制处理之后,即使没有明确的Person类型对象(依然需要实例化对象,Object对象描述,所有 的普通方法必须在有实例化对象之后才可以进行调用)。就可以通过反射调用。通过反射去调用setter,getter方法

Method getMethod(String name,Class...parameterTypes)

name: method的名称

parameterTypes:method的参数类型的列表(参数顺序需按声明method时的参数列表排列)

返回:符合method名称和参数的method对象

抛出错误:NoSuchMethodException (没有找到所要查询的Method对象或Method名称为“<init>”或“<clinit>”) NullPointerException (所要查询的Method对象的名称为null) SecurityException(调用的类或其父类没有调用权限)

invoke方法:

作用:调用包装在当前Method对象中的方法。

原型:Object invoke(Object obj,Object...args) 参数解释:obj:实例化后的对象                args:用于方法调用的参数

返回:根据obj和args调用的方法的返回值

抛出错误:IllegalAccessException(Method对象强制Java语言执行控制或无权访问obj对象) IllegalArgumentException(方法是实例化方法,而指定需要调用的对象并不是实例化后的类或接口)

import java.lang.reflect.Method;
class Person

    private  String name;
    private  int age;
    private  String sex;

    public int getAge() 
        return age;
    

    public String getName() 
        return name;
    

    public String getSex() 
        return sex;
    
    public void setAge(int age) 
        this.age = age;
    

    public void setSex(String sex) 
        this.sex = sex;
    

    public void setName(String name) 
        this.name = name;
    



public class getMethod 
    public static void main(String[] args) throws Exception 
        //通过类名.class获取class对象
        Class<?> cl=Person.class;
        //实例划对象
        Object o=cl.newInstance();
        //通过getMethon方法取得setName这个方法的实例化对象,方法名称与参数类型
        Method setMethod=cl.getMethod("setName", String.class);
        //通过invoke调用方法
        setMethod.invoke(o,"wangyang");
        Method  getMethod=cl.getMethod("getName");
        Object result=getMethod.invoke(o);
        System.out.println(result);
    


此类操作的好处是:不再局限于某一具体类型的对象,而是可以通过Object类型进行所有类的方法调用。这个操作 必须掌握.

可参考Java反射(超详细!)_一只小菜鸡-CSDN博客_java反射

Java反射之剖析方法

继上篇反射构造函数后,今剖析函数方法。

  要通过反射执行方法:

  1、可以先反射出类或构造函数,创建实例对象,通过对象调用方法(反射通过构造函数创建对象参见上篇)。

  2、可以通过类反射出方法,传入关联对象,从而实现对象调用方法。

 

以下是一个简单测试类:

包含两个文件:

  1、Person.java,用于反射操作

  2、Deom:Demo_MtdRft.java,反射的测试代码

测试的情况包括:1、公有方法,2、私有方法,3、无参数方法,4、有参数方法,5静态方法

下面是两个测试代码文件:

Person.java

技术分享
  1 package cn.rt.gwq;
  2 
  3 import java.util.List;
  4 
  5 public class Person {
  6     
  7     public String value = "public  value";
  8     
  9     /**
 10      *无参数构造函数
 11      */
 12     public Person() {
 13         System.out.println("no params constructor");
 14     }
 15     
 16     /**
 17      * 一个参数的构造函数
 18      * @param name
 19      */
 20     public Person(String name) {
 21         System.out.println("string name constructor");
 22         value = "change the value : "+name;
 23     }
 24     
 25     /**
 26      * 一个参数的构造函数
 27      * @param age
 28      */
 29     public Person(int age) {
 30         System.out.println("int age constructor");
 31         value = "change the value : "+age;
 32     }
 33     
 34     /**
 35      * 多个参数的构造函数
 36      * @param usm
 37      * @param pwd
 38      */
 39     public Person(String usm,String pwd) {
 40         System.out.println("String usm,String pwd constructor");
 41         value = "change the value : "+usm +":"+pwd;
 42     }
 43     
 44     /**
 45      * 私有的构造函数
 46      * @param list
 47      */
 48     private Person(List list) {
 49         System.out.println("List constructor");
 50         value = "change the value : "+list.toArray().toString();
 51     }
 52     ////////
 53     
 54     
 55     
 56     
 57     
 58     
 59     
 60     
 61     ////////
 62     /**
 63      *无参数方法
 64      */
 65     public void eat(){
 66         System.out.println("eating soup...");
 67     }
 68     
 69     /**
 70      * 有参数方法
 71      * @param food
 72      */
 73     public void eat(String food){
 74         System.out.println(food + "is delicious...");
 75     }
 76     
 77     /**
 78      * 有返回值的方法
 79      * @param food
 80      * @return
 81      */
 82     public String eat(String name,String food){
 83         System.out.println(food + "is good,"+name+", try it.");
 84         return food;
 85     }
 86     
 87     /**
 88      * 私有方法
 89      */
 90     private void work(){
 91         System.out.println("I don‘t like to work.");
 92     }
 93     
 94     /**
 95      * 静态方法
 96      */
 97     public static void sleep(){
 98         System.out.println("I‘m sleeping ....");
 99     }
100     
101 
102 
103 }
Person.java

Demo_MtdRft.java

技术分享
  1 package cn.rt.gwq;
  2 
  3 import java.lang.reflect.Method;
  4 
  5 import org.junit.Test;
  6 
  7 /**
  8  * 反射方法的测试demo
  9  * @author Administrator
 10  *
 11  */
 12 public class Demo_MtdRft {
 13 
 14     /**
 15      * 反射没有参数的公开方法
 16      * @throws Exception
 17      */
 18     @Test
 19     public void test1() throws Exception{
 20         
 21         Person person = new Person();
 22         //加载类
 23         Class clazz = Class.forName("cn.rt.gwq.Person");
 24         //获取方法
 25         Method method = clazz.getMethod("eat", null);
 26         //执行方法
 27         method.invoke(person, null);
 28         
 29         return;
 30         
 31     }
 32     
 33     /***
 34      * 反射带一个参数的方法
 35      * @throws Exception
 36      */
 37     @Test
 38     public void test2() throws Exception{
 39         
 40         Person person = new Person();
 41         
 42         Class clazz = Class.forName("cn.rt.gwq.Person");
 43         Method method = clazz.getMethod("eat", String.class);
 44         method.invoke(person, "fish");
 45         
 46         return;
 47         
 48     }
 49     
 50     /***
 51      * 反射有返回值的方法
 52      * @throws Exception
 53      */
 54     @Test
 55     public void test3() throws Exception{
 56     
 57         Person person = new Person();
 58         
 59         Class clazz = Class.forName("cn.rt.gwq.Person");
 60         Method method = clazz.getMethod("eat", String.class,String.class);
 61         String food = (String) method.invoke(person, "tom","fish");
 62         System.out.println("food :"+food);
 63         
 64         return;
 65         
 66     }
 67     
 68     /**
 69      * 反射私有方法
 70      * @throws Exception
 71      */
 72     @Test
 73     public void test4() throws Exception{
 74         
 75         Person person = new Person();
 76         
 77         Class clazz = Class.forName("cn.rt.gwq.Person");
 78         //获取私有方法
 79         Method method = clazz.getDeclaredMethod("work", null);
 80         //强制在类外可自执行
 81         method.setAccessible(true);
 82         //执行
 83         method.invoke(person, null);
 84         
 85         return;
 86         
 87     }
 88     
 89     /**
 90      * 反射静态方法
 91      * @throws Exception
 92      */
 93     @Test
 94     public void test5() throws Exception{
 95         
 96         Person person = new Person();
 97         
 98         Class clazz = Class.forName("cn.rt.gwq.Person");
 99         //也可以用getMethod方法获取
100         Method method = clazz.getDeclaredMethod("sleep", null);
101         method.setAccessible(true);
102         method.invoke(person, null);
103         
104         return;
105         
106     }
107     
108         
109 }
Demo_MtdRft.java

 

以上是关于Java之反射的主要内容,如果未能解决你的问题,请参考以下文章

系统开发系列 之java反射以及应用

Java之反射 — 用法及原理

Java进阶之reflection(反射机制)——反射概念与基础

Java进阶之reflection(反射机制)——反射概念与基础

Java后端总结

Java 高级开发必修知识---反射