一.类加载器
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化.
加载:将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=setAgepackage 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
打卡下班