反射

参考这几篇博文 

点击打开链接    点击打开链接2  点击打开链接3   点击打开链接4


反射机制,对于任何一个类(.class文件),能够知道这个类的所有属性和方法,对于任何一个对象,都能调用他的任一个方法和属性

也就说通过字节码文件去获取其中的类信息 ,所以必须先获得字节码对象

public class Person {
    int age;
    String name;
    
	public Person() {
		super();
		System.out.println("person run");
	}
	public Person(int age, String name) {
		super();
		this.age = age;
		this.name = name;
		System.out.println("person param run...."+this.name+" : "+this.age);
	}
	
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	public void show(){
		System.out.println(name+" .... "+age);
	}
	public  void  method(){
		System.out.println(" method run ");
	}
	public void paramMethod(String str,int num){
		System.out.println("paramMethod run....."+str+" : "+num);
	}
	public static void staticMethod(){
		System.out.println("static method run......");
	}
}


1.获取类对象

3种方法,第三种最为好用、常见,注意类名要带上包名

public class MyReflectDemo {
  
	public static void main(String[] args) throws ClassNotFoundException {
		getClassObject_1();
		getClassObject_2();
		getClassObject_3();
  }
	
	/*
	 * 1.object类里的getclass方法
	 * 必须明确具体的类,并创建对象,麻烦
	 */
	
	public  static void getClassObject_1(){
		Person p =new Person();
		Class clazz = p.getClass();
		
		Person p1 = new Person();
		Class clazz1 = p1.getClass();
		
		System.out.println(clazz==clazz1);
	}
	/*
	 * 2.任何数据类型都具备一个静态属性 .class来获取class对象
	 * 相对简单,但是还是要用到类中的静态成员,不够扩展
	 */
	public  static void getClassObject_2(){
		Class clazz = Person.class;
		Class clazz2 = Person.class;
		System.out.println(clazz == clazz2);
	}
	/*
	 * 3.只要一个类的字符串名即可,最方便
	 * 用class类中的方法forName()
	 * 这里必须带包名,不能直接用类名的字符串
	 */
	public  static void getClassObject_3() throws ClassNotFoundException{
		String className = "bean.Person";
		Class clazz = Class.forName(className);
		System.out.println(clazz);
	}
}

person run
person run
true
true
class bean.Person

可以看到,前两个还是调用了构造函数


2.获取构造函数,newInstance()方法

public class MyReflectDemo2 {
   public static void main(String[] args) {
	   /*
	    * 这样写无需导包,早期的写法
	    * 要根据被new的对象找到做这个类的字节码文件加载到内存
	    * 再创建字节码文件的对象,以及该字节码文件对应的类的对象
	    */
	   /*bean.Person p = new bean.Person();*/
	   
	   String name = "bean.Person";
	   Class clazz;
	try {
		//直接找到类文件加载到内存,并产生字节码文件的对象
		clazz = Class.forName(name);
		//通过newInstance方法产生类的对象
		Object obj = clazz.newInstance();
	} catch (ClassNotFoundException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}catch (InstantiationException | IllegalAccessException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
   }
}
person run

Person类里面必须有public的无参构造函数,没有的话会提示无法初始化,private会提示无法调用

当要调用的类对象没有无参构造时,先拿到一个构造器

public  static  void createNewObject2() {
	  /* bean.Person p = new bean.Person(40,"小强");*/
	   /*
	    * 当没有无参构造函数时,怎搞
	    * getConstructor(参数类型)
	    */
	   String name = "bean.Person";
	   Class clazz;
	try {
		//找到文件加载进内存,产生字节码文件对象
		clazz = Class.forName(name);
		//获取指定构造函数对象
		Constructor cons = clazz.getConstructor(int.class,String.class);
	    //通过构造器的newInstance()方法初始化
		Object obj = cons.newInstance(20,"小明");
	} catch (ClassNotFoundException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}catch (NoSuchMethodException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (SecurityException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (InstantiationException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (IllegalAccessException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (IllegalArgumentException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (InvocationTargetException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
   }
person param run....小明 : 20


3.获取字段

若是私有字段,需要设置下

public class MyReflectDemo3 {
    public static void main(String[] args) {
    	getFieldDemo();
	}

	private static void getFieldDemo() {
		// TODO Auto-generated method stub
		Class clazz;
		Field field;
		try {
			clazz = Class.forName("bean.Person");
			/*//只能获取公有的
			field = clazz.getField("age");*/
			//获取本类所有字段,包含私有
			field = clazz.getDeclaredField("age");
			//若私有,对私有字段的访问取消权限检查,暴力访问
			field.setAccessible(true);
			//找字段需要先找到对象
			Object obj = clazz.newInstance();
			field.set(obj, 89);
			//通过这个对象去找字段,返回的也是对象
			Object o = field.get(obj);
			
			System.out.println(o);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

person run
89

4.方法

所有方法

指定方法

带参方法

public class MyReflectDemo4 {
   public static void main(String[] args) {
	   getMethodDemo();
	   getMethodDemo2();
	   getMethodDemo3();
   }
   //获取所有公共方法
   private static void getMethodDemo() {
	   // TODO Auto-generated method stub
	  try {
		Class clazz = Class.forName("bean.Person");
		Method[] methods = clazz.getMethods();
		methods = clazz.getDeclaredMethods();
		for (Method method:methods) {
			System.out.println(method);
		}
	} catch (ClassNotFoundException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	  
   }
   //获取指定方法
   private static void getMethodDemo2(){
	   Object obj;
	   try {
			Class clazz = Class.forName("bean.Person");
			Method method = clazz.getMethod("show", null);
			//运行一个方法需要对象和参数
			Constructor cons = clazz.getConstructor(int.class,String.class);
			obj = cons.newInstance(26,"小明");		
			method.invoke(obj, null);
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}catch (ClassNotFoundException | NoSuchMethodException | SecurityException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}	   
   }
   //获取带参方法
   private static void getMethodDemo3(){
	   try {
		Class clazz = Class.forName("bean.Person");
		Method method = clazz.getMethod("paramMethod",String.class, int.class);
		Object obj = clazz.newInstance();
		method.invoke(obj,"小强",89);
	} catch (ClassNotFoundException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (NoSuchMethodException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (SecurityException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (IllegalAccessException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (IllegalArgumentException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (InvocationTargetException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (InstantiationException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
   }
}
<pre name="code" class="plain">public void bean.Person.method()
public void bean.Person.show()
public void bean.Person.paramMethod(java.lang.String,int)
public int bean.Person.getAge()
public void bean.Person.setAge(int)
public static void bean.Person.staticMethod()
person param run....小明 : 26
小明 .... 26
person run
paramMethod run.....小强 : 89

类的生命周期

在一个类编译完成之后,下一步就需要开始使用类,如果要使用一个类,肯定离不开JVM。在程序执行中JVM通过装载,链接,初始化这3个步骤完成。


类的装载是通过类加载器完成的,加载器将.class文件的二进制文件装入JVM的方法区,并且在堆区创建描述这个类的java.lang.Class对象。用来封装数据。


链接就是把二进制数据组装为可以运行的状态。 

链接分为校验,准备,解析这3个阶段

校验一般用来确认此二进制文件是否适合当前的JVM(版本),

准备就是为静态成员分配内存空间,。并设置默认值

解析指的是转换常量池中的代码作为直接引用的过程,直到所有的符号引用都可以被运行程序使用(建立完整的对应关系)


完成之后,类型也就完成了初始化,初始化之后类的对象就可以正常使用了,直到一个对象不再使用之后,将被垃圾回收。释放空间。


当没有任何引用指向Class对象时就会被卸载,结束类的生命周期


反射一般是给设计框架的人用的,因为他需要先搭架子,但具体要操作的对象是什么还不知道,所以要用反射来做。



                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值