【Java语言特性学习之二】反射

一、概念
java加载class文件分两种情况:
(1)类型是编译器已知的,这种文件的.class文件在编译的时候,编译器会把.class文件打开(不加载)检查,称为Run- Time Type Identification 运行时类型识别
(2)从其它地方获取引用,然后动态的把这个未知类型的引用的对象的.class文件加载进jvm虚拟机里,称为反射;

在运行状态中,动态获取类信息(属性、方法)及动态调用类对象方法的功能称为java的反射机制。

二、反射API
Java反射包:java.lang.reflect.*
1、获取类
首先获取类,获取到类之后,Class类提供了很多获取类属性,方法,构造方法的api
(1)obj.getClass(),这个是Object类里面的方法;
(2)User.Class属性,任何的数据类型,基本数据类型或者抽象数据类型,都可以通过这种方式获取类;
(3)Class.forName(""),Class类提供了这样一个方法,让我们通过类名来获取到对象类,使用最多;

package reflect;

import reflect.test.model.User;

public class Main {

    public static void main(String[] args) throws ClassNotFoundException {
        
        //1.通过Object类里面的方法getClass()
        User u = new User();
        Class c = u.getClass();
        System.out.println(c);//class reflect.test.model.User

        //2通过.Class属性
        Class c2 = User.class;
        System.out.println(c2);//class reflect.test.model.User
        
        //3.Class.forName("全路径名")
        Class c3 = Class.forName("reflect.test.model.User");
        System.out.println(c3);//class reflect.test.model.User
    }
}

2、获取属性和方法

package reflect.test.model;

public class User {
    
    private String name;
    
    private int age;
    
    public User() {}
    public User(String name,int age) {
        this.name = name;
        this.age = age;
    }
    
    public int a = 100;
    
    private String str = "123456789";
    
    public boolean dosomething(Integer a,Float b) {
        System.out.println("dosomething");
        return true;
    }

}
package reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Main2 {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException {

        /************************获取所有的属性************************/
        Class<?> c = Class.forName("reflect.test.model.User");
        //getDeclaredFields 获取所有的属性
        Field[] fs = c.getDeclaredFields();

        // 定义可变长的字符串,用来存储属性
        StringBuffer sb = new StringBuffer();
        // 通过追加的方法,将每个属性拼接到此字符串中
        // 最外边的public定义
        sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() + "{\n");
        // 里边的每一个属性
        for (Field field : fs) {
            sb.append("\t");// 空格
            sb.append(Modifier.toString(field.getModifiers()) + " ");// 获得属性的修饰符,例如public,static等等
            sb.append(field.getType().getSimpleName() + " ");// 属性的类型的名字
            sb.append(field.getName() + ";\n");// 属性的名字+回车
        }

        sb.append("}");

        System.out.println(sb);
        
        /***************************获取指定属性***********************/
        
        //获取id属性  
        Field idF = null;
        try {
            idF = c.getDeclaredField("age");
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }  
        //实例化这个类赋给o  
        Object o = null;
        try {
            o = c.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }  
        //打破封装  
        idF.setAccessible(true); //使用反射机制可以打破封装性,导致了java对象的属性不安全。  
        //给o对象的id属性赋值"110"  
        try {
            //set  
            idF.set(o,110);
        } catch (IllegalArgumentException | IllegalAccessException e) {
            e.printStackTrace();
        } 
        //get  
        try {
            System.out.println(idF.get(o));
        } catch (IllegalArgumentException | IllegalAccessException e) {
            e.printStackTrace();
        }
        
        /***************************获取方法****************************/
        
        //getDeclaredMethods()    获取所有的方法(不包含构造方法)
        Method[] declaredMethods = c.getDeclaredMethods();
        for (Method m:declaredMethods) {
            System.out.println(m);
            //getReturnType()    获得方法的放回类型
            System.out.println(m.getReturnType());
            //getParameterTypes()    获得方法的传入参数类型
            Class<?>[] parameterTypes = m.getParameterTypes();
            for(Class cc : parameterTypes) {
                System.out.println(cc);
            }
        }

        //getDeclaredMethod("方法名",参数类型.class,……)    获得特定的方法
        Method declaredMethod = c.getDeclaredMethod("dosomething", Integer.class,Float.class);
        System.out.println(declaredMethod);
        Method method = c.getMethod("dosomething", Integer.class,Float.class);
        System.out.println(method);
        //getDeclaredConstructors()    获取所有的构造方法
        Constructor<?>[] declaredConstructors = c.getDeclaredConstructors();
        for(Constructor ccc : declaredConstructors) {
            System.out.println(ccc);
        }
        //getDeclaredConstructor(参数类型.class,……)    获取特定的构造方法
        Constructor<?> declaredConstructor = c.getDeclaredConstructor(String.class,int.class);
        System.out.println(declaredConstructor);
        //getSuperclass()    获取某类的父类
        Class<?> superclass = c.getSuperclass();
        System.out.println(superclass);
        //getInterfaces()    获取某类实现的接口
        Class<?>[] interfaces = c.getInterfaces();
        for(Class cccc: interfaces) {
            System.out.println(cccc);
        }
        
        
    }

}

结果:

public class User{
    private String name;
    private int age;
    public int a;
    private String str;
}
110
public boolean reflect.test.model.User.dosomething(java.lang.Integer,java.lang.Float)
boolean
class java.lang.Integer
class java.lang.Float
public boolean reflect.test.model.User.dosomething(java.lang.Integer,java.lang.Float)
public boolean reflect.test.model.User.dosomething(java.lang.Integer,java.lang.Float)
public reflect.test.model.User()
public reflect.test.model.User(java.lang.String,int)
public reflect.test.model.User(java.lang.String,int)
class java.lang.Object

三、反射应用--动态代理

package reflect.test.intf;

public interface Interface {

    public void dosomething() ;
}
package reflect.test.intf.impl;

import reflect.test.intf.Interface;

public class InterfaceImpl implements Interface {

    @Override
    public void dosomething() {
        System.out.println("dosomething");
    }

}

1、静态代理

package reflect;

import reflect.test.intf.Interface;
import reflect.test.intf.impl.InterfaceImpl;

/**
 * 静态代理
 */
public class HandProxy implements Interface{
    
    Interface inter = new InterfaceImpl();

    @Override
    public void dosomething() {
        System.out.println("静态代理类");
        inter.dosomething();
    }

}
package reflect;

public class TestHandProxy {

    public static void main(String[] args) {

        HandProxy p = new HandProxy();
        p.dosomething();
    }

}
结果:
静态代理类 dosomething

2、动态代理

package reflect;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 动态代理
 */
public class AutoProxy implements InvocationHandler{
    private Object target;
    
    public Object bind(Object target) {
        this.target = target;
        /**
         * 第一个是被代理类的类构造器,
         * 第二个指的是被代理类的接口,也就是Interface接口,
         * 第三个是实现这个代理的类,这里就是本类。
         * 这个方法执行了下面三步:
            1.生成一个实现了参数interfaces里所有接口且继承了Proxy的代理类的字节码,然后用参数里的classLoader加载这个代理类。
            2.使用代理类父类的构造函数 Proxy(InvocationHandler h)来创造一个代理类的实例,将我们自定义的InvocationHandler的子类传入。
            3.返回这个代理类实例,因为我们构造的代理类实现了interfaces(也就是我们程序中传入的target.getClass().getInterfaces())里的所有接口,因此返回的代理类可以强转成Interface类型来调用接口中定义的方法。
         */
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        System.out.println("动态代理");
        result = method.invoke(target, args);
        System.out.println("动态代理执行结束");
        return result;
    }

}
package reflect;

import reflect.test.intf.Interface;
import reflect.test.intf.impl.InterfaceImpl;

public class TestAutoProxy {

    public static void main(String[] args) {
        Interface inter = new InterfaceImpl();
        AutoProxy ap = new AutoProxy();
        Interface obj = (Interface)ap.bind(inter);
        obj.dosomething();
    }

}

结果:

动态代理
dosomething
动态代理执行结束

 

posted @ 2019-12-06 17:53  cac2020  阅读(192)  评论(0编辑  收藏  举报