反射

Java让我们在运行时识别对象和类的信息,主要有2种方式:一种是传统的RTTI(running-time type infomation ),它假定我们在编译时已经知道了所有的类型信息;另一种是反射机制,它允许我们在运行时发现和使用类的信息。

反射机制允许程序在运行时取得任何一个已知名称的class的内部信息,包括包括其modifiers(修饰符),fields(属性),methods(方法)等,并可于运行时改变fields内容或调用methods。

Java动态代理可以在不改变被调用对象源码的前提下,在被调用方法前后增加自己的操作,极大地降低了模块之间的耦合性。

获取class的三种方法:

1、通过对象调用 getClass() 方法来获取,通常应用在:比如你传过来一个 Object类型的对象,而我不知道你具体是什么类,用这种方法
  Person p1 = new Person();
  Class c1 = p1.getClass();
          
2、直接通过 类名.class 的方式得到,该方法最为安全可靠,程序性能更高这说明任何一个类都有一个隐含的静态成员变量 class

Class c2 = Person.class; 3、通过 Class 对象的 forName() 静态方法来获取,用的最多, 但可能抛出 ClassNotFoundException 异常 Class c3 = Class.forName("com.ys.reflex.Person");

通过反射创建对象:

 1.通过默认构造函数创建对象:Class<?> t = Class.forName("cn.test.reflect.A"); t.newInstance();

 2. 通过指定构造函数创建对象:Class<?> t = Class.forName("cn.test.reflect.A"); Constructor<?> cons[] = t.getConstructors(); A a = (A) cons[2].newInstance("aa","bb");

 

通过Class来获取成员变量,方法等

1.获得类完整的名字
  String className = c2.getName();
  System.out.println(className);         //输出com.ys.reflex.Person
          
2.获得类的public类型的属性。
  Field[] fields = c2.getFields();
  for(Field field : fields){
     System.out.println(field.getName());//age
  }
         
3.获得类的所有属性。包括私有的
 Field [] allFields = c2.getDeclaredFields();
 for(Field field : allFields){
     System.out.println(field.getName());//name    age
 }

通过反射获取父类的信息(私有信息)

public class Parent {
    public String publicField = "parent_publicField";
    protected String protectField = "parent_protectField";
    String defaultField = "parent_defaultField";
    private String privateField = "parent_privateField";

}
public class Son extends Parent {
 }

public class ReflectionTest {

    public void testGetParentField() throws Exception{
        Class c1 = Class.forName("com.ys.model.Son");
        //获取父类私有属性值
        System.out.println(getFieldValue(c1.newInstance(),"privateField"));
    }

    public static Field getDeclaredField(Object obj,String fieldName) {
        Field field = null;
        Class c = obj.getClass();
        for(; c != Object.class ; c = c.getSuperclass()){
            try {
                field = c.getDeclaredField(fieldName);
//只有变为true,才能通过反射访问私有变量 field.setAccessible(true); return field; }catch (Exception e){ //这里甚么都不要做!并且这里的异常必须这样写,不能抛出去。 //如果这里的异常打印或者往外抛,则就不会执行c = c.getSuperclass(),最后就不会进入到父类中了 } } return null; } public static Object getFieldValue(Object object,String fieldName) throws Exception{ Field field = getDeclaredField(object,fieldName); return field.get(object); } } 

java里面可以通过反射获得方法参数名字和类型。

通过反射调用类里面的方法:

http://www.apigo.cn/2018/11/27/javacore6/

posted @ 2018-12-10 21:47  LeeJuly  阅读(135)  评论(0)    收藏  举报