Java笔记-反射

一.类加载器

    当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化.

        加载:将class文件读入内存,并为之创建一个Class对象

        连接:为类的静态成员分配内存,并设置默认初始化值等

        初始化:创建类的实例,访问类的静态变量,或者为静态变量赋值,调用类的静态方法,使用反射方式来强制创建某个类或接口对应的java.lang.Class对象,初始化某个类的子类,直接使用java.exe命令来运行某个主类

二.反射概述

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

三.反射使用
    1.获取Class对象
package refection;

public class Student {
	public String name;
	private int age;
	public Student() {
		super();
	}	
	private Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	private int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
}
package refection;

public class GetClassDemo {
	public static void main(String[] args) {
		
		Student s=new Student();
		//1.Object类的方法Class<?>	getClass()  :Returns the runtime class of this Object.
		Class c1= s.getClass();
		//2.任何数据类型都有static的class字段
		Class c2=Student.class;
		//3.Class方法:static Class<?> forName(String className) :Returns the Class object associated with the class or interface with the given string name. 
		Class c3 = null;
		try {
			c3 = Class.forName("refection.Student");//完整路径
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(c1==c2);	//true
		System.out.println(c2==c3);//true
	}	
}
2.构造方法
package refection;

import java.lang.reflect.Constructor;

/* 
 * 通过Class对象可以获取某个类中的:构造方法、成员变量、成员方法;并访问成员; 
 *  
 * 1.获取构造方法: 
 *      1).批量的方法: 
 *          public Constructor[] getConstructors():所有"公有的"构造方法 
            public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有) 
      
 *      2).获取单个的方法,并调用: 
 *          public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法: 
 *          public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有; 
 *       
 *       	获取调用私有的权限
 *       	setAccessible(true)
 *          调用构造方法: 
 *          Constructor-->newInstance(Object... initargs) 
 */ 
public class ConstructorDemo {
	public static void main(String[] args) throws Exception {
		Class class1=Class.forName("refection.Student");
		//Constructor[] getConstructors()
		Constructor[] constructors1=class1.getConstructors();
		for(Constructor c:constructors1)
		{
			System.out.println(c);
		}
		//Constructor[] getDeclaredConstructors()
		System.out.println("--------");
		Constructor[] constructors2=class1.getDeclaredConstructors();
		for(Constructor c:constructors2)
		{
			System.out.println(c);
		}
		//Constructor getConstructor(Class... parameterTypes)
		System.out.println("--------");
		Constructor c=class1.getConstructor();
		Object obj1=c.newInstance();
		System.out.println(obj1);
		//Constructor getDeclaredConstructor(Class... parameterTypes)
		System.out.println("--------");
		Constructor c2=class1.getDeclaredConstructor(String.class,int.class);
		c2.setAccessible(true);
		Object obj2=c2.newInstance("张三",20);
		System.out.println(obj2);
	}
}
3.成员变量
package refection;

import java.lang.reflect.Field;

public class FieldDemo {
	public static void main(String[] args) throws Exception {
		@SuppressWarnings({ "unchecked" })
		Class<refection.Student> class1=(Class<Student>) Class.forName("refection.Student");
		//getFields();
		Field[] fields=class1.getFields();
		for(Field f:fields){
			System.out.println(f);	//public java.lang.String refection.Student.name
		}
		//getDeclaredFields();
		System.out.println("-------");
		Field[] fields2=class1.getDeclaredFields();
		for(Field f:fields2){		//public java.lang.String refection.Student.name
			System.out.println(f);//private int refection.Student.age					
		}
		//getField(String name)
		System.out.println("------");
		Field field1=class1.getField("name");
		System.out.println(field1);//public java.lang.String refection.Student.name
		//getDeclaredField(String name)
		System.out.println("------");
		Field field2=class1.getDeclaredField("age");
		field2.setAccessible(true);
		System.out.println(field2);	//private int refection.Student.age
	}
}
4.成员方法
package refection;

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

public class MethodDemo {
	public static void main(String[] args) throws Exception{
		Class class1=Class.forName("refection.Student");
		//getMethods() 包括了父类继承的方法
		Method[] methods1=class1.getMethods();
		for(Method m:methods1) {
			System.out.println(m);
		}
		//getDeclaredMethods()
		System.out.println("------");
		Method[] methods2=class1.getDeclaredMethods();
		for(Method m:methods2) {
			System.out.println(m);
		}
		//getMethod(),invoke()
		System.out.println("------");
		Constructor constructor1=class1.getConstructor();
		Object obj1=constructor1.newInstance();
		Method method1=class1.getMethod("setName", String.class);
		method1.invoke(obj1,"张三");
		System.out.println(obj1);//Student [name=张三, age=0]
		
		//getDeclaredMethod() invoke()
		System.out.println("-------");
		Method method3=class1.getDeclaredMethod("setAge",int.class);// 注意是int不是Integer,吃大亏了
		method3.setAccessible(true);
		method3.invoke(obj1, 20);
		System.out.println(obj1);
	}
}
5.应用-配置文件

config.properties:

Class=refection.Student

Method=setAge
package refection;

import java.io.FileReader;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;
/**
 * 读取配置文件,设置age后读取age
 * @author sun
 *
 */
public class PropertiesDemo {
	public static void main(String[] args) throws Exception {
		Properties properties=new Properties();
		FileReader fileReader=new FileReader("C:\\java\\code\\sewk\\czbk\\src\\refection\\config.properties");
		properties.load(fileReader);
		//fileReader.close();
		String className=properties.getProperty("Class");
		String methodName=properties.getProperty("Method");
		Class class1=Class.forName(className);
		Constructor constructor=class1.getConstructor();
		Object object=constructor.newInstance();
		Method method=class1.getDeclaredMethod(methodName,int.class);//是int不是Integer
		method.setAccessible(true);
		method.invoke(object,20);
		Field field=class1.getDeclaredField("age");
		field.setAccessible(true);
		System.out.println(field.get(object));
	}
}
6.应用-越过泛型检查
package refection;

import java.lang.reflect.Method;
import java.util.ArrayList;
/**
 * 越过泛型检查
 * @author sun
 *
 */
public class GenericDemo {
	public static void main(String[] args) throws Exception {
		ArrayList<Integer> array=new ArrayList<Integer>();
		array.add(20);
		Class class1=Class.forName("java.util.ArrayList");
		Method method=class1.getMethod("add", Object.class);
		method.invoke(array, "Hello");
		System.out.println(array);//[20, Hello]
		
	}
}
7.应用-动态代理
package refection;
/**
 * 注意:传入的是实例Manager,但一定要用接口接返回值
 */
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyDemo {
	public static void main(String[] args) {
		/**
		 * 方式一:通过构造传入实例对象Manager
		 * 注意:返回值要用接口接,不然报错
		 */
		Worker worker=(Worker)Proxy.newProxyInstance(Manager.class.getClassLoader(), Manager.class.getInterfaces(), new MyInvokeHandler(new Manager()));
		worker.work();
		/**
		 * 方式二:封装一下,注意传入
		 */
		MyInvokeHandler handler=new MyInvokeHandler();
		Worker worker2=(Worker)handler.bind(new Manager());
		worker2.work();
	}
}

class MyInvokeHandler implements InvocationHandler{
	
	//invoke()的method调用所需的实例和初始化方法
	private Object obj;
	public MyInvokeHandler(Object obj) {
		this.obj=obj;
	}
	public MyInvokeHandler() {
		// TODO Auto-generated constructor stub
	}
	public Object bind(Object obj) {
		this.obj=obj;
		//注意要用obj.getClass()而不是Object.class啊啊啊啊
		return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
	}
	/**
	 * proxy - 调用该方法的代理实例 
	 * method -所述方法对应于调用代理实例上的接口方法的实例。 方法对象的声明类将是该方法声明的接口,它可以是代理类继承该方法的代理接口的超级接口。 
	 * args -包含的方法调用传递代理实例的参数值的对象的阵列,或null如果接口方法没有参数。 原始类型的参数包含在适当的原始包装器类的实例中,例如java.lang.Integer或java.lang.Boolean 
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("打卡上班");
		Object result=null;
		result=method.invoke(obj, args);//注意是obj,proxy就是obj但是一般不直接调用invoke所以用bind初始化或构造初始化
		System.out.println("打卡下班");
		return result;
	}
}
interface Worker{
	void work();
}
class Manager implements Worker{

	@Override
	public void work() {
		System.out.println("manager work");
	}
	
}

输出:

打卡上班
manager work
打卡下班
打卡上班
manager work
打卡下班

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值