概述
#一、项目中最常见用法 (读取配置文件)
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的右边是类名,类型的右边是一个;。
有法基本完了下次看看反射的原理。
最后
以上就是可爱盼望为你收集整理的Java基础之—反射(高级用法)的全部内容,希望文章能够帮你解决Java基础之—反射(高级用法)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复