2016-11-5
Java 反射机制
1. 映射类的创建三种方法
String.class,Class.forName("完整类名"),new String("abc").getClass()实例创建 ;
String str ="acc";
String str2 ="accd";
System.out.println( String.class == str.getClass());//true 内存中只有一份该类的映射类,
System.out.println( String.class == str2.getClass() );//true
System.out.println( String.class == Class.forName("java.lang.String") );//true
//
System.out.println( int.class == Integer.class );//false 基本类型和它的包装类不一样的.
System.out.println( int.class == Integer.TYPE );//true,Integer.TYPE 获得包装类其基本类型映射类2. 构造方法的反射
//映射String类的 String(StringBuffer buffer) 构造方法
Constructor constructor1 = String.class.getConstructor( StringBuffer.class );//映射成String的 String(StringBuffer buffer) 构造方法
String str3 = (String)constructor1.newInstance( new StringBuffer("abc") );//用构造方法映射类创建 String 对象.
System.out.println( str3.charAt(0) );3. 成员变量的反射
class Point{
private int x;
public int y;
public void abc(){
System.out.println("x="+x+" y="+y);
}
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
Point p1 = new Point(3,5);
java.lang.reflect.Field fieldY = p1.getClass().getField("y");//fieldY 仅代表Point类y的成员变量映射的对象
int p1Y = (int)fieldY.get(p1);//获得p1 对象身上的该成员变量的值
System.out.println(p1Y);
java.lang.reflect.Field fieldX = p1.getClass().getDeclaredField("x");//可以映射 获取私有的成员变量
fieldX.setAccessible(true);//映射后还是不能访问//设置访问私有变量(暴力反射)
int p1X = (int)fieldX.get(p1);
System.out.println(p1X);
//反射获取私有字段
public Object forceGet(String fieldName) throws Exception {
Field field = this.original.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(this.original);
}
//替换值 void setXxx(Object obj,xxx val):将obj对象的该Field字段设置成val值, 此处的xxx表示8个基本数据类型; 若该字段的类型是引用数据类型则使用, void set(Object obj, Object value);4. 成员方法的反射
Method m = String.class.getMethod("charAt", int.class);//映射String的charAt( int )的方法
String str3 = "abcd";
System.out.println( m.invoke(str3, 2) );//调用str3对象的该映射方法; 若对象参数为null则是静态方法5. 反射调用方法
Method m =Point.class.getMethod("abc", null);
Point p1 = new Point(3,5);
m.invoke(p1, null);
//反射调用私有方法
public Object forceCall(String methodName, Object ... param) throws Exception {
Method method = this.original.getClass().getDeclaredMethod(methodName);
method.setAccessible(true);
return method.invoke(this.original, param);
}6. 数组的反射与Object
//具有相同的类型,相同的维度, 才算是同一个映射(字节码)
int [] a1 = new int []{1,2,3};//一维数组 int类型
int [] a2 = new int [4]; //一维数组 int类型
int [][] a3 = new int [2][4]; //二维数组 int类型
String [] a4 = new String []{"a","b","c"}; //一维数组 String类型
System.out.println( a1.getClass() == a2.getClass() );//true
System.out.println( a1.getClass() == a3.getClass() ); //编译错误,不同维度
System.out.println( a1.getClass() == a4.getClass() ); //编译错误,不同类型
与Object的关系?
Object o1 = a1;//o1 是数组映射 @1
Object o2 = a4;//o2当数组 是数组映射@2
Object[] o3 = a1;//obj当数组 但是基本类型不是对象,不能转型,编译错误
Object[] o4 = a3;//obj当元素
Object[] o5 = a4;//obj当元素
System.out.println( a1);//I@ffffff int类型
System.out.println( a4);//java.lang.String;@ffffff String类型
综上@1;@2; 当你得到一个object反射如何区分,是当数组反射,还是当对象反射?
//答案是: class.isArray() 方法判断
//如何看到数组的内容?
System.out.println( Arrays.asList(a1));//a1[]转成object了
System.out.println( Arrays.asList(a4));
7. 获取注解
MethodInterface methodAnno = Method.getAnnotation(MethodInterface.class);
8. 参考 java.lang.Class API
注解&元注解
@Retention
Retention的英文意为保留期的意思; 当 `@Retention` 应用到一个注解上的时候, 它解释说明了这个注解的的存活时间;
它的取值如下:
- `RetentionPolicy.SOURCE` 注解只在源码阶段保留, 在编译器进行编译时它将被丢弃忽视;
- `RetentionPolicy.CLASS` 注解只被保留到编译进行的时候, 它并不会被加载到 JVM 中;
- `RetentionPolicy.RUNTIME` 注解可以保留到程序运行的时候, 它会被加载进入到 JVM 中, 所以在程序运行时可以获取到它们;
@Target
Target 是目标的意思, @Target 指定了注解运用的地方;
比如只能张贴到方法上, 类上, 方法参数上等等; @Target 有下面的取值
ElementType.ANNOTATION_TYPE可以给一个注解进行注解ElementType.CONSTRUCTOR可以给构造方法进行注解ElementType.FIELD可以给属性进行注解ElementType.LOCAL_VARIABLE可以给局部变量进行注解ElementType.METHOD可以给方法进行注解ElementType.PACKAGE可以给一个包进行注解ElementType.PARAMETER可以给一个方法内的参数进行注解ElementType.TYPE可以给一个类型进行注解, 比如类, 接口, 枚举
@Inherited
Inherited 是继承的意思, 但是它并不是说注解本身可以继承, 而是说如果一个超类被 @Inherited 注解过的注解进行注解的话, 那么如果它的子类没有被任何注解应用的话, 那么这个子类就继承了超类的注解;
@Documented
顾名思义, 这个元注解和文档有关; 它的作用是能够将注解中的元素包含到 Javadoc 中去;
示例
/**
* @author yangfh
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(TYPE)
public @interface ObjectDesciption {
String value();
String extra() default "";
long flag() default 0L;
}