JAVASE--08


反射


java中提供的动态执行API,可以动态检查对象的类型,对象类型的内部结构,还能动态创建对象,动态执行方法等.

public static void main(String[] args) {
    test(123);//class java.lang.Integer
    test("wome");//class java.lang.String
    test(new File("./"));//class java.io.File
    test(new ArrayList<Double>());//class java.util.ArrayList   

    Collection<String> c = new ArrayList<>();
    Iterator<String> it = c.iterator();
    //it的具体对象的类型是什么?
    test(it);//class java.util.ArrayList$Itr,ArrayList的内部类Itr   
}

public static void test(Object obj){
/*
 * obj的具体类型是什么?
 * 如何在方法中检查对象的具体类型?
 * 利用反射API可以动态检查对象的类型
 * Object类上定义了getClass,用于检查软件执行期间对象的具体类型
 */
Class cls = obj.getClass();
System.out.println(cls);

/*
 * 进一步动态检查类型的内部结构
 * 1:检查类型声明的全部成员变量
 * Declared  声明    Fields 字段,成员变量
 * getDeclaredFields()的功能是检查cls代表的类型中全部的字段(成员变量)
 */
Field[] fields = cls.getDeclaredFields();
for (Field field : fields) {
    System.out.println("****" + field);
}

/*
 * 2:检查类中声明的方法
 * getDeclaredMethods():动态获取当前类中声明的方法信息,不包含继承的方法
 * getMethods():获取当前类和从父类中继承的方法
 */
Method[] methods = cls.getDeclaredMethods();
for (Method m : methods) {
    System.out.println("---" + m);
}

/*
 * 3:检查类中声明的构造方法
 * getDeclaredConstructors():动态获取当前类中声明的构造方法,不包含继承的
 * getConstructors():动态获取当前类和父类中继承的方法
 */
Constructor[] constructors = cls.getDeclaredConstructors();
for (Constructor constructor : constructors) {
    System.out.println("~~~~"+constructor);
}
}


动态检查对象的类型


Class cls = obj.getClass();


对象类型的内部结构


Field[] fields = cls.getDeclaredFields();
Method[] methods = cls.getDeclaredMethods();
Constructor[] constructors = cls.getDeclaredConstructors();


反射API动态加载类,动态创建对象

Class cls = Class.forName(类名);

/**
 * 动态加载类,创建对象
 * 如下方法可以动态加载任何类,创建其对象
 * 注意:类型必须有无参构造器
 * @author Mr.Huang
 * @date 2018年8月8日
 */
Scanner scan = new Scanner(System.in);
System.out.println("请输入一个类全名package.className:");
String className = scan.nextLine();
// Class.forName(类名)动态加载类到方法区,类名错误抛异常
try {
    Class cls = Class.forName(className);// 类找不到报异常
    // 显示加载的结果
    System.out.println(cls);
    // 动态创建对象
    Object obj = cls.newInstance();// 默认使用的是空参构造类没有空参构造就会抛异常
    // 显示创建好的对象
    System.out.println(obj);
} catch (ClassNotFoundException e) {//类找不到
    e.printStackTrace();
} catch (InstantiationException e) {//没有空参构造
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
}


反射动态调用对象的方法


Foo f = new Foo();
f.test();
动态调用:运行期间动态给出方法名,如果输入的是test则执行test()方法,输入demo就执行demo()方法
动态执行方法:invoke :调用
* 1:先在类中找到方法 method 对象 * 2:在method上调用invoke()就是执行方法,需要传递包含方法的对象作为参数.
method.invoke(包含方法的对象,传递参数...)
try {
    System.out.println("请输入方法名:");
    String methodName = scan.nextLine();
    //根据方法名动态查找方法getDeclaredMethod,查找一个方法
    Method method = cls.getDeclaredMethod(methodName);
    //动态执行方法
    method.invoke(obj);
} catch (NoSuchMethodException e) {
    e.printStackTrace();
} catch (SecurityException e) {
    e.printStackTrace();
} catch (IllegalArgumentException e) {
    e.printStackTrace();
} catch (InvocationTargetException e) {
    e.printStackTrace();
}


反射的用途


反射API用途之一:访问不可见的属性,方法
//在动态执行方法之前,打开访问权限,可以访问私有方法
method.setAccessible(true);
反射的核心用途: 1:将一段程序于另外一段程序进行解耦
案例:单元测试工具原型
执行一个类中的全部的以test为开头的方法
1:类有无参构造
2:方法都是无参数方法
解决方案:
1:动态输入类名
2:动态加载类
3:动态创建类型的实例
4:动态查找类型全部方法
5:遍历检查每个方法的名,如果是以test开头,则利用发射API执行方法

try {
//1:动态输入类名
System.out.println("请输入全类名:");
Scanner scan = new Scanner(System.in);
String className = scan.nextLine();
//2:动态加载类
Class cls = Class.forName(className);
//3:动态创建类型的实例
Object obj = cls.newInstance();
//4:动态查找类型的全部方法
Method[] methods = obj.getClass().getDeclaredMethods();
for (Method method : methods) {
    //System.out.println("===" + method.getName());
    //5:遍历检查每个方法的名,如果是以test开头,则利用发射API执行方法
    if(method.getName().startsWith("test")){
        //Method m = cls.getDeclaredMethod(method.getName());
        method.setAccessible(true);
        method.invoke(obj);
    }
}
} catch (Exception e) {
    e.printStackTrace();
}


利用反射调用有参数的方法


1:查找有参数方法 Method method = cls.getDeclaredMethod(方法名,参数类型1,参数类型2...)
2:动态调用执行 method.invoke(对象,参数1,参数2...)

 

Scanner scan = new Scanner(System.in);
System.out.print("请输入全类名;");
String className = scan.nextLine();
System.out.print("请输入方法名:");
String methodName = scan.nextLine();
try {
    //1:动态加载类
    Class cls = Class.forName(className);
    //2:动态创建对象
    Object obj = cls.newInstance();
    //3:查找有参数的方法,第一个参数是方法名,随后参数是类型.class
    //找不到就会抛异常
    Method method = cls.getDeclaredMethod(methodName,int.class,String.class);
    //4:动态获取参数
    System.out.print("请输入第一个参数p1:");
    String p1 = scan.nextLine();
    System.out.print("请输入第一个参数p2:");
    String p2 = scan.nextLine();
    int n = Integer.parseInt(p1);
    //5:动态执行方法
    Object val = method.invoke(obj, n,p2);
    System.out.println(val);
} catch (Exception e) {
    e.printStackTrace();
}


紧耦合


组件和组件之间是紧密关联的关系.


松耦合


组件和组件之间不是紧密关联的关系,可以将组件进行重新组合,可以进行组件替换


解耦


将组件关系从紧耦合改编为松耦合称为解耦

利用反射实现松耦合

反射API可以动态解析注解=====解析的只有运行期的注解

自定义注解

 

注解可以分为SOURCE|CLASS|RUNTIME
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
 * 自定义注解
 * Retention:用于声明注解的存在范围SOURCE|CLASS|RUNTIME
 * 代表着注解的存在范围;
 * SOURCE:存在于源代码中
 * CLASS:存在于源代码和字节码中
 * RUNTIME:存在于源代码.字节码以及运行期
 * 反射API能获取到的注解形式只能是运行期注解
 * 
 * @author Mr.Huang
 * @date 2018年8月8日
 */
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {

}
动态解析注解
try {
    //动态加载类
    Class cls = Class.forName(className);
    //动态查找全部方法
    Method[] methods = cls.getDeclaredMethods();

    /*Annotation[] ann = cls.getAnnotations();
    for (Annotation annotation : ann) {
        System.out.println("类名" + annotation);
    }*/
    /*
     * 方法上的注解
     */
    for (Method method : methods) {
        //method  代表cls 类上的每一个方法
        //Annotation  注解,getAnnotations(),用于获取标注在方法上的全部注解
        System.out.println("方法名" + method.getName());
        Annotation[] annotations = method.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println("    "+annotation);
        }
    }
} catch (Exception e) {
    e.printStackTrace();
}


自定义Junit测试工具

import java.lang.reflect.Method;
/**
 * 注解的用途演示
 * 
 * 实现一个工具,自动执行类中标注了@MyAnnotation的方法
 *
 * @author Mr.Huang
 * @date 2018年8月8日
 */
public class Junit {
public static void main(String[] args) {
        try {
            String className = "reflect.DemoAll";
            Class cls = Class.forName(className);
            Method[] methods = cls.getDeclaredMethods();
            for (Method method : methods) {
                //检查每个方法上是否包含@MyAnnotation注解
                /*
                 * method.getAnnotation检查方法上是否包含 了MyAnnotation的注解,如果包含则返回注解类型,不包含则返回null
                 */
                MyAnnotation ann = method.getAnnotation(MyAnnotation.class);
                if(ann != null){
                    //找到注解
                    method.invoke(cls.newInstance());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
东南亚位于我国倡导推进的“一带一路”海陆交汇地带,作为当今全球发展最为迅速的地区之一,近年来区域内生产总值实现了显著且稳定的增长。根据东盟主要经济体公布的最新数据,印度尼西亚2023年国内生产总值(GDP)增长5.05%;越南2023年经济增长5.05%;马来西亚2023年经济增速为3.7%;泰国2023年经济增长1.9%;新加坡2023年经济增长1.1%;柬埔寨2023年经济增速预计为5.6%。 东盟国家在“一带一路”沿线国家中的总体GDP经济规模、贸易总额与国外直接投资均为最大,因此有着举足轻重的地位和作用。当前,东盟与中国已互相成为双方最大的交易伙伴。中国-东盟贸易总额已从2013年的443亿元增长至 2023年合计超逾6.4万亿元,占中国外贸总值的15.4%。在过去20余年中,东盟国家不断在全球多变的格局里面临挑战并寻求机遇。2023东盟国家主要经济体受到国内消费、国外投资、货币政策、旅游业复苏、和大宗商品出口价企稳等方面的提振,经济显现出稳步增长态势和强韧性的潜能。 本调研报告旨在深度挖掘东南亚市场的增长潜力与发展机会,分析东南亚市场竞争态势、销售模式、客户偏好、整体市场营商环境,为国内企业出海开展业务提供客观参考意见。 本文核心内容: 市场空间:全球行业市场空间、东南亚市场发展空间。 竞争态势:全球份额,东南亚市场企业份额。 销售模式:东南亚市场销售模式、本地代理商 客户情况:东南亚本地客户及偏好分析 营商环境:东南亚营商环境分析 本文纳入的企业包括国外及印尼本土企业,以及相关上下游企业等,部分名单 QYResearch是全球知名的大型咨询公司,行业涵盖各高科技行业产业链细分市场,横跨如半导体产业链(半导体设备及零部件、半导体材料、集成电路、制造、封测、分立器件、传感器、光电器件)、光伏产业链(设备、硅料/硅片、电池片、组件、辅料支架、逆变器、电站终端)、新能源汽车产业链(动力电池及材料、电驱电控、汽车半导体/电子、整车、充电桩)、通信产业链(通信系统设备、终端设备、电子元器件、射频前端、光模块、4G/5G/6G、宽带、IoT、数字经济、AI)、先进材料产业链(金属材料、高分子材料、陶瓷材料、纳米材料等)、机械制造产业链(数控机床、工程机械、电气机械、3C自动化、工业机器人、激光、工控、无人机)、食品药品、医疗器械、农业等。邮箱:market@qyresearch.com

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值