反射
Java反射机制提供的功能
- 在运行时判断任意一个对象所属的类
- 在运行时构造一个任意类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时获取泛型信息
- 在运行时调用任意一个对象的成员变量和方法
- 在运行时处理注解
- 生成动态代理
package reflect01;
public class Person {
public String name;
private int age;
public Person() {
}
private Person(String name) {
this.name = name;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public void show(){
System.out.println("hello");
}
private void test(){
System.out.println("test reflect");
}
}
package reflect01;
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test01 {
@Test
public void test1() throws Exception {
Constructor<Person> constructor = Person.class.getConstructor(String.class, int.class);
Person tom = constructor.newInstance("tom", 12);
System.out.println(tom.toString());
}
@Test
public void test12() throws Exception {
Constructor<Person> constructor = Person.class.getConstructor(String.class, int.class);
Person tom = constructor.newInstance("tom", 12);
Field name = Person.class.getDeclaredField("name");
name.set(tom, "hhh");
System.out.println(tom.toString());
}
//调方法
@Test
public void test3() throws Exception {
Class<Person> aClass = Person.class;
Constructor<Person> constructor = aClass.getConstructor(String.class, int.class);
Person tom = constructor.newInstance("tom", 12);
Method show = Person.class.getMethod("show");
show.invoke(tom);
//调用私有构造函数
System.out.println("----------------------------------------------");
Constructor<Person> constructor1 = aClass.getDeclaredConstructor(String.class);
constructor1.setAccessible(true);
Person test = constructor1.newInstance("test");
System.out.println(test.toString());
//调用私有属性
Field age = aClass.getDeclaredField("age");
age.setAccessible(true);
age.set(test,11);
System.out.println(test.toString());
//调用私有方法
Method method = aClass.getDeclaredMethod("test");
method.setAccessible(true);
method.invoke(test);
}
/**
* 反射是否与类的封装是矛盾的?
*/
}
获取Class实例
//获取Class类方式
@Test
public void test4() throws Exception {
Class aClass = Person.class;
System.out.println(aClass);
Person person = new Person();
Class aClass1 = person.getClass();
Class aClass2 = Class.forName("reflect01.Person");
System.out.println(aClass==aClass1);
ClassLoader classLoader = Test01.class.getClassLoader();
Class aClass3 = classLoader.loadClass("reflect01.Person");
}
获取运行时类的信息
package reflect02;
import java.io.StringReader;
import java.util.Comparator;
@MyAnnotation(value = "123")
public class Person extends Creature<String> implements Comparable<String>, MyInterface{
public static int fie=2;
private String name;
int age;
public int id;
public Person() {
}
private Person(String name) {
this.name = name;
}
Person(String name, int age) {
this.name = name;
this.age = age;
}
@MyAnnotation
private String show(String nation){
System.out.println("国籍"+nation);
return nation;
}
public String display(String interests){
return interests;
}
public void info(){
System.out.println("我是人");
}
@Override
public int compareTo(String o) {
return 0;
}
public static void me(String s){
System.out.println(s);
}
}
package reflect02;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
public class Test {
/**
* 获取类属性结构
*/
@org.junit.Test
public void test(){
Class<Person> aClass = Person.class;
//获取运行时类及其父类声明为public的属性
Field[] fields = aClass.getFields();
for (Field f:fields) {
System.out.println(f);
}
System.out.println();
//获取当前运行时类的属性 不包括父类的属性
Field[] fields1 = aClass.getDeclaredFields();
for (Field f:fields1) {
System.out.println(f);
}
}
@org.junit.Test
public void test1(){
Class<Person> aClass = Person.class;
//获取运行时类及其父类声明为public的属性
Field[] fields = aClass.getFields();
for (Field f:fields) {
/**
* 获取权限修饰符
* 默认权限也是权限
*/
int modifiers = f.getModifiers();
System.out.println(Modifier.toString(modifiers));
//数据类型
Class type = f.getType();
System.out.println(type);
//变量名
String name = f.getName();
System.out.println(name);
}
}
/**
* 获取运行时类的方法结构
*/
@org.junit.Test
public void test2(){
Class<Person> aClass = Person.class;
//获取运行时类及其父类声明为public的方法
Method[] methods = aClass.getMethods();
for (Method me :
methods) {
System.out.println(me);
}
Method[] declaredMethods = aClass.getDeclaredMethods();
for (Method me :
declaredMethods) {
System.out.println(me);
}
}
/**
* 获取方法的内部结构
*/
@org.junit.Test
public void test3(){
//获取方法声明的注解
Class<Person> aClass = Person.class;
Method[] methods = aClass.getDeclaredMethods();
for (Method me:methods){
Annotation[] annotations = me.getAnnotations();
for (Annotation an:
annotations) {
System.out.println(an);
}
//权限修饰符
int modifiers = me.getModifiers();
System.out.println(Modifier.toString(modifiers));
//返回值类型
String name = me.getReturnType().getName();
System.out.println(name);
//方法名
String name1 = me.getName();
System.out.println(name1);
//抛出的异常
Class<?>[] exceptionTypes = me.getExceptionTypes();
}
}
/**
* 获取构造器
*/
@org.junit.Test
public void test4(){
Class<Person> personClass = Person.class;
//当前运行时类中声明为public的构造器
Constructor<?>[] constructors = personClass.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
//拿到运行时类中所有的构造器
Constructor<?>[] declaredConstructors = personClass.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
}
/**
* 获取运行时类的父类
*/
@org.junit.Test
public void test5(){
//获取运行时类的父类
Class<Person> personClass = Person.class;
Class<? super Person> superclass = personClass.getSuperclass();
System.out.println(superclass);
//获取运行时类带泛型的父类
Type genericSuperclass = personClass.getGenericSuperclass();
System.out.println(genericSuperclass);
}
/**
* 获取运行时类实现的接口
*/
@org.junit.Test
public void test6() {
Class<Person> personClass = Person.class;
Class<?>[] interfaces = personClass.getInterfaces();
for (Class<?> anInterface : interfaces) {
System.out.println(anInterface);
}
}
/**
* 获取运行是类所在的包
*/
@org.junit.Test
public void test7() {
Class<Person> personClass = Person.class;
Package aPackage = personClass.getPackage();
System.out.println(aPackage);
}
}
package reflect02;
import org.junit.Test;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 调用运行时类中制定的结构 属性 方法 构造器
*/
public class Test2 {
@Test
public void test() throws Exception{
Class<Person> personClass = Person.class;
Person person = personClass.newInstance();
//获取public的属性
Field id = personClass.getField("id");
id.set(person,100);
System.out.println(id.get(person));
}
@Test
public void test1() throws Exception{
Class<Person> personClass = Person.class;
Person person = personClass.newInstance();
//可以获取为private属性 但要设置access
Field age = personClass.getDeclaredField("age");
Field name = personClass.getDeclaredField("name");
age.set(person,12);
System.out.println(age.get(person));
name.setAccessible(true);
name.set(person,"sss");
System.out.println(name.get(person));
}
/**
* 获取运行时类指定的方法
*
*/
@Test
public void test2() throws Exception{
Class<Person> personClass = Person.class;
Person person = personClass.newInstance();
//指明方法名称 指明形参列表
Method show = personClass.getDeclaredMethod("show", String.class);
show.setAccessible(true);
show.invoke(person,"CHN");
//调用静态方法
Method me = personClass.getDeclaredMethod("me",String.class);
me.setAccessible(true);
me.invoke(person,"ss");
//调用静态属性
Field fie = personClass.getField("fie");
System.out.println(fie.get(person));
}
}
静态代理
假设现在项目经理有一个需求:在项目现有所有类的方法前后打印日志。
你如何在不修改已有代码的前提下,完成这个需求?
我首先想到的是静态代理。具体做法是:
1.为现有的每一个类都编写一个对应的代理类,并且让它实现和目标类相同的接口(假设都有)
2.在创建代理对象时,通过构造器塞入一个目标对象,然后在代理对象的方法内部调用目标对象同名方法,并在调用前后打印日志。也就是说,代理对象 = 增强代码 + 目标对象(原对象)。有了代理对象后,就不用原对象了
package proxy;
interface Factory{
public void produceCloth();
}
class ProxyCloth implements Factory{
public Factory factory;
public ProxyCloth(Factory factory) {
this.factory = factory;
}
@Override
public void produceCloth() {
System.out.println("生产衣服前的准备");
factory.produceCloth();
System.out.println("生产衣服后的准备");
}
}
//被代理类
class Nike implements Factory{
@Override
public void produceCloth() {
System.out.println("耐克衣服");
}
}
public class StaticProxy {
public static void main(String[] args) {
Nike nike = new Nike();
ProxyCloth proxyCloth = new ProxyCloth(nike);
proxyCloth.produceCloth();
}
}
动态代理
区分代理类 和被代理类
如明星和经纪人 明星是作为被代理类 经纪人是作为代理类
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
interface Human{
String getBelief();
void eat(String fool);
}
class SuperMan implements Human{
@Override
public String getBelief() {
return "Java";
}
@Override
public void eat(String food) {
System.out.println("我喜欢吃"+food);
}
}
/**
* 动态代理解决的问题?
* 1.如何根据加载到内存中的被代理类 动态的创建一个代理类及其对象
* 2.当通过代理类的对象调用方法时 如何动态的去调用被代理类的同名方法
*/
class ProxyFactory{
//返回一个代理类的对象
public static Object getProxyInstance(Object object){ //传进去被代理类的对象 动态生产一个代理类的对象
MyInvocationHandler myInvocationHandler = new MyInvocationHandler();
myInvocationHandler.bind(object);
Object o = java.lang.reflect.Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), myInvocationHandler);
return o;
}
}
class MyInvocationHandler implements InvocationHandler{
private Object obj;
public void bind(Object obj){
this.obj=obj;
}
//当通过代理类的对象 调用方法a是 会就自动调用如下方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//为代理类对象调用的方法 此方法也就作为了被代理类对象要调用的方法
Object invoke = method.invoke(obj, args);
//返回方法返回值
return invoke;
}
}
public class Proxy {
public static void main(String[] args) {
SuperMan superMan = new SuperMan();
Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);
proxyInstance.eat("零食");
System.out.println(proxyInstance.getBelief());
Nike nike = new Nike();
Factory proxyInstance1 = (Factory) ProxyFactory.getProxyInstance(nike);
proxyInstance1.produceCloth();
}
}
根据代理Class的构造器创建对象时,需要传入InvocationHandler。通过构造器传入一个引用,那么必然有个成员变量去接收。没错,代理对象的内部确实有个成员变量invocationHandler,而且代理对象的每个方法内部都会调用handler.invoke()!InvocationHandler对象成了代理对象和目标对象的桥梁,不像静态代理这么直接。