浅谈Java反射

今天来学习一下Java的反射机制,若有不当请多指教!学习

概述

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

Java中的反射主要和Class类有关。Class类没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及经过调用类加载器中的defineClass方法自动构造的。也就是说不须要咱们本身去处理建立,JVM已经帮咱们建立好了。对象

反射的使用

获取Class对象

一、getClass()

getClass()是Object类中的方法,也就是说每一个类都有本身的Class对象。字符串

Student s1 = new Student();//这一new 产生一个Student对象,一个Class对象。
Class stuClass1 = s1.getClass();

二、.class

任何数据类型(包括基本数据类型)都有一个“静态”的class属性,好比String.Classget

Class stuClass2 = Student.class;

三、Class.forName(String className) —— 推荐

经过Class类的静态方法forName获取Class对象(经常使用)编译器

Class stuClass3 = Class.forName("czy.Student");//注意此字符串必须是真实路径→包名.类名

注意:在运行期间,一个类,只有一个Class对象产生。虚拟机

获取构造方法

public class Constructors {
 
    public static void main(String[] args) throws Exception {
        //1.加载Class对象
        Class c = Class.forName("czy.Student");
        
        //2.获取全部公有构造方法
        Constructor[] conArray = c.getConstructors();
    
        //三、获取全部的构造方法(包括:私有、受保护、默认、公有)
        Constructor[] conArray = c.getDeclaredConstructors();
        
        //四、获取公有、无参的构造方法
        Constructor con = c.getConstructor();
        //由于是无参的构造方法因此类型是一个null,不写也能够:这里须要的是一个参数的类型,切记是类型
        //调用构造方法
        Object obj = con.newInstance();
        
        //五、获取私有构造方法,并调用
        con = c.getDeclaredConstructor(char.class);
        //调用构造方法
        con.setAccessible(true);//暴力访问(忽略掉访问修饰符)
        obj = con.newInstance('男');
    }    
}

获取成员变量

public class Fields {
 
        public static void main(String[] args) throws Exception {
            //一、获取Class对象
            Class stuClass = Class.forName("czy.Student");
   
            //二、获取全部公有的字段
            Field[] fieldArray = stuClass.getFields();
            
            //三、获取全部的字段(包括私有、受保护、默认的)
            Field[] fieldArray = stuClass.getDeclaredFields();
            
            //四、获取公有字段"name"并调用
            Field f = stuClass.getField("name");
             //获取一个对象
            Object obj = stuClass.getConstructor().newInstance();//产生Student对象--》Student student = new Student();
             //为字段设置值
            f.set(obj, "刘德华");//为Student对象中的name属性赋值--》student.name = "刘德华"
            
            //五、获取私有字段"phone"并调用
            f = stuClass.getDeclaredField("phone");
            f.setAccessible(true);//暴力反射,解除私有限定
            f.set(obj, "13415038974");
        }
    }

获取成员方法

public class MethodClass {
 
    public static void main(String[] args) throws Exception {
        //1.获取Class对象
        Class stuClass = Class.forName("czy.Student");
  
        //2.获取全部公有方法
        Method[] methodArray = stuClass.getMethods();
    
        //3.获取全部的方法,包括私有的
        Method[] methodArray = stuClass.getDeclaredMethods();
        
        //4.获取公有的show1()方法
        Method m = stuClass.getMethod("show1", String.class);
        //调用show1()方法
        Object obj = stuClass.getConstructor().newInstance();
        m.invoke(obj, "刘德华");
        
        //5.获取私有的show4()方法
        m = stuClass.getDeclaredMethod("show4", int.class);
        m.setAccessible(true);//解除私有限定
        Object result = m.invoke(obj, 20);//须要两个参数,一个是要调用的对象(由反射获取),一个是实参
    }
}

反射的其它用法

经过反射越过泛型检查

例如:有一个String泛型的集合,怎样能向这个集合中添加一个Integer类型的值?io

public class Demo {
   public static void main(String[] args) throws Exception{
            ArrayList<String> strList = new ArrayList<>();
            strList.add("aaa");
            strList.add("bbb");
        
            //获取ArrayList的Class对象,反向的调用add()方法,添加数据
        Class intClass = strList.getClass(); //获得 strList 对象的字节码 对象
        //获取add()方法
        Method m = intClass.getMethod("add", Object.class);
        //调用add()方法
        m.invoke(strList, 100);
    }
}

固然这样只能躲过编译器检查,去遍历的话仍是会抛出异常的。编译

相关文章
相关标签/搜索