Java19:反射

一:反射的理解

Reflection(反射)是指被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API 取得任何类的内部信息,并直接操作任意对象的内部属性及方法。

框架=反射+注解+设计模式

二:体会反射机制的“动态性”

// 创建一个指定类的对象,classpath:指定类的全类名
public  Object getInstance(String classpath) throws Exception {

    Class clazz = Class.forName(classpath);

    return clazz.newInstance();
}

@Test
public void test2()  {
    Random random = new Random();
    String classpath="";
    for (int i = 0; i < 100; i++) {
        int number = random.nextInt(3);
        switch (number) {
            case 0:
                classpath = "java.util.Date";
                break;

            case 1:
                classpath = "java.lang.Object";
                break;
            case 2:

                classpath = "com.cn.test.Person";
                break;

        }

        try {
      Object obj=getInstance(classpath);
            System.out.println(obj);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

三:反射机制能提供的功能

》在运行时判断任意一个对象所属的类

》在运行时构造任意一个类的对象

》在运行时判断任意一个类所具有的成员变量和方法

》在运行时获取泛型信息

》在运行时调用任意一个对象的成员变量和方法

》在运行时处理注解

》生成动态代理

四:相关API

java.lang.Class  :反射的源头

java.lang.reflect.Method

java.lang.reflect.Field

java.lang.reflect.Constructor

五:关于Class类的理解

1.类的加载过程:

程序经过javac.exe命令以后,会生成一个或多个字节码文件(.class结尾)。

接着我们使用java.exe 命令 对某个字节码文件进行解释运行。相当于将某个字节码文件加载到内存中,在此过程就称为类的加载。加载到内存中的类,我们称为运行时类,此运行时类,就作为Class 的一个实例。

2.换句话说,Class的实例 对应着 一个运行时类。

3.加载到内存中的运行时类会缓存一定的时间,在此时间之内,我们可以通过不同方式来获取此运行时类。

4.获取Class实例的几种方式:

@Test
public void test3() throws ClassNotFoundException {
    //1.调用类.class 属性,获取Class实例
    Class class1= Person.class;
    System.out.println(class1);
    Person p =new Person();
    //2.调用getClass(),获取Class实例
    Class class2= p.getClass();
    System.out.println(class2);
    //3.Class.forName,获取Class实例
    Class class3 = Class.forName("com.cn.test.Person");
    System.out.println(class3);
    //4.调用类的加载器getClassLoader(),获取Class实例
    ClassLoader classLoader = Reflection1Test.class.getClassLoader();
    Class class4= classLoader.loadClass("com.cn.test.Person");
    System.out.println(class4);
    //System.out.println(class1==class2);

5. 总结:创建类的对象的方式

方式一: new + 构造器

方式二:要创建Xxx类的对象,可以考虑:Xxx/Xxxs 类是否有静态方法存在,可以调用其静态方法,创建Xxx对象。

方式三:通过反射

6.Class实例可以是哪些结构的说明

1)class:外部类,成员(成员内部类,静态内部类)局部内部类,匿名内部类

2)interface:接口

3) []:数组

4)enum:枚举

5)annotation:注解@interface

6)primitive type:基本数据类型

7)void

7.类的加载器,加载配置文件

@Test
public void test3() throws IOException {
    //方式一
    Properties pro =new Properties();
    FileInputStream fis =new FileInputStream("jdbc.propertities");
    pro.load(fis);
    String name = pro.getProperty("name");
    String age = pro.getProperty("age");
    System.out.println(name+":"+age);


}
@Test
public void test4() throws IOException {
  //方式二,该方式文件放在src目录下
    ClassLoader classLoader = Reflection2Test.class.getClassLoader();
    InputStream resourceAsStream = classLoader.getResourceAsStream("jdbc2.propertities");
    Properties pro =new Properties();
    pro.load(resourceAsStream);
    String name = pro.getProperty("name");
    String age = pro.getProperty("age");
    System.out.println(name+":"+age);

}

六:反射的实例

1.获取所有的属性,方法,构造器

@Test
public void test2() {

    Class clazz = Person.class;
    //获取运行时类及其所有父类的public方法
    Method[] methods = clazz.getMethods();
    for (Method m : methods) {
        System.out.print(m + "\t");
        System.out.println(m.getName());
    }

    System.out.println();
    //获取运行时类所有方法
    Method[] declaredMethods = clazz.getDeclaredMethods();
    for (Method m : declaredMethods) {
        System.out.print(m + "\t");
        System.out.println(m.getName());
    }


}

@Test
public void test3() {

    Class clazz = Person.class;
    //获取运行时类所有public的构造器
    Constructor[] constructors = clazz.getConstructors();
    for(Constructor c:constructors){
        System.out.println(c);
    }
    System.out.println();
    //获取运行时类所有构造器
    Constructor[] constructors2 = clazz.getDeclaredConstructors();
    for(Constructor c:constructors2){
        System.out.println(c);
    }

}
@Test
public void test4() throws Exception {
    //获取当前运行时类父类的对象
    Class superclass = Person.class.getSuperclass();
    System.out.println(superclass);

}

2.获取指定的属性,方法,构造器

@Test
public  void filedTest() throws Exception {
    Class clazz=Person.class;
    Object obj = clazz.newInstance();
     Person per= (Person) obj;
     //获取指定属性
    Field name = clazz.getDeclaredField("name");
    //给指定对象属性复制
    name.set(per,"tom");
    System.out.println(name.get(per));
    //给静态属性赋值,并获取
    Field hobbies = clazz.getDeclaredField("hobbies");
    hobbies.set(clazz,"baskball");
    System.out.println(hobbies.get(clazz));
}


@Test
public  void methodTest() throws Exception {

    Class clazz=Person.class;
    Object obj = clazz.newInstance();
    Person per= (Person) obj;
    //获取public 无参方法 并调用
    Method info = clazz.getDeclaredMethod("info");
    info.invoke(per);
    //获取public 有参方法 并调用
    Method getNation = clazz.getDeclaredMethod("getNation",String.class);
    getNation.invoke(per,"china");
    //获取静态方法并调用
    Method study = clazz.getDeclaredMethod("study");
    study.invoke(clazz);
    //获取私有方法并调用
    Method getAge = clazz.getDeclaredMethod("getAge", int.class);
    //设置为可访问
    getAge.setAccessible(true);
    System.out.println(getAge.invoke(per, 20));


}

@Test
public  void ConstructTest() throws Exception {
   Class clazz= Person.class;
   //该方法为常用用法,具有通用性
    Object o = clazz.newInstance();
    System.out.println(o);
    //获取带有参数的构造器,不常用
    Constructor constructor = clazz.getDeclaredConstructor(int.class, String.class);
    constructor.setAccessible(true);
    Object jerry = constructor.newInstance(15, "jerry");
    System.out.println(jerry);


}



七:反射的应用:动态代理

1.静态代理:

interface ColthFactory{
   void  produceColth();
}
//代理类
class ProxyColthFactory implements ColthFactory{
    private ColthFactory factory;

    public ProxyColthFactory(ColthFactory factory){
        this.factory=factory;
    }

    @Override
    public void produceColth() {
        System.out.println("生产衣服之前的准备工作");
        factory.produceColth();
        System.out.println("生产衣服之后的收尾工作");

    }
}
//被代理类
class NIkeColthFactory implements  ColthFactory{

    @Override
    public void produceColth() {
        System.out.println("NIKE生产衣服");
    }
}

public class StaticProxyTest {
    public static void main(String[] args) {
        //创建被代理类对象
        NIkeColthFactory nike =new NIkeColthFactory();
        //创建代理类对象
        ProxyColthFactory proxy =new ProxyColthFactory(nike);
        //调用方法
        proxy.produceColth();
    }
}

2.动态代理:

class ProxyFactory{

    public static Object getInstance(Object obj){
        MyInvocationHandler hander= new MyInvocationHandler();
        hander.blind(obj);
        return  Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), hander);

    }
}

class MyInvocationHandler implements InvocationHandler{
    private Object obj; //赋值时必须传被代理类实例
    public void blind(Object obj){
        this.obj=obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object invoke = method.invoke(obj, args);// method为代理类调用的方法,此方法也作为被代理类对象要调用的方法
        return invoke;
    }
}

public class ProxyTest {
    public static void main(String[] args) {
        NIkeColthFactory nike = new NIkeColthFactory();
        ColthFactory  colthFactory= (ColthFactory) ProxyFactory.getInstance(nike);
        colthFactory.produceColth();

    }
}

你可能感兴趣的:(java,java,开发语言)