反射

反射

反射【剖析】类的手术刀,获取类的一切资源。
类的资源如下:
          属性
          构造器
          方法

获取属性之后可以做什么? 1.获取值  2.赋值
获取构造器之后可以做什么? 1.将对象实例化
获取方法之后可以做什么? 1.调用该方法

反射的真正意义:在知道类路径的情况下,去获取类的资源
        目标:反射的目标和我们类的实例化是一样的  访问的规则
        方式不一样
        入侵类 剖析 可以使用私有的方法 
        
class Person{
    private int pid;
    private String pname;
    private char  psex;

    private Person(int pid,String pname,char psex)
    {
    this.pid=pid;
    this.pname=pname;
    this.psex=psex;
    }
    
    public Person()
    {
     
    }
    
    private void sayHello()
    {
    
    }
    
    private static void doSomething()
    {
    
    }
    

}

反射的概念

把某个资源变成Class的过程,我们称为叫做反射。
3种反射的方式
1.将对象变成Class
Person p=new Person();
Class clz=p.getClass(); //getClass() 1.查看真实的类对象 2.反射方法获取Class对象

2.将类变成Class
Class clz=Person.class; //class不是一个方法

3.使用Class类的静态方法 获取Class对象
Class clz=Class.forName("类路径") 

4.获取该类的所有构造器
Constructor[] constructors = clz.getConstructors(); //获取所有的public的构造器
Constructor[] constructors = clz.getDeclaredConstructors(); //获取所有的构造器
通过特征获取单个构造器 【根据构造器的参数类型来区分不同的构造器】
Constructor c=clz.getDeclaredConstructor(int.class,String.class,char.class);
实例化 newInstance(),实例化的时候根据调用构造器不同 传入相应的实参
如果当前的构造器是私有的,我们无法去使用。
c.setAccessible(true); //之前暴力授权
Object o=c.newInstance(1,"张三”,'女’); //以多态的方式获取到我们对象

5.获取该类的属性
Field[] fields= clz.getFields(); //获取所有的public的属性
Field[] fields = clz.getDeclaredFields(); //获取所有的属性
通过属性名和特征获取单个属性
Field pname=clz.getDeclaredField("pname");
要获取属性的值 要先实例化  
如果说当前的属性是私有的,我们无法使用
pname.setAccessible(true); // 需要在实例化之前暴力授权
一般对属性的操作 就是获取值 和 设置值 
Object value=pname.get(o); //这里o表示实例化的对象  value是以多态的方式获取的
pname.set(o,"张三"); //这里o表示实例化的对象 "张三"表示我们要传递实参

6.获取该的方法
Method[] methods= clz.getMethods(); //获取所有的public的方法
Method[] methods = clz.getDeclaredMethods(); //获取所有的属性
通过方法名和特征获取单个方法
Method sayhello=clz.getDeclaredMethod("sayHello",null); //方法没有参数 填写null值
如果该方法是私有
sayhello.setAccessible(true); // 之前暴力授权
使用invoke方法来执行该方法 有返回值你可以接受 如果方法的返回值类型是void 那么会返回Void类 
Object result=sayhello.invoke(o,null); //第一个参数是对象
静态方法的调用
Method doSomething=clz.getDeclaredMethod("doSomething",null); //方法没有参数 填写null值
Object result=doSomething.invoke(null,null); //因为我是一个静态方法 所以可以将第一个参数设置为null

7.注解标注在类,方法,全局变量的上面
  1.特殊的意义
  2.存放一些数据
@Target(value={ElementType.TYPE,ElementType.METHOD,ElementType.FIELD,ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
public @interface Hello
{
      int id() default 1;
	  String name() default " ";	
}
@Target 表示可以使用在哪些资源上
@Retention 表示在什么时候有效 如果我们想要在反射的时候去解析 一定要设置为 RetentionPolicy.RUNTIME

使用反射获取类上的注解
@Hello(id=51,name="冉益")
public class Person
{
	
	@Hello(id=52,name="冉益2")
	int pid;
	
	@Hello(id=53,name="冉益3")
	public Person()
	{
		// TODO Auto-generated constructor stub
	}

	@Hello(id=54,name="冉益4")
	public void sayHello()
	{
		
	}	
}
//获取类上面的注解
  Class clz=Person.class;
  Hello hello=clz.getDeclaredAnnotation(Hello.class);
  hello.id();
  hello.name();
  
//获取属性上的注解信息
  Field pid=clz.getDeclaredFiled("pid");
  Hello hello=pid.getDeclaredAnnotation(Hello.class);
  hello.id();
  hello.name();
  
//获取构造器上的注解信息  
Constructor c = clz.getDeclaredConstructor(null);
Hello declaredAnnotation = c.getDeclaredAnnotation(Hello.class);
System.out.println(declaredAnnotation.id());
System.out.println(declaredAnnotation.name());
  
//获取方法上面的注解信息
Method sayHello=clz.getDeclaredMethod("sayHello", null);
Hello declaredAnnotation2 = sayHello.getDeclaredAnnotation(Hello.class);
System.out.println(declaredAnnotation2.name());
System.out.println(declaredAnnotation.id());

posted @ 2020-06-10 21:34  幻世纪  阅读(111)  评论(0)    收藏  举报