1:反射(理解)
(1)类的加载及类加载器
(2)反射:
通过字节码文件对象,去使用成员变量,构造方法,成员方法
package day27_Reflect;
public class Person {
private String name;
private int age;
public Person() {
// TODO Auto-generated constructor stub
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
private Person(String name){
this.name=name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void show(){
System.out.println("show");
}
public void method(String s){
System.out.println("method"+s);
}
public String getString(String s,int i){
return s+"---"+i;
}
private void function(){
System.out.println("function");
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
package day27_Reflect;
/*
* 反射:就是通过Class文件对象,去使用该文件中的成员变量、构造方法、成员方法
*
* Person p=new Person();
* p.使用
*
* 要想这样使用,首先你必须得到Class文件对象,其实也就是得到Class类的对象
* Class类:
* 成员变量 Field
* 构造方法 Constructor
* 成员方法 Method
*
* 获取Class文件对象的方式:
* A:Object类的getClass()方法
* B:数据类型的静态属性class方法
* C:Class类中的静态方法
* public static Class forName(String className)
*
* 一般我们到底使用谁呢?
* A:自己玩 任选一种,第二种方式比较方便
* B:开发 第三种
* 为什么呢?因为第三种是一个字符串,而不是一个具体的类名
* 这样我们就可以把这样的字符串配置到配置文件中
* */
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
// TODO Auto-generated method stub
//方式1
Person p = new Person();
Class c = p.getClass();
Person p2 = new Person();
Class c2 = p2.getClass();
System.out.println(p==p2);//false
System.out.println(c==c2);//true
//方式2
Class c3=Person.class;
System.out.println(c3==c);//true
//方式3
//ClassNotFoundException
Class c4 = Class.forName("day27_Reflect.Person");
System.out.println(c==c4);//true
}
}
(3)反射的使用
A:通过反射获取构造方法并使用
package day27_Reflect2;
import java.lang.reflect.Constructor;
/*
* 通过反射获取构造方法并使用
* */
public class ReflectDemo {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
//获取字节码文件
Class c = Class.forName("day27_Reflect.Person");
//获取构造方法
// public Constructor [] getConstructor():所有公共构造方法
// public Constructor [] getConstructors():所有构造方法
// Constructor[] cons = c.getConstructors();
// for(Constructor con:cons){
// System.out.println(con);
// }
//获取单个构造方法
// public Constructor<T> getConstructor(Class<T>...parameterTypes)
//参数表示的是:你要获取的构造方法的构造参数个数及数据类型的class字节码文件对象
Constructor con = c.getConstructor();
//Person person = new Person();
//public T newInstance(Object...initargs)
//使用此Constructor对象表示的构造方法来创建该构造方法的声明类的实例,并用指定的初始化参数初始化实例
Object obj = con.newInstance();
System.out.println(obj);
}
package day27_Reflect2;
import java.lang.reflect.Constructor;
/*
* 需求:通过反射去获取该构造方法并使用
* public Person(String name,int age)
*
* Person p=new Person("林青霞",27);
* System.out.println(p);
*
* */
public class ReflectDemo2 {
public static void main(String[] args)throws Exception {
// TODO Auto-generated method stub
//获取字节码文件对象
Class c = Class.forName("day27_Reflect.Person");
//获取带参构造方法对象
Constructor con = c.getConstructor(String.class,int.class);
//通过带参构造方法对象创建对象
Object obj = con.newInstance("林青霞",27);
System.out.println(obj);
}
}
package day27_Reflect2;
import java.lang.reflect.Constructor;
/*
* 需求:通过反射获取私有构造方法并使用
* private Person(String name){}
*
* Person p=new Person("风清扬");
* System.out.println(p);
* */
public class ReflectDemo3 {
public static void main(String[] args)throws Exception {
// TODO Auto-generated method stub
//获取字节码对象
Class c = Class.forName("day27_Reflect.Person");
//获取私有构造方法对象
//publie Constructor getDeclaredConstructor(Class...parameterType)
Constructor con = c.getDeclaredConstructor(String.class);
//用该私有构造方法创建对象
//IllegalAccessException:非法的访问异常
//暴力访问
con.setAccessible(true);//值为true则指示反射的对象在使用时应该取消Java语言访问检查
Object obj = con.newInstance("风清扬");
System.out.println(obj);
}
}
B:通过反射获取成员变量并使用
package day27_Reflect3;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
/*
* 需求:通过反射获取成员变量并使用
* */
public class ReflectDemo {
public static void main(String[] args)throws Exception {
// TODO Auto-generated method stub
//获取字节码文件
Class c = Class.forName("day27_Reflect.Person");
//获取所有成员变量
// Field[] fields = c.getFields();
//成员变量私有访问方法
// Field[] fields = c.getDeclaredFields();
// for(Field field:fields){
// System.out.println(field);
// }
//通过无参构造方法创建对象
Constructor con = c.getConstructor();
Object obj = con.newInstance();
System.out.println(obj);
//获取单个的成员变量
//获取name的成员变量
// Field nameField = c.getField("name");
//获取私有成员变量
Field nameField = c.getDeclaredField("name");
//public void set(Object obj,Object value)
//NoSuchFieldException:匹配异常
//私有变量访问,需要暴力访问
nameField.setAccessible(true);
nameField.set(obj, "风清扬");
System.out.println(obj);
//对age私有成员变量赋值
Field ageField = c.getDeclaredField("age");
//暴力访问
ageField.setAccessible(true);
ageField.set(obj, 27);
System.out.println(obj);
}
}
C:通过反射获取成员方法并使用
package day27_Reflect3;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class ReflectDemo2 {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
// 获取字节码文件对象
Class c = Class.forName("day27_Reflect.Person");
// 创建实例
Constructor con = c.getConstructor();
Object obj = con.newInstance();
// 获取单个方法并使用
// public void show()
// public void getMethod(String name,Class<T>...parameterType)
// 第一个参数表示方法名,第二个参数表示的是方法的参数的class类型
Method m1 = c.getMethod("show");
// public void invoke(Object obj,Object...args)
// 返回值是Object接收,第一个参数表示对象是谁,第二个参数表示调用该方法的实际参数
m1.invoke(obj);// 调用obj对象的m1方法
System.out.println("----------------");
// public void method(String s)
Method m2 = c.getMethod("method", String.class);
m2.invoke(obj, "hello");
System.out.println("----------------");
Method m3 = c.getMethod("getString", String.class, int.class);
Object objectString = m3.invoke(obj, "hello", 100);
System.out.println(objectString);
System.out.println("----------------");
//private void function()
Method m4 = c.getDeclaredMethod("function");
m4.setAccessible(true);
m4.invoke(obj);
}
}
(4)反射案例
A:通过反射运行配置文件的内容
package day27_Reflect4;
import java.io.FileReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;
/*
* 需求:通过配置文件运行类中的方法
*
* 反射:
* A:需要有配置文件配合使用
* B:用config.txt替代
* C:并且你知道有两个键
* className
* methodName
* */
public class ReflectDemo {
public static void main(String[] args)throws Exception {
// TODO Auto-generated method stub
//反射前的做法
// Student s = new Student();
// s.love();
// Teacher t = new Teacher();
// t.love();
// Worker w = new Worker();
// w.love();
//反射后的做法
//加载键值对数据
Properties pro = new Properties();
FileReader fr = new FileReader("config.txt");
pro.load(fr);
fr.close();
//获取数据
String className=pro.getProperty("className");
String methodName=pro.getProperty("methodName");
//反射
Class c = Class.forName(className);
//无参构造
Constructor con = c.getConstructor();
//获取实例对象
Object obj = con.newInstance();
//加载方法
Method m = c.getMethod(methodName);
//调用
m.invoke(obj);
}
}
B:通过反射越过泛型检查
package day27_Reflect4;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
/*
* 需求:利用反射实现在给定ArrayList<Integer>的一个对象
* 我想在这个集合中添加一个字符串数据,如何实现呢?
* */
public class ReflectTest {
public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// TODO Auto-generated method stub
ArrayList<Integer> array = new ArrayList<Integer>();
// array.add(10);
// array.add("hello");
//通过反射
Class c = array.getClass();//集合ArrayList的class文件对象
Method m = c.getMethod("add", Object.class);
//添加数据
m.invoke(array, "hello");
m.invoke(array, "world");
m.invoke(array, "java");
System.out.println(array);
}
}
C:通过反射给任意的一个对象的任意的属性赋值为指定的值
package day27_Reflect4;
import java.lang.reflect.Field;
public class Tool {
public void setProperty(Object obj,String propertyName,Object value) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{
//此方法可将obj对象中名为propertyName的属性值设为value
//获取对象字节码文件d对象
Class c = obj.getClass();
//获取该对象的propertyName成员变量
Field field = c.getDeclaredField(propertyName);
//取消访问检查
field.setAccessible(true);
//赋值
field.set(obj, value);
}
}
package day27_Reflect4;
public class ToolDemo {
public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
// TODO Auto-generated method stub
Person p = new Person();
//p.name="林青霞";//私有成员变量无法访问
//调用Tool工具类
Tool tool = new Tool();
tool.setProperty(p, "name", "林青霞");
tool.setProperty(p, "age", 27);
System.out.println(p);
}
}
class Person{
private String name;
public int age;
@Override
public String toString() {
// TODO Auto-generated method stub
return name+"---"+age;
}
}
(5)动态代理
接口类:
package day27_Reflect_Agent;
public interface StudentDao {
public abstract void login();
public abstract void regist();
}
实现类:
package day27_Reflect_Agent;
public class StudentDaoImpl implements StudentDao {
@Override
public void login() {
// TODO Auto-generated method stub
System.out.println("登录");
}
@Override
public void regist() {
// TODO Auto-generated method stub
System.out.println("注册");
}
}
代理:
package day27_Reflect_Agent;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler {
private Object target;//目标对象
public MyInvocationHandler(Object target) {
// TODO Auto-generated constructor stub
this.target=target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
System.out.println("权限校验");
Object result = method.invoke(target, args);
System.out.println("日志记录");
return result;
}
}
测试类:
package day27_Reflect_Agent;
import java.lang.reflect.Proxy;
/*
* 通过代理实现
* */
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
//未使用代理
UserDao ud = new UserDaoImpl();
// ud.add();
// ud.delete();
// ud.update();
// ud.find();
// System.out.println("-------------------");
//使用代理做法
//public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
MyInvocationHandler handler=new MyInvocationHandler(ud);
UserDao proxy=(UserDao) Proxy.newProxyInstance(ud.getClass().getClassLoader(),ud.getClass().getInterfaces(), handler);
proxy.add();
proxy.delete();
proxy.update();
proxy.find();
System.out.println("---------------");
StudentDao sd = new StudentDaoImpl();
MyInvocationHandler handler2 = new MyInvocationHandler(sd);
StudentDao proxy2 = (StudentDao) Proxy.newProxyInstance(sd.getClass().getClassLoader(), sd.getClass().getInterfaces(), handler2);
proxy2.login();
proxy2.regist();
}
}