Java学习-单元测试,反射,注解,动态代理

111 阅读2分钟

反射

反射获取类对象

try {    Class c = Class.forName("Client");    System.out.println(c);} catch (ClassNotFoundException e) {    throw new RuntimeException(e);}

反射获取构造器对象

获取构造器对象

            //        获取无参数的, public构造器            Class c = Class.forName("Client");//            Constructor constructor = c.getConstructor();            System.out.println(constructor.getName() + "参数个数" + constructor.getParameterCount());

//获取所有的构造器            Class c = Class.forName("Client");            System.out.println(c);//            获取类中全部的构造器对象            Constructor[] constructors = c.getDeclaredConstructors();//            遍历构造器            for (Constructor constructor : constructors) {                System.out.println(constructor.getName() + "参数个数======" + constructor.getParameterCount());            }

//        获取有参数的, public构造器            Class c = Class.forName("Client");//            Constructor constructor = c.getConstructor(String.class);            System.out.println(constructor.getName() + "参数个数" + constructor.getParameterCount());

使用构造器创建对象

            //        获取有参数的, public构造器            Class c = Class.forName("Client");//            Constructor constructor = c.getConstructor(String.class);//            如果构造器方法是私有的,那就使用setAccessible打开权限。进行暴力反射            constructor.setAccessible(true);            Client client =  (Client) constructor.newInstance("名称参数");            System.out.println(client.getName());            System.out.println(constructor.getName() + "参数个数" + constructor.getParameterCount());

反射技术,获取成员变量对象。并使用

//            获取所有的成员变量            Field[] fields = c.getDeclaredFields();            for (Field field : fields) {                field.setAccessible(true);                System.out.println(field.getName() + "类型"  + field.getType());            }//            根据名字获取成员变量            Field field = c.getDeclaredField("name");

field.setAccessible(true);//成员变量是私有的话,强行打开权限field.set(client, "给成员对象赋值");
String name = (String) field.get(client);//获取成员变量的值

反射获取方法对象

//            获取方法            Method[] methods = c.getDeclaredMethods();//            遍历方法            for (Method method : methods) {                System.out.println(method.getName() + "返回值类型" + method.getReturnType()                        + "获取参数类型" + method.getParameterTypes());            }//            获取单个方法            Method method = c.getDeclaredMethod("setName", String.class);

//            执行方法            method.invoke(client, "通过反射调用方法");            System.out.println(field.get(client));

反射的作用

ArrayList<Integer> list = new ArrayList<>();        list.add(1);        list.add(18);        //想要添加一个字符串就需要使用反射        Class c = list.getClass();//        获取添加方法        Method add = c.getDeclaredMethod("add", Object.class);//        执行该方法        Object bo = add.invoke(list, "添加字符串");        System.out.println(bo);        System.out.println(list);

true
[1, 18, 添加字符串] 

使用另外一种方式也可以做到以上的效果

ArrayList list2 = list;list2.add("另外一个字符串");System.out.println(list2);//[1, 18, 添加字符串, 另外一个字符串]

反射的作用----通用框架的底层原理

        try {            PrintStream ps = new PrintStream(new FileOutputStream("data.txt", true));//        第一步,获取类队形            Class c = object.getClass();            ps.println("================" + c.getSimpleName() + "==============");//        第二步。获取类对象中的所有方法和成员变量//        Method[] methods = c.getDeclaredMethods();            Field[] fields = c.getDeclaredFields();            for (Field field : fields) {                field.setAccessible(true);                String name = field.getName();//                获取成员变量的值                String value = field.get(object) + "";//通过运算的方式,将不同类型的值转化为字符串。不用强转是//                为了防止强转异常抛出                ps.println(name + "=" + value);            }            ps.close();        } catch (Exception e) {            e.printStackTrace();        }

注解

@Target({ElementType.METHOD, ElementType.TYPE})//注解在类和成员方法上@Retention(RetentionPolicy.RUNTIME)public @interface Book {    String value();//书名    double price();//价格    String[] authors();//作者}

@Book(value = "情深深域名梦",price = 120.5, authors = {"k", "Q"})public class BookStore {    private String shopName;    private List<Book> bookList;    @Book(value = "方法注解",price = 120.5, authors = {"老巫婆"})    public void test() {    }}

//        第一步,先得到类对象        Class c = BookStore.class;//        判断这个类上面是否有这个注解        if(c.isAnnotationPresent(Book.class)) {//            直接获取该注解对象            Book book = (Book) c.getDeclaredAnnotation(Book.class);            System.out.println(book.value());            System.out.println(book.price());            System.out.println(Arrays.toString(book.authors()));//            获取所有的方法            Method[] methods = c.getDeclaredMethods();            for (Method method : methods) {                if (method.isAnnotationPresent(Book.class)) {                    Book book1 = method.getDeclaredAnnotation(Book.class);                    System.out.println(book1.value());                    System.out.println(book1.price());                    System.out.println(Arrays.toString(book1.authors()));                }            }        }

  public static void main(String[] args) {//        第一步得到类队形        Main main = new Main();        Class c = main.getClass();//        获取类对象所有的成员方法        Method[] methods = c.getDeclaredMethods();//        根据类对象,生成实例对象,首先找到够找到构造器对象//        遍历        for (Method method : methods) {//            判断方法是否是被注解            if(method.isAnnotationPresent(MyTest.class)){                try {                    method.invoke(main);                } catch (IllegalAccessException e) {                    throw new RuntimeException(e);                } catch (InvocationTargetException e) {                    throw new RuntimeException(e);                }            }        }    }

动态代理

接口

public interface Skill {    public void jump();    public void song();}

public class Star implements Skill {    private String name;    public Star(String name) {        this.name = name;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    @Override    public void jump() {        System.out.println(name+"正在跳舞");    }    @Override    public void song() {        System.out.println(name + "正在唱歌");    }}

代理类

import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class StarAgentProxy {    public static Skill getProxy(Star obj) {//        为明星对象创建一个代理对象        return (Skill) Proxy.newProxyInstance(obj.getClass().getClassLoader(),                obj.getClass().getInterfaces(), new InvocationHandler() {                    @Override                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                        Object rs =method.invoke(obj, args);                        return rs;                    }                });    }}

调用

Skill skill = StarAgentProxy.getProxy(new Star("杨超越")) ;skill.jump();;skill.song();

案例,了解做代理的好处。

代理存在的意义,其实就是为了将重复的代码放在代码核心处理程序中