今天来学习一下Java的反射机制,若有不当请多指教!学习
反射机制是在运行状态中,对于任意一个类,都可以知道这个类的全部属性和方法;对于任意一个对象,都可以调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。code
Java中的反射主要和Class
类有关。Class类没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及经过调用类加载器中的defineClass方法自动构造的。也就是说不须要咱们本身去处理建立,JVM已经帮咱们建立好了。对象
一、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); } }
固然这样只能躲过编译器检查,去遍历的话仍是会抛出异常的。编译