Java基础之—反射(高级用法)

一、项目中最常见用法 (读取配置文件)

package com.todoming.reflect;
import java.io.FileReader;
import java.lang.reflect.Method;
import java.util.Properties;
public class ReadProperties {
    //获取配置文件属性
    public static String getValue() throws Exception{
        //获取配置文件的对象
        Properties properties=new Properties();
        //获取输入流
        FileReader reader=new FileReader("app.properties");
        //将流加载到配置文件对象中 
        properties.load(reader);
        reader.close();
        return properties.getProperty("message");
    }
    public static void main(String[] args) throws Exception{
        Class cla = Class.forName(getValue());
        Method method = cla.getDeclaredMethod("showMessage",String.class);
        Object object = cla.newInstance();
        //调用配置文件中类的方法
        method.invoke(object,"hahaha");
    }
}

二 获取泛型的返回类型

先看段代码:

package com.todoming.reflect;
import java.util.ArrayList;
import java.util.List;
public class Generic {
    public static void main(String[] args) throws Exception {
        List<Integer> list = new ArrayList<>();
        list.add(10);
        //通过反射调用 list的add方法
        list.getClass().getMethod("add",Object.class).invoke(list,"hahah");
        System.out.println(list.toString());
    }
}

这里定义了一个只能存入int类型的List 在通过反射调用add方法时缺可以插入一个string类型的值。
这个要从泛型的原理说起:Java中的泛型基本上都是在编译器这个层次来实现的。在生成的Java字节码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会在编译器在编译的时候去掉。这个过程就称为类型擦除。所以java的泛型是一种伪泛型。反射是在运行状态中获取的,所以通过反射调用的时候我们声明的类型已经被擦除了。这个有时候会导致类型转换失败的问题。

可以通过反射的方式获取返回泛型方法的返回类型。
在University类中添加如下方法

public List<String> getList(String name){
        List<String> list = new ArrayList<>();
        list.add(name);
        return list;
    }

获取返回类型

package com.todoming.reflect;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public class GetGenericReturn {
    public static void main(String[] args) throws Exception{
        Class cla = Class.forName("com.todoming.reflect.University");
        //这里University类中getList方法
        Method method = cla.getMethod("getList",String.class);
        //获取方法的返回类型对象
        Type returnType = method.getGenericReturnType();
        //判断该type对象能不能转型为ParameterizedType
        if (returnType instanceof ParameterizedType){
            ParameterizedType parameterizedType = (ParameterizedType)returnType;
            //调用getActualTypeArguments得到参数化类型的数组
            Type[] types = parameterizedType.getActualTypeArguments();
            for (Type type:types){
                //转型为Class对象
                Class returnTy = (Class)type;
                System.out.println(returnTy);
            }
        }
    }
}

使用上比较灵活些 不局限与以上这一种写法。关于java泛型的类型擦除有时间研究下。

三、操作数组

Java反射可以对数组进行操作,包括创建一个数组,访问数组中的值,以及得到一个数组的Class对象。

 //创建一个int类型的数组,长度为3
 int[] arr = (int[])Array.newInstance(int.class,10);
 //通过反射的形式,给数组赋值
 for (int i = 0 ;i < arr .length;i++){
       arr .set(arr ,i,i + 2);
 }
//通过反射的形式,得到数组中的值
for (int i = 0 ; i < arr .length;i++){
      System.out.println(Array.get(arr ,i));
}

除以上基本操作外还有些奇怪的用法。

Class clz = Class.forName("[I");
System.out.println(clz.getTypeName());

输出:int[]
forName中的字符串,[表示是数组,I表示是int,float就是F,double就是D 。

Class stringClz = Class.forName("[Ljava.lang.String;");

上面这种用法是获取一个普通对象数组的用法
[表示是数组,L的右边是类名,类型的右边是一个;。
有法基本完了下次看看反射的原理。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 在经过一次没有准备的面试后,发现自己虽然写了两年的android代码,基础知识却忘的差不多了。这是程序员的大忌,没...
    猿来如痴阅读 7,915评论 3 10
  • 一、Java 简介 Java是由Sun Microsystems公司于1995年5月推出的Java面向对象程序设计...
    子非鱼_t_阅读 9,785评论 1 44
  • 整体Retrofit内容如下: 1、Retrofit解析1之前哨站——理解RESTful 2、Retrofit解析...
    隔壁老李头阅读 10,096评论 2 12
  • 今天起了个大早!对!七点多!〈ps:众人听到一阵嘘嘘,楼猪你怎么可以这么扯淡!七点还叫啥大早!〉 而今天又是个美...
    游尘浮影阅读 1,293评论 0 1
  • 题记:我想让写作变成清晨唤醒我的鸟鸣,午间小憩的甜梦,傍晚散步的晚风。 其实是不知道我是否能坚持写作,至少希望不会...
    下铺兄弟阅读 3,788评论 0 50