天天看点

Java基础中的反射一、反射

一、反射

“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”,JAVA有着一个非常突出的动态相关机制:Reflection。

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

Java反射机制,可以实现以下功能:
	①在运行时判断任意一个对象所属的类;
	②在运行时构造任意一个类的对象;
	③在运行时判断任意一个类所具有的成员变量和方法;
	④在运行时调用任意一个对象的方法;
	⑤生成动态代理。
           

1.获取源头

获取源头 Class(重点)

所有类的对象其实都是Class的实例。

序列化: 实现serializable接口,

反序列化: 实现cloneable接口,重写 clone() 方法,修改权限为public

New 反射

//
import java.lang.reflect.Modifier;
public class Demo02 extends Object{
	public static void main(String[] args) throws ClassNotFoundException {
		//1.类名.class
		Class cls1=String.class;
		System.out.println(cls1.toString());
		//2.对象.getClass()
		Class cls2="哈哈".getClass();
		System.out.println(cls1==cls2);  //true
		//3.Class.forName("包名+类名")
		Class cls3=Class.forName("java.lang.Object");
		System.out.println(cls3);
		//根据反射的方式获取到这个类型的父类的Class对象
		Class cls4=cls1.getSuperclass();
		System.out.println(cls3==cls4);
		//获取基本数据类型的Class对象
		//根据包装类型.TYPE属性获取对应基本数据类型的Class对象
		Class cls5=int.class;
		Class cls6=Integer.class;
		Class cls7=Integer.TYPE;
		System.out.println(cls5==cls6);
		System.out.println(cls5==cls7);	
		//getName() 
		System.out.println(cls1.getName());	
		//getModifiers() 
		System.out.println(cls1.getModifiers()); //17
		System.out.println(Modifier.toString(cls1.getModifiers())); //public final	
	}
}
           

(1)三种

获取类的class对象,也有三种方式:

①Class.forName(”包名.类名”) //一般尽量采用该形式

②类名.class

③对象.getClass()

2.实例化对象(重点)

之前我们了解过的创建对象的方式,有new 、克隆、反序列化,再加一种,根据Class对象,使用newInstance() 或者构造器实例化对象。

(1)通过反射获取构造器,创建对象

通过反射获取方法,调用方法
 	 Method getDeclaredMethod(String name, Class<?>... parameterTypes)  返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。 
	 Method[] getDeclaredMethods()  返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
	 Method getMethod(String name, Class<?>... parameterTypes)  返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。 
	 Method[] getMethods() 返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。
通过反射获取构造器,创建对象
	 执行方法:
	 	Object invoke(Object obj, Object... args) 
			参数1: 调用方法的对象
			参数2: 调用方法的实参
			返回值: 调用方法的返回值
           
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
public class Demo03 {
	public static void main(String[] args) throws Exception {
		//testConstructor(Person.class);
		//testField(Person.class);
		testMethod(Person.class);
	}
	public static void testMethod(Class<Person> cls) throws Exception{
		Method[] arr=cls.getMethods();
		for(Method me:arr){
			System.out.println(me);
		}
		Person p=cls.newInstance();
		Field field=cls.getDeclaredField("name");
		field.setAccessible(true);
		field.set(p, "lushuangshuang");;
		//System.out.println(arr[8].invoke(p));
		System.out.println(arr[8].invoke(null));  //null没有对象
	}
	//接下
	//接下
}
           

(2)通过反射获取方法,调用方法

通过反射获取属性,获取值|设置值
	Field getField(String name) 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。 
	Field[] getFields()  
	Field getDeclaredField(String name) 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。 
	Field[] getDeclaredFields()  
	
获取属性的值: Object get(Object obj)  
设置属性的值: void set(Object obj, Object value)
           
//接上
public static void main(String[] args) throws Exception {
		//testConstructor(Person.class);
		//testField(Person.class);
		testMethod(Person.class);
}
public static void testField(Class<Person> cls) throws Exception{
		Field name=cls.getDeclaredField("name");
		//成员要跟随对象使用
		Person p=cls.getConstructor(String.class,int.class,Double.TYPE).newInstance("因为",18,100);
		name.setAccessible(true);
		System.out.println(name.get(p));
		name.set(p, "所以");
		System.out.println(name.get(p));
		name.setAccessible(false);
	}
           

(3)通过反射获取属性,获取值|设置值

通过反射获取构造器,创建对象
	Constructor<T> getConstructor(Class<?>... parameterTypes)  返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。 
	Constructor<?>[] getConstructors()  
	Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。 
	Constructor<?>[] getDeclaredConstructors() 

创建对象:
		通过指定的构造器创建对象,如果私有,放开权限
		通过一个类的Class对象的newInstance方法创建这个类的实例,默认调用空构造
           
//接上
public static void main(String[] args) throws Exception {
		//testConstructor(Person.class);
		//testField(Person.class);
		testMethod(Person.class);
	}
public static void testConstructor(Class cls) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
		Constructor<Person>[] arr=cls.getConstructors();  //所有公共的
		System.out.println(Arrays.toString(arr));
		//根据构造器的newInstance(实参...)
		Person p=arr[0].newInstance("zhangsan",18,180);
		System.out.println(p);		
		Constructor<Person> con=cls.getDeclaredConstructor(String.class);
		//放开构造器的权限
		con.setAccessible(true);
		Person p2=con.newInstance("lisi");
		con.setAccessible(false);
		System.out.println(p2);
		//默认调用空构造
		Person p3=(Person) cls.newInstance();
		System.out.println(p3);
	}