反射(Reflection):
    反射就是根据对象反射出对象所在的类以及包。
    Class类是反映类的类。

    利用反射调用私有结构的代码:

    1. package com.ReflectionTest;
    2. import org.junit.Test;
    3. import java.lang.reflect.Constructor;
    4. import java.lang.reflect.Field;
    5. import java.lang.reflect.InvocationTargetException;
    6. import java.lang.reflect.Method;
    7. public class ReflectionTest {
    8. @Test
    9. public void test2() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
    10. Class clazz = Person.class;
    11. Constructor cons = clazz.getConstructor(String.class,int.class);
    12. //1、通过反射,创建Person类对象
    13. Object obj = cons.newInstance("TOm", 12);
    14. Person p = (Person) obj;
    15. System.out.println(obj.toString());
    16. //2、通过反射,调用对象指定的属性、方法
    17. //调用属性
    18. Field age = clazz.getDeclaredField("age");
    19. age.set(p,10);
    20. System.out.println(p.toString());
    21. //调用方法
    22. Method show = clazz.getDeclaredMethod("show");
    23. show.invoke(p);
    24. //通过反射可以调用Person类私有结构
    25. //调用私有构造器
    26. Constructor cons1 = clazz.getDeclaredConstructor(String.class);
    27. cons1.setAccessible(true);
    28. Person p1 = (Person) cons1.newInstance("Jerry");
    29. System.out.println(p1);
    30. //调用私有的属性
    31. Field name = clazz.getDeclaredField("name");
    32. name.setAccessible(true);
    33. name.set(p1,"HanMeimei");
    34. System.out.println(p1);
    35. //调用私有方法
    36. Method showNation = clazz.getDeclaredMethod("showNation",String.class);
    37. showNation.setAccessible(true);
    38. showNation.invoke(p1,"中国");
    39. }
    40. }

    反射机制和封装性是否矛盾?如何看待?
    封装和反射是大门和窗户的关系。

    获取Class实例的四种方法(前三种重点掌握):

    1. public void test3() throws ClassNotFoundException {
    2. //方式一:调用运行时类的属性
    3. Class<Person> clazz1 = Person.class;
    4. System.out.println(clazz1);
    5. //方式二通过运行时类的对象
    6. Person p1 = new Person();
    7. Class clazz2 = p1.getClass();
    8. System.out.println(clazz2);
    9. //**方式三:调用Class的静态方法:forNmae(String classPath)
    10. Class clazz3 = Class.forName("com.ReflectionTest.ReflectionTest");
    11. System.out.println(clazz3);
    12. //这三种运行时类,只要是同一个类的class对象,那他们都是一样的。
    13. //方式四:使用类的加载器:ClassLoader(了解)
    14. ClassLoader classLoader = ReflectionTest.class.getClassLoader();
    15. Class clazz4 = classLoader.loadClass("com.ReflectionTest.Person");
    16. System.out.println(clazz4);
    17. }

    Properties可以读取配置文件

    反射机制可以做:

    • 在运行时判断任意一个对象所属的类
    • 在运行时构造任意一个类的对象
    • 在运行时判断任意一个类所具有的成员变量和方法
    • 在运行时获取泛型信息
    • 在运行时调用任意一个对象的成员变量和方法
    • 在运行时处理注解
    • 生成动态代理

    应用: 创建运行时类的对象、获取运行时类的完整结构、调用运行时类的指定结构

    相关API:
    java.lang.reflect.Method
    java.lang.reflect.Filed
    java.lang.reflect.Constructor

    一、创建类的对象的方式:
    方式一: 通过构造器来new;
    方式二: 要创建Xxx类的对象,可以考虑:Xxx、Xxxs、XxxEactory、XxxBuilder类中查看是否有静态方法的存在。可以调用其静态方法,创建Xxx对象;
    方式三:通过反射。

    类加载器的作用:

    • 类加载的作用:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口。

    • 类缓存:标准的JavaSE类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,它将维持加载(缓存)一段时间。不过JVM垃圾回收机制可以回收这些Class对象。

    反射可以调用运行时类的指定结构:
    构造器、方法、属性。

    静态代理代码:

    1. package com.ReflectionTest;
    2. import org.junit.Test;
    3. /**
    4. * 静态代理举例
    5. */
    6. interface ClothFactory{
    7. void produceCloth();
    8. }
    9. //代理类
    10. class ProxyClothFactory implements ClothFactory{
    11. private ClothFactory factory;// 用被代理类对象进行实例化。这里应该是
    12. //一个多态的状况,相当于new了接口的一个实现类
    13. public ProxyClothFactory(ClothFactory factory){
    14. this.factory = factory;
    15. }
    16. @Override
    17. public void produceCloth() {
    18. System.out.println("代理工厂做一些准备工作");
    19. factory.produceCloth();
    20. System.out.println("代理工厂做一些后续的收尾工作");
    21. }
    22. }
    23. //被代理类
    24. class NikeClothFactory implements ClothFactory{
    25. @Override
    26. public void produceCloth() {
    27. System.out.println("耐克工厂生产一些运动服");
    28. }
    29. }
    30. public class StaticProxyTest{
    31. public static void main(String[] args) {
    32. //创建被代理类的对象
    33. NikeClothFactory nike = new NikeClothFactory();
    34. //创建代理类的对象
    35. ProxyClothFactory proxyClothFactory = new ProxyClothFactory(nike);
    36. proxyClothFactory.produceCloth();
    37. }
    38. }

    动态代理:
    其实是根据动态的被代理类,生成动态的代理类,来执行被代理类中的方法。

    下面是例子代码,其中nike那个是上面静态代理的代码

    1. package com.ProxyTest;
    2. import com.ReflectionTest.ClothFactory;
    3. import com.ReflectionTest.NikeClothFactory;
    4. import java.lang.reflect.InvocationHandler;
    5. import java.lang.reflect.Method;
    6. import java.lang.reflect.Proxy;
    7. interface Human{
    8. String getBelief();
    9. void eat(String food);
    10. }
    11. // 被代理类
    12. class SuperMan implements Human{
    13. @Override
    14. public String getBelief() {
    15. return "I believe I can fly!";
    16. }
    17. @Override
    18. public void eat(String food) {
    19. System.out.println("我喜欢吃" + food);
    20. }
    21. }
    22. /*
    23. 实现动态代理需要解决的问题:
    24. 问题一:如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象
    25. 问题二:当通过代理类的对象调用方法时,如何动态地去调用被代理类中的同名方法。
    26. */
    27. class ProxyFactory{
    28. //调用此方法,返回一个代理类的对象,解决问题一
    29. public static Object getProxyInstance(Object obj){ //obj:被代理类的对象
    30. MyInovationHandler handler = new MyInovationHandler();
    31. handler.bind(obj);
    32. return Proxy.newProxyInstance(obj.getClass().getClassLoader(),...
    33. obj.getClass().getInterfaces(),handler);
    34. //把被代理
    35. // 类装进内存并且获取被代理类的接口,在本例子中,被代理类实现的是Human接口,
    36. //handler里面已经初始化,并且把被代理类装进了MyInovationHandler的obj属性,
    37. //调用该方法后,返回一个根据当前需求而产生的代理类,后面可以根据该代理类通
    38. //过共同实现的Human接口调用被代理类的方法。这个方法已经被封装好了,里面会
    39. //自己调invoke,然后再通过字符串去找被代理类中对应的方法,进而实现。
    40. }
    41. }
    42. class MyInovationHandler implements InvocationHandler{
    43. private Object obj;//赋值时也需要使用被代理类的对象
    44. public void bind(Object obj){
    45. this.obj = obj;
    46. }
    47. //当我们通过代理类的对象,调用方法a时,就会自动的调用如下的方法
    48. //将被代理类要执行的方法a的功能声明再invoke()中
    49. @Override
    50. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    51. //此处的Method是一个对象
    52. //method()即为代理类对象调用的方法,此方法也是被代理类需要调用的方法
    53. //obj为被代理类的对象
    54. Object returnValue = method.invoke(obj,args);
    55. //上述方法的返回值就作为当前类中的invoke()的返回值。
    56. return returnValue;
    57. }
    58. }
    59. public class ProxyTest {
    60. public static void main(String[] args) {
    61. SuperMan superMan = new SuperMan();//这个就是动态变化的类
    62. //proxyInstance:代理类的对象。这里不能写SuperMan,如果写SuperMan就让这
    63. //个代理类成了被代理类
    64. Human proxyInstance = (Human)ProxyFactory.getProxyInstance(superMan);
    65. // 当通过代理类对象调用方法时,会自动的调用被代理类中同名的方法
    66. String belief = proxyInstance.getBelief();
    67. System.out.println(belief);
    68. proxyInstance.getBelief();
    69. proxyInstance.eat("四川麻辣烫");
    70. System.out.println("**********************************************************");
    71. NikeClothFactory nikeClothFactory = new NikeClothFactory();
    72. ClothFactory factory1 = (ClothFactory) ProxyFactory.getProxyInstance(nikeClothFactory);
    73. factory1.produceCloth();
    74. }
    75. }

    有个AOP的东西,面向切面编程,提了一嘴。