1:反射
(1)类的加载及类加载器
(2)反射:
1.概念:通过class文件对象,去使用该文件中的成员变量,构造方法,成员方法。
允许程序在运行期间,动态的创建某个对象,并调用其中的方法。是创建对象的另外一种方式
要想使用,首先你必须得到class文件对象,其实也就是得到Class类的对象。
2.获取class文件对象的方式:
A:Object类的getClass()方法--Class cls=new 对象().getClass();
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
B:数据类型的静态属性class--Class cls=类名.class;
Class c3 = Person.class;
// int.class;
// String.class;
System.out.println(c == c3);
C:Class类中的静态方法
public static Class forName(String className)--Class cls=Class.forName("类的完全限定名");
Class c4 = Class.forName("cn.itcast_01.Person");
System.out.println(c == c4);
开发使用第三种:因为第三种是一个字符串,而不是一个具体的类名。这样我们就可以把这样的字符串配置到配置文件中。
3.Class对象封装了一个类的所有信息,包括:
1,类继承自哪个类
2,实现了哪些接口
3,有哪些属性
4,有哪些方法
5,有哪些构造器
4.反射的优点:
功能强大
提供了很大的灵活性
常用于高级编程,如开发Web容器
反射的缺点:
性能开销
数据安全问题
暴露隐藏的成员
(3)反射的使用
Class常用的方法:
1,class.new Instance(); //创建当前实例对象
2,class.getName(); //获取类的完全限定名
3,class.getSimpleName(); //获取类名
4,class.getSuperClass(); //获取父类的class对象
A:通过反射获取构造方法(Constructor)并使用
public Constructor[] getConstructors():所有公共构造方法
public Constructor[] getDeclaredConstructors():所有构造方法
public Constructor<T> getConstructor(Class<?>... parameterTypes):获取单个构造方法
参数表示的是:你要获取的构造方法的构造参数个数及数据类型的class字节码文件对象
Constructor con = class .getConstructor();// 返回的是构造方法对象
Constructor con = class .getConstructor(String.class, int.class, String.class);//获取带参数的构造方法对象
public T newInstance(Object... initargs)
使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
Object obj = con.newInstance();
System.out.println(obj);
con.setAccessible(true); 暴力访问,设置允许私有调用,值为true则指示反射的对象在使用时应该取消Java语言访问检查。
/*
* 需求:通过反射获取私有构造方法并使用
* private Person(String name){}
*
* Person p = new Person("风清扬");
* System.out.println(p);
*/
public class ReflectDemo3 {
public static void main(String[] args) throws Exception {
// 获取字节码文件对象
Class c = Class.forName("cn.itcast_01.Person");
// 获取私有构造方法对象
// NoSuchMethodException:没有这个方法异常
Constructor con = c.getDeclaredConstructor(String.class);
// 用该私有构造方法创建对象
// IllegalAccessException:非法的访问异常。
// 暴力访问
con.setAccessible(true);// 值为true则指示反射的对象在使用时应该取消Java语言访问检查。
Object obj = con.newInstance("风清扬");
System.out.println(obj);
}
}
B:通过反射获取成员变量(Field)并使用
class.getFields(); //获取所有的public修饰的属性
class.getDeclaredFields(); //获取所有的属性,包含私有
class.getDeclaredField(name);//获取指定的属性:name是属性名
field.getName(); //获取属性名
field.set(Obejct,value); //向指定对象中设值
field.get(Obejct); //从指定对象中取值
/*
* 通过反射获取成员变量并使用
*/
public class ReflectDemo {
public static void main(String[] args) throws Exception {
// 获取字节码文件对象
Class c = Class.forName("cn.itcast_01.Person");
// 通过无参构造方法创建对象
Constructor con = c.getConstructor();
Object obj = con.newInstance();
// 获取单个的成员变量
// 获取address并对其赋值
Field addressField = c.getField("address");
addressField.set(obj, "北京"); // 给obj对象的addressField字段设置值为"北京"
// 获取name并对其赋值
// NoSuchFieldException //没有这个字段-加上Declared获取指定字段
Field nameField = c.getDeclaredField("name");
// IllegalAccessException //安全权限异常
nameField.setAccessible(true); //暴力访问
nameField.set(obj, "林青霞");
// 获取age并对其赋值
Field ageField = c.getDeclaredField("age");
ageField.setAccessible(true);
ageField.set(obj, 27);
System.out.println(obj);
}
}
C:通过反射获取成员方法(Method)并使用
class.getMethods(); //获取自己的包括父亲的公共方法
class.getDeclaredMethods(); //获取自己的所有的方法
class.getMethod(String name,Class<?>... parameterTypes); //获取指定的方法
class.getDeclaredMethod(name,参数1类型.class); //获取指定的私有方法:第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型
method.setAccessible(true);//设置允许私有调用
method.invoke(Obejct, "参数","参数2","参数3");//调用方法:第一个参数表示对象是谁,第二参数表示调用该方法的实际参数
public class ReflectDemo {
public static void main(String[] args) throws Exception {
// 获取字节码文件对象
Class c = Class.forName("cn.itcast_01.Person");
Constructor con = c.getConstructor();
Object obj = con.newInstance();
// 获取单个方法并使用
Method m1 = c.getMethod("show");
m1.invoke(obj); // 调用obj对象的m1方法
// public void method(String s)
Method m2 = c.getMethod("method", String.class);
m2.invoke(obj, "hello");
// public String getString(String s, int i)
Method m3 = c.getMethod("getString", String.class, int.class);
Object objString = m3.invoke(obj, "hello", 100);
// String s = (String)m3.invoke(obj, "hello",100);
// System.out.println(s);
// private void function()
Method m4 = c.getDeclaredMethod("function");
m4.setAccessible(true);
m4.invoke(obj);
}
}
(4)反射案例
A:通过反射运行配置文件的内容
/*
* 通过配置文件运行类中的方法
*
* 反射:
* 需要有配置文件配合使用。
* 用class.txt代替。
className=cn.itcast.test.Worker
methodName=love
* 并且你知道有两个键。
* className
* methodName
*/
public class Test {
public static void main(String[] args) throws Exception {
// 加载键值对数据
Properties prop = new Properties();
FileReader fr = new FileReader("class.txt");
prop.load(fr);
fr.close();
// 获取数据
String className = prop.getProperty("className");
String methodName = prop.getProperty("methodName");
// 反射
Class c = Class.forName(className);
Constructor con = c.getConstructor();
Object obj = con.newInstance();
// 调用方法
Method m = c.getMethod(methodName);
m.invoke(obj);
}
}
B:通过反射越过泛型检查
/*
* 我给你ArrayList<Integer>的一个对象,我想在这个集合中添加一个字符串数据,如何实现呢?
*/
public class ArrayListDemo {
public static void main(String[] args) throws NoSuchMethodException,
SecurityException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
// 创建集合对象
ArrayList<Integer> array = new ArrayList<Integer>();
Class c = array.getClass(); // 集合ArrayList的class文件对象
Method m = c.getMethod("add", Object.class);
m.invoke(array, "hello"); // 调用array的add方法,传入的值是hello
m.invoke(array, "world");
m.invoke(array, "java");
System.out.println(array);
}
}
C:通过反射给任意的一个对象的任意的属性赋值为指定的值
public class Tool {
public void setProperty(Object obj, String propertyName, Object value)
throws NoSuchFieldException, SecurityException,
IllegalArgumentException, IllegalAccessException {
// 根据对象获取字节码文件对象
Class c = obj.getClass();
// 获取该对象的propertyName成员变量
Field field = c.getDeclaredField(propertyName);
// 取消访问检查
field.setAccessible(true);
// 给对象的成员变量赋值为指定的值
field.set(obj, value);
}
}
public class ToolDemo {
public static void main(String[] args) throws NoSuchFieldException,
SecurityException, IllegalArgumentException, IllegalAccessException {
Person p = new Person();
Tool t = new Tool();
t.setProperty(p, "name", "林青霞");
t.setProperty(p, "age", 27);
System.out.println(p);
Dog d = new Dog();
t.setProperty(d, "sex", '男');
t.setProperty(d, "price", 12.34f);
System.out.println(d);
}
}
class Dog {
char sex;
float price;
@Override
public String toString() {
return sex + "---" + price;
}
}
class Person {
private String name;
public int age;
@Override
public String toString() {
return name + "---" + age;
}
}
(5)动态代理
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MyInvocationHandler implements InvocationHandler {
private Object target; // 目标对象
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("权限校验");
Object result = method.invoke(target, args);
System.out.println("日志记录");
return result; // 返回的是代理对象
}
}
public interface StudentDao {
public abstract void login();
public abstract void regist();
}
public class StudentDaoImpl implements StudentDao {
@Override
public void login() {
System.out.println("登录功能");
}
@Override
public void regist() {
System.out.println("注册功能");
}
}
/*
* 用户操作接口
*/
public interface UserDao {
public abstract void add();
public abstract void delete();
public abstract void update();
public abstract void find();
}
public class UserDaoImpl implements UserDao {
@Override
public void add() {
System.out.println("添加功能");
}
@Override
public void delete() {
System.out.println("删除功能");
}
@Override
public void update() {
System.out.println("修改功能");
}
@Override
public void find() {
System.out.println("查找功能");
}
}
public class Test {
public static void main(String[] args) {
UserDao ud = new UserDaoImpl();
ud.add();
ud.delete();
ud.update();
ud.find();
System.out.println("-----------");
// 我们要创建一个动态代理对象
// Proxy类中有一个方法可以创建动态代理对象
// public static Object newProxyInstance(ClassLoader loader,Class<?>[]
// interfaces,InvocationHandler h)
// 我准备对ud对象做一个代理对象
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();
}
}