反射
反射位于java.lang.reflect包类,还是那句话,有兴趣的同学可以去瞅瞅,反正代码挺好看的。
下面主要讲的是这几个类,Method,Field,Type(子实现类GenericArrayType,WildcardType,TypeVariable,ParameterizedType)
当然有核心的类Class了,Proxy放在下一章讲。
1.java.lang.reflect.Array 动态创建数组的。示例如下:
Object obg = Array.newInstance(String.class,5);
Array.set(obg,0,"rulang0");
Array.set(obg,1,"rulang1");
String[] value = (String[])obg;
System.out.println(value[1]);//输出:rulang1
2.java.lang.reflect.Constructor 构造函数
/* ********* _getConstructor()_ 和 _getDeclaredConstructor()_ 区别:*********
getDeclaredConstructor(Class<?>... parameterTypes)
这个方法会返回制定参数类型的所有构造器,包括public的和非public的,当然也包括private的。
getDeclaredConstructors()的返回结果就没有参数类型的过滤了。
再来看getConstructor(Class<?>... parameterTypes)
这个方法返回的是上面那个方法返回结果的子集,只返回制定参数类型访问权限是public的构造器。
getConstructors()的返回结果同样也没有参数类型的过滤。*/
Class<?> cls = Class.forName("com.rulang.reflect.RuLangDemo");
Constructor constructor1=cls.getConstructor(new Class[]{});
System.out.println("修饰符: "+ Modifier.toString(constructor1.getModifiers()));
System.out.println("构造函数名: "+constructor1.getName());
System.out.println("参数列表: "+constructor1.getParameterTypes());
Object obj = constructor1.newInstance();
// System.out.println("调用默认构造函数生成实例:"+obj.toString());
// Constructor constructor2 = cls.getConstructor(new Class[]{String.class});
Constructor constructor2 = cls.getDeclaredConstructor(new Class[]{String.class});//getConstructor
System.out.println("修饰符: "+Modifier.toString(constructor2.getModifiers()));
System.out.println("构造函数名: "+constructor2.getName());
System.out.println("参数列表: "+constructor2.getParameterTypes());
RuLangDemo obj2 = (RuLangDemo) constructor2.newInstance(new Object[]{"rulang"});
// Constructor constructor3 = cls.getDeclaredConstructor(new Class[]{String.class}); 此处会抱错
Constructor constructor3 = cls.getDeclaredConstructor(new Class[]{int.class});
System.out.println("修饰符: "+Modifier.toString(constructor3.getModifiers()));
System.out.println("构造函数名: "+constructor3.getName());
System.out.println("参数列表: "+constructor3.getParameterTypes());
//下面的代码会抱错的,因为是私有构造函数,没法这样处理。
//RuLangDemo obj3 = (RuLangDemo) constructor3.newInstance(new Object[]{Integer.valueOf(999)});
输出的内容是:
修饰符: public
构造函数名: com.rulang.reflect.RuLangDemo
参数列表: [Ljava.lang.Class;@14ae5a5
修饰符: public
构造函数名: com.rulang.reflect.RuLangDemo
参数列表: [Ljava.lang.Class;@6d6f6e28
修饰符: private
构造函数名: com.rulang.reflect.RuLangDemo
参数列表: [Ljava.lang.Class;@135fbaa4
java.lang.reflect.Field
1.getDeclaredField(String name): 是可以获取一个类的其中一个字段
2.getDeclaredFields():是可以获取一个类的所有字段
3.getField(String name): 获取其中一个obj的字段
4.getFields(): 主要是public字段所有的
5.getType(): 获取属性声明时类型对象(返回class对象)
6.getGenericType() : 返回属性声的Type类型
7.getName() : 获取属性声明时名字
8.getAnnotations() : 获得这个属性上所有的注释
9.getModifiers() : 获取属性的修饰
10.isEnumConstant() : 判断这个属性是否是枚举类
11.isSynthetic() : 判断这个属性是否是 复合类
12.get(Object obj) : 取得obj对象这个Field上的值
13.set(Object obj, Object value) : 向obj对象的这个Field设置新值value
RuLangDemo demo=new RuLangDemo();
System.out.println(demo.getmStr());//输出:xixi
Field field=demo.getClass().getDeclaredField("mStr");
field.setAccessible(true);
field.set(demo,"rulang");
System.out.println(demo.getmStr());//输出:rulang1
4.java.lang.reflect.Method
1.getMethods(): 获得类的public类型的方法
2.getMethod(String name, Class[] params): 获得类的特定方法,name参数指定方法的名字,params参数指定方法的参数类型
3.getDeclaredMethods(): 获取类中所有的方法(public、protected、default、private)
4.getDeclaredMethod(String name, Class[] params): 获得类的特定方法,name参数指定方法的名字,params参数指定方法的参数类型
RuLangDemo demo=new RuLangDemo();
System.out.println(demo.getmStr());//输出:xixi
Method setmStrMethod = demo.getClass().getMethod("setmStr", new Class[]{String.class});
System.out.println("修饰符: " + Modifier.toString(setmStrMethod.getModifiers()));
setmStrMethod.setAccessible(true); // 修饰符 如果是私有的,必须设置这个
setmStrMethod.invoke(demo, "rulang"); // 方法调用哦
System.out.println(demo.getmStr());//输出:rulang1
5.java.lang.reflect.Type
Type是所有类型的父接口, 如原始类型(raw types 对应 Class)、
参数化类型(parameterized types 对应 ParameterizedType)、 数组类型
(array types 对应 GenericArrayType)、 类型变量(type variables 对应 TypeVariable )
基本(原生)类型(primitive types 对应 Class),。
子接口有 ParameterizedType, TypeVariable, GenericArrayType, WildcardType, 实现类有Class。
(1)ParameterizedType 是什么样的呢?
文档上有说明哦 ParameterizedType represents a parameterized type such as Collection<String>
Map<String, Object> map;
Set<String> set;
Class<?> class;
List<String> list; 这都是ParameterizedType类型哦
Type[] getActualTypeArguments(); Map<String,Object> map 这个ParameterizedType返回的是 String 类。
Object类的全限定类名的 Type Array。
Type getRawType()Map<String,Object> map 这个 ParameterizedType 返回的是 Map 类的全限定类名的 Type Array。
Type getOwnerType();Map<String,Object> map 这个 ParameterizedType 的 getOwnerType() 为 null,
而 Map.Entry<String,String> map 的 getOwnerType() 为 Map 所属于的 Type。
public class Test {
private Map<String,Object> map=null;
private Map.Entry<String, String> map1=null;
public static void main(String[] jiexieQi) throws Exception {
Field map=Test.class.getDeclaredField("map");
Field map1=Test.class.getDeclaredField("map1");
ParameterizedType mapType = (ParameterizedType) map.getGenericType();
ParameterizedType map1Type = (ParameterizedType) map1.getGenericType();
System.out.println(mapType.getOwnerType());//输出:null
System.out.println(map1Type.getOwnerType());//输出:interface java.util.Map
System.out.println(mapType.getActualTypeArguments()[0]);//输出:class java.lang.String
System.out.println(mapType.getActualTypeArguments()[1]);//输出:class java.lang.Object
}
(2)TypeVariable:是各种类型变量的公共父接口,就是泛型里面的类似T、E。
TypeVariable,类型变量,描述类型,表示泛指任意或相关一类类型,也可以说狭义上的泛型(泛指某一类类型),
一般用大写字母作为变量,比如K、V、E等
TypeVariable 源码如下:
public interface TypeVariable<D extends GenericDeclaration> extends Type {
//获得泛型的上限,若未明确声明上边界则默认为Object
Type[] getBounds();
//获取声明该类型变量实体(即获得类、方法或构造器名)
D getGenericDeclaration();
//获得名称,即K、V、E之类名称
String getName();
}
(3)GenericArrayType:表示一种元素类型是参数化类型或者类型变量的数组类型,比如List<>[],T[]这种。
public class Test {
private List<String> [] listArray; //GenericArrayType 转为Class哦
public static void main(String[] jiexieQi) throws Exception {
Field listArray=Test.class.getDeclaredField("listArray");
Type typeList=listArray.getGenericType();
GenericArrayTypeImpl ty= (GenericArrayTypeImpl) typeList;
ParameterizedType uu= (ParameterizedType) ty.getGenericComponentType();
System.out.println(uu.getTypeName());//输出:java.util.List<java.lang.String>
}
(4)WildcardType:代表一种通配符类型表达式,类似? super T这样的通配符表达式。
源码如下:
public interface WildcardType extends Type {
//获得泛型表达式上界(上限)
Type[] getUpperBounds();
//获得泛型表达式下界(下限)
Type[] getLowerBounds();
}
public <T> void test(List<? extends classA > a){}
Method method = Main.class.getMethod("test",List.class);
Type[] upperBounds = null;
Type[] lowerBounds = null;
Type[] types = method.getGenericParameterTypes();
for(Type type : types){
Type[] actualTypeArgument = ((ParameterizedType)type).getActualTypeArguments();
for(Type t : actualTypeArgument){
WildcardType wildcardType = (WildcardType) t;
lowerBounds = wildcardType.getLowerBounds();
upperBounds = wildcardType.getUpperBounds();
System.out.println("通配符表达式类型是:"+ wildcardType);
if(upperBounds.length != 0){
System.out.println("表达式上边界:"+Arrays.asList(upperBounds));
}
if(lowerBounds.length != 0){
System.out.println("表达式下边界:"+Arrays.asList(lowerBounds));
}
}
}
//输出结果
通配符表达式类型是:? extends com.fcc.test.classA
表达式上边界:[class com.fcc.test.classA]
次章结束,下一章将Proxy讲一下之后,将讲Retrofit源码分析。