一、概念
java加载class文件分两种情况:
(1)类型是编译器已知的,这种文件的.class文件在编译的时候,编译器会把.class文件打开(不加载)检查,称为Run- Time Type Identification 运行时类型识别
(2)从其它地方获取引用,然后动态的把这个未知类型的引用的对象的.class文件加载进jvm虚拟机里,称为反射;
在运行状态中,动态获取类信息(属性、方法)及动态调用类对象方法的功能称为java的反射机制。
二、反射API
Java反射包:java.lang.reflect.*
1、获取类
首先获取类,获取到类之后,Class类提供了很多获取类属性,方法,构造方法的api
(1)obj.getClass(),这个是Object类里面的方法;
(2)User.Class属性,任何的数据类型,基本数据类型或者抽象数据类型,都可以通过这种方式获取类;
(3)Class.forName(""),Class类提供了这样一个方法,让我们通过类名来获取到对象类,使用最多;
package reflect; import reflect.test.model.User; public class Main { public static void main(String[] args) throws ClassNotFoundException { //1.通过Object类里面的方法getClass() User u = new User(); Class c = u.getClass(); System.out.println(c);//class reflect.test.model.User //2通过.Class属性 Class c2 = User.class; System.out.println(c2);//class reflect.test.model.User //3.Class.forName("全路径名") Class c3 = Class.forName("reflect.test.model.User"); System.out.println(c3);//class reflect.test.model.User } }
2、获取属性和方法
package reflect.test.model; public class User { private String name; private int age; public User() {} public User(String name,int age) { this.name = name; this.age = age; } public int a = 100; private String str = "123456789"; public boolean dosomething(Integer a,Float b) { System.out.println("dosomething"); return true; } }
package reflect; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; public class Main2 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException { /************************获取所有的属性************************/ Class<?> c = Class.forName("reflect.test.model.User"); //getDeclaredFields 获取所有的属性 Field[] fs = c.getDeclaredFields(); // 定义可变长的字符串,用来存储属性 StringBuffer sb = new StringBuffer(); // 通过追加的方法,将每个属性拼接到此字符串中 // 最外边的public定义 sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() + "{\n"); // 里边的每一个属性 for (Field field : fs) { sb.append("\t");// 空格 sb.append(Modifier.toString(field.getModifiers()) + " ");// 获得属性的修饰符,例如public,static等等 sb.append(field.getType().getSimpleName() + " ");// 属性的类型的名字 sb.append(field.getName() + ";\n");// 属性的名字+回车 } sb.append("}"); System.out.println(sb); /***************************获取指定属性***********************/ //获取id属性 Field idF = null; try { idF = c.getDeclaredField("age"); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } //实例化这个类赋给o Object o = null; try { o = c.newInstance(); } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); } //打破封装 idF.setAccessible(true); //使用反射机制可以打破封装性,导致了java对象的属性不安全。 //给o对象的id属性赋值"110" try { //set idF.set(o,110); } catch (IllegalArgumentException | IllegalAccessException e) { e.printStackTrace(); } //get try { System.out.println(idF.get(o)); } catch (IllegalArgumentException | IllegalAccessException e) { e.printStackTrace(); } /***************************获取方法****************************/ //getDeclaredMethods() 获取所有的方法(不包含构造方法) Method[] declaredMethods = c.getDeclaredMethods(); for (Method m:declaredMethods) { System.out.println(m); //getReturnType() 获得方法的放回类型 System.out.println(m.getReturnType()); //getParameterTypes() 获得方法的传入参数类型 Class<?>[] parameterTypes = m.getParameterTypes(); for(Class cc : parameterTypes) { System.out.println(cc); } } //getDeclaredMethod("方法名",参数类型.class,……) 获得特定的方法 Method declaredMethod = c.getDeclaredMethod("dosomething", Integer.class,Float.class); System.out.println(declaredMethod); Method method = c.getMethod("dosomething", Integer.class,Float.class); System.out.println(method); //getDeclaredConstructors() 获取所有的构造方法 Constructor<?>[] declaredConstructors = c.getDeclaredConstructors(); for(Constructor ccc : declaredConstructors) { System.out.println(ccc); } //getDeclaredConstructor(参数类型.class,……) 获取特定的构造方法 Constructor<?> declaredConstructor = c.getDeclaredConstructor(String.class,int.class); System.out.println(declaredConstructor); //getSuperclass() 获取某类的父类 Class<?> superclass = c.getSuperclass(); System.out.println(superclass); //getInterfaces() 获取某类实现的接口 Class<?>[] interfaces = c.getInterfaces(); for(Class cccc: interfaces) { System.out.println(cccc); } } }
结果:
public class User{ private String name; private int age; public int a; private String str; } 110 public boolean reflect.test.model.User.dosomething(java.lang.Integer,java.lang.Float) boolean class java.lang.Integer class java.lang.Float public boolean reflect.test.model.User.dosomething(java.lang.Integer,java.lang.Float) public boolean reflect.test.model.User.dosomething(java.lang.Integer,java.lang.Float) public reflect.test.model.User() public reflect.test.model.User(java.lang.String,int) public reflect.test.model.User(java.lang.String,int) class java.lang.Object
三、反射应用--动态代理