Java中的反射

一,什么是反射

1,反射机制是在 运行状态 中:

对于任意一个类,都能知道这个类的所有属性和方法

对于任意一个对象,都能够调用它的任意一个方法和属性。

2,反射提供的功能:

在运行时判断任意一个对象所属的类

在运行时构造任意一个类的对象

在运行时判断任意一个类所具有的成员变量和方法

在运行时调用任意一个对象的方法

生成动态代理(动态代理底层用到了反射)

二,反射入口

1,获取反射对象(反射入口):就是拿到Class。有三种方法:

1.1,Class.forName("全类名");需要 包名+类名。需要处理异常

  Class<?> perClazz = Class.forName("sys.person");//推荐这种方式

  System.out.println(perClazz);

1.2,类名.class

  Class<?> perClazz = Person.class;

  System.out.println(perClazz);

1.3,对象.getClass();

  Person per = new Person();

  Class<?> perClazz = per.getClass(); //getClass()方法是object提供的

  System.out.println(perClazz);

 

2,获取公共的方法

  Class<?> perClazz = Class.forName("sys.person");

  Method[] methods = perClazz.getMethods();

  for(Method method : methods){

    System.out.print(method);

  }

打印结果:

public static void sys.Person.staticMethod()

pulic java.lang.String sys.Person.getName()

public final native void java.lang.Object.hashCode()

可以获取本类和父类(Object)中的public方法。

3,获取接口(多实现)

  Class<?> perClazz = Class.forName("sys.person");

  Class<?>[]  interfaces = perClazz.getInterface();

  for(Class<?> inter : interfaces){

    System.out.println(inter)

  }

打印结果(Person实现两个MyInterface,MyInterface2):

interface sys.MyInterface

interface sys.MyInterface2

4,获取所有父类(单继承)

  Class<?> perClazz = Class.forName("sys.person");  

  Class<?>  superClass= perClazz.getInterface();

  System.out.println(superClass);

打印结果:

class java.lang.Object

5,获取所有的构造方法

  Class<?> perClazz = Class.forName("sys.person");  

  Constructor<?>[] constructors = perClazz.getConstructors();

  for(Constructor constructor : constructors){

    System.out.println(constructor);

  }

打印结果:

public sys.Person(int,java.lang.String);//两个参数

public sys.Person(int);//一个参数

public sys.Person();//无参

 

6,获取所有的公共属性

  Class<?> perClazz = Class.forName("sys.person");

  Field[] fields = perClazz.getFields();

  for(Field field : fields){

    System.out.println(field);

  }

打印结果:

什么也没有,因为Person里定义的变量都是private的。

如果定义了public变量(public String title),反射才能获取到(public java.lang.String sys.Person.title)。

7,获取当前类的所有方法(要求:只能是当前类,并忽略访问修饰符限制)

  Class<?> perClazz = Class.forName("sys.person");

  Method[] declaredMethods = perClazz.getDeclaredMethods();

  for(Method method : declaredMethods){

    System.out.print(method);

  }

打印结果:

public java.lang.String sys.Person.getName()

private void sys.Person.privateMethod()

public static void sys.Person.staticMethod()

 

8,获取所有的属性(当前类,忽略访问修饰符)

  Class<?> perClazz = Class.forName("sys.person");

  Field[] fields = perClazz.getDeclaredFields();

  for(Field field : fields){

    System.out.println(field);

  }

打印结果:

private int sys.Person.id

private java.lang.String sys.Person.name

public java.lang.String sys.Person.title

 9,获取当前反射所代表类(接口)的对象

  Class<?> perClazz = Class.forName("sys.person");

  Object instance = perClazz.newInstance();

  Person per = (Person)instance;//强转

  per.interfaceMehthod();//调用方法

如果调用成功,说明instance就是Person对象

 

三,通过反射获取对象的实例,并操作对象

  Class<?> perClazz = Class.forName("sys.person");

  Person per = (Person)perClazz.newInstance();

  per.setId(1);

  per.setAge(22);

  System.out.println(per.getId() + " : "+ per.getAge());

可以打印出 id 和 age

四,通过反射获取对象的实例,操作属性

  Class<?> perClazz = Class.forName("sys.person");

  Person per = (Person)perClazz.newInstance();

  Field idField = perClazz.getDeclaredField(" id ");

  //现在要访问的是private修饰的id,但是private是私有的(私有的只能通过 public void setId()来访问),

  //但是我们通过反射还是想访问private int id 。所以,我们在操作属性之前,需要修改属性访问权限。

  //使用反射时,如果因为访问修饰符限制造成异常,可以通过setAccessible(true)来解决,同理操作私有方法也可以这样做

  idField.setAccessible(true);

  idField.set(per,1); // 相当于 ----->per.setId(1);

  System.out.println( per.getId() );

 

五,通过反射获取对象的实例,操作方法

  Class<?> perClazz = Class.forName("sys.person");

  Person per = (Person)perClazz.newInstance();

1,无参方法

  Method method = perClazz.getDeclaredMethod(" privateMethod ",null);//方法名:privateMethod,参数:null

  //操作方法私有方法时,把访问修饰符屏蔽掉

  method.setAccessible(true);

  method.invoke(per,null);//方法的调用:invoke

2,有参方法

  Method method2 = perClazz.getDeclaredMethod(" privateMethod2 ",String.class);//方法名:privateMethod2,参数:String类型

  method2.setAccessible(true);

  method2.invoke(per," 张三 ");//调用方法,并传参数

六,通过反射获取对象的实例,操作构造方法

1,获取本类全部构造方法(公有的,私有的构造方法都能拿到)

  Class<?> perClazz = Class.forName("sys.person");  

  Constructor<?>[] constructors = perClazz.getDeclaredConstructors();

  for(Constructor constructor : constructors){

    System.out.println(constructor);

  }

2,获取指定的构造方法(比如:public Person(int id){ this.id = id })

  Class<?> perClazz = Class.forName("sys.person");  

  Constructor<?> constructor = perClazz.getConstructor(int.class);

  System.out.println(constructor);

打印结果:

public sys.Person(int);

3,获取私有的构造方法

----->通过getDeclaredConstructor();获取。注意使用setAccessible(true)

七,

 

 

  

 

 

 

 

  

  

  

  

 

posted @ 2019-05-05 23:29  inspire0x001  阅读(176)  评论(0编辑  收藏  举报