java反射机制

这是以前看了毕向东老师的视频所做的笔记,刚开始还是有点不理解,不过一两年再回头看看,其实自己做的笔记好像自己看的很有意思。(废话)

这里https://how2j.cn/p/3955有完整的java学习路线,小伙伴可以到这里学习

先看下面这幅图吧,看到什么

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

 

一个类有多个组成部分,例如:成年变量,方法,构造方法等。反射就是加载类,并解剖出类的各个组成部分。

反射技术一般用于框架中的获取,比如某个程序已经做好运行了,不可能再进行源代码的更改,此时想添加功能或修改,则我们自己写的代码怎么能放进去呢,这时就用到反射技术进行解剖类和方法,把我们的代码放进去。

 

编程时什么情况下才需要加载类,并解剖出类的各个组成部分呢?

比如:我们已经弄好了一个项目,那么项目里面的接口都是已经封装好的了 ,我们不可以直接调用里面的属性或方法,那么这时就用到反射了

 

java中有一个Class类用于代表某一个类的字节码。

Class类既然代表某个类的字节码,它当然就要提供加载某个类字节码的方法:

       forName();forName方法用于加载某个类的字节码到内存中,并使用class对象进行封装。

另外两种得到class对象的方式

           类名.class

          对象.getClass()

 

//反射,加载类 获得类的字节码
public class Demo1 {
	public static void main(String[] args) throws ClassNotFoundException{
		//1
		Class clazz=Class.forName("cn.itcast.demo.Demo4");
		//2
		Class clazz1=new Demo4().getClass();
		//3
		Class clazz2=Demo4.class;
	}

}

 

 

package cn.itcast.bean;
/*java反射机制是在运行状态中,对于任意一个类(class文件),都能够
 * 知道这个类的所有属性和方法。
 * 这种动态获取的信息,就是java反射。
 * 可以理解为对类的解剖。
 * 
 * 要想要对字节码文件进行解剖,必须要有字节码文件对象。
 * 如何让获取字节码文件对象呢?
 * 
 * 
 * */
 
public class ReflectDemo {
	public static void main(String[] args) throws ClassNotFoundException {
		getClassObject_3();

	}
	/*方式3:
	 * 只要通过给定类的字符串名称就可以获取该类,更为扩展。
	 * 可以用Class类中的方法完成。
	 * 该方法就是forName
	 * 这种方式只要有名称即可,更为方便,扩展性更强。
	 * */
	public  static void getClassObject_3() throws ClassNotFoundException {
		String className="cn.itcast.been.Person";
		Class clazz=Class.forName(className);
		System.out.println(clazz);		
	}
	/*方式2:
	 * 2.任何数据类型都具备一个静态的属性.class来获取其对应的class对象。
	*相对简单,但是还是需要明确用到类中的静态成员。
	*还是不够扩展。
	*/
	private static void getClassObject_2() {
		Class clazz=Person.class;
		Class clazz1=Person.class;
		System.out.println(clazz==clazz1);		
	}	
	/*获取字节码对象的方式:
	 *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);
	}

}

 

package cn.itcast.bean;

public class Person {
	private int age;
	private String name;
	public Person(int age, String name) {
		super();
		this.age = age;
		this.name = name;
		System.out.println("Person param run..."+this.name+":"+this.age);
	}
	public Person(){
		super();
		System.out.println("person run");
	}
	public void show(){
		System.out.println(name+"...show run..."+age);
	}
	private 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...");
	}
}

 

Class对象提供如下常用方法:                                                                                                                                      

public   Constructor getConstructor(Class<?>...parameterTypes):获取字节码

public   Method getMethod (Stringname.Class<?>...parameterTypes):获取方法

public   Field getField (String name):获取字段)

Declared(可以拿类中的所有内容包括私有的)

public  Constructor getDeclaredConstructor(Class...parameterTypes)

public  Method getDeclaredMethod (Stringname.Class...parameterTypes)

public  Field getDeclaredField (String name)

这些方法分别用于从类中解剖出构造函数、方法、成员变量(属性)。

解剖出的成员分别使用Constructor、Method、Field对象表示。

思考:假设你是一个框架的设计者,解剖出这些成员你会干什么?

反射类的构造函数                                                                                                                                                               

利用Constructor创建对象

Constructor类提供了如下方法,用于创建类的对象:

       public Object newInstance(Object...initargs)

       initargs用于指定构造函数接收的参数

练习:反射类无参、有参、私有的构造函数,创建类的对象。

多学一招:sun公司为简化开发人员创建对象,它在class对象中也提供了一个newInstance方法,用于创建类的对象。这样开发人员可以避免每次都需要去反射Constructor类创建对象。

 不过需要注意的是:class.newInstance方法内部是反射类无参的构造函数创建对象,所以利用此种方式创建类对象时,类必须有一个无参的构造函数。

反射类的方法                                                                                                                                                                        

利用Method执行方法

Method对象提供 了如下方法,用于执行它所代表的方法。

         public Object invoke(Objectobj,Object...args)

练习:使用Method分别执行无参、有参、多个参(带数组和基本数据类型)、静态、私有的方法。

jdk1.4和jdk1.5的invoke方法的区别:

jdk1.5:public  Object  invoke(Object obj,Object...args)

jdk1.4:public  Object  invoke(Object obj,Object[]...args)

反射机制(获取Class中的构造函数)

package cn.itcast.bean;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class ReflectDemo2 {
	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
		createNewObject_2();

	}
	public static void createNewObject_2() throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
//		cn.itcast.bean.Person p=new cn.itcast.bean.Person(39,"小强");
		/*
		 * 当获取指定名称对应类中的所体现的对象时,
		 * 而该对象初始化不使用空参数构造该怎么办呢?
		 * 既然是通过指定的构造函数 进行对象的初始化,
		 * 所以应该先获取到该构造函数。了、通过字节码文件对象即可完成。
		 * 该方法是:getConstructor(paramterTypes)
		 * */
		String name="cn.itcast.bean.Person";
		Class clazz=Class.forName(name);
		Constructor constructor=clazz.getConstructor(String.class,int.class);
		//通过该构造器对象的newInstance方法进行对象的初始化。
		Object obj=constructor.newInstance("小明",38);
	}
	public static void createNewObject()throws ClassNotFoundException, InstantiationException, IllegalAccessException{
		//早期:new 的时候,先根据new的类的名称寻找该类的字节码文件,并加载进内存,
		//并创建该字节码文件对象,并接着创建该字节码文件的对应的Person对象。
		//cn.itcast.bean.Person p=new cn.itcast.bean.Person();
		
		//现在
		String name="cn.itcast.bean.Person";
		//寻找该名称类文件,并加载进内存,并产生Class对象。
		Class clazz=Class.forName(name);
		//如何产生该类的对象呢?
		Object obj=clazz.newInstance();
	}

}

反射机制(获取Class中的字段)

 

 

 

package cn.itcast.bean;

import java.lang.reflect.Field;

public class ReflectDemo3 {
	public static void main(String[] args) throws SecurityException, NoSuchFieldException, ClassNotFoundException, InstantiationException, IllegalAccessException {
		getFiledDemo();
	}
	public static void getFiledDemo() throws SecurityException, NoSuchFieldException, ClassNotFoundException, InstantiationException, IllegalAccessException {
		Class clazz=Class.forName("cn.itcast.bean.Person");
		//Field field=clazz.getField("age");//只能获取公共的
		Field field=clazz.getDeclaredField("age");//只获取本类,但包含私有。
		//对私有字段的访问取消权限检查。
		field.setAccessible(true);
		Object obj=clazz.newInstance();
		Object o=field.get(obj);	
		System.out.println(o);		
	}
}

 

反射机制(获取Class中的方法)

package cn.itcast.bean;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class ReflectDemo4 {
	public static void main(String[] args) throws Exception {
		getMethodDemo_3();

	}

	public static void getMethodDemo_3() throws Exception {
		Class clazz=Class.forName("cn.itcast.bean.Person");
		Method method=clazz.getMethod("paramMethod",String.class,int.class);
		Object obj=clazz.newInstance();
		method.invoke(obj, "小强",89);
		
	}

	public static void getMethodDemo_2() throws Exception {
		Class clazz=Class.forName("cn.itcast.bean.Person");
		Method method=clazz.getMethod("show",null);//获取show空参数方法
//		Object obj=clazz.newInstance();
		Constructor constructor=clazz.getConstructor(String.class,int.class);
		Object obj=constructor.newInstance("小明",37);
		method.invoke(obj, null);
	}

	public static void getMethodDemo() throws Exception {
		Class clazz=Class.forName("cn.itcase.bean.Person");
		Method[]methods=clazz.getMethods();//获取的都是公有的方法
		methods=clazz.getDeclaredMethods();//指获取本类中所有方法,包含私有的。
		for(Method method:methods){
			System.out.println(method);
		}
		
	}

}

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

未名胡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值