1.反射
1.1 反射概述
反射(Reflection)是 Java特征之一,它允许运行中的Java程序对自身进行检查,或者说“自审”,并能直接操作程序的内部属性。例如,使用它能获得 Java 类中各成员的名称并显示出来。
1.2 示例
package cn.htmlv5.bobshute.jse.javasihu.reflect7;
import java.lang.reflect.*;
public class ReflectTest {
public static final int i = 11;
public String str;
private int j;
private String [] strArray;
public static void main(String args[]) throws Exception {
//1.返回类的各方法名以及它们的限制符和返回类型
reflectDeclaredMethods();
//2.判断是否一类-isInstance
reflectInstance();
//3.获取方法详细信息:方法名,所在类,参数信息,异常信息,返回类型
reflectMethodsDetail(null,null);
//4.获取方法详细信息:方法名,所在类,参数信息,异常信息
reflectConstructor();
//5.类的属性字段(域字段)
reflectFields();
//6.通过实例化构造方法,实例化对象
reflectNewInstance();
//7.根据方法名称执行方法
reflectExecMethod();
//8.修改类的属性值
changeFiledValue();
//9.操作数组1-普通数组
reflectArray();
//10.操作数组2-多维数组
reflectArrayDim();
}
/**
* 1. 返回类的各方法名以及它们的限制符和返回类型
运行结果:
private static java.lang.Object java.util.Collections.get(java.util.ListIterator,int)
public static java.lang.Object java.util.Collections.min(java.util.Collection,java.util.Comparator)
public static java.lang.Object java.util.Collections.min(java.util.Collection)
...
public static java.util.SortedSet java.util.Collections.unmodifiableSortedSet(java.util.SortedSet)
static java.lang.Object[] java.util.Collections.zeroLengthArray(java.lang.Class)
*/
public static void reflectDeclaredMethods() throws Exception {
Class c = Class.forName("java.util.Collections");
Method m[] = c.getDeclaredMethods();
for (int i = 0; i < m.length; i++){
System.out.println(m[i].toString());
}
}
/**
* 2. 判断是否一类-isInstance
*/
public static void reflectInstance() throws Exception {
Class c1 = Long.TYPE;
Class c2 = long.class;
Class c3 = Long.class;
//long-long-class java.lang.Long
System.out.println(c1+"-"+c2+"-"+c3);
Class cls = Class.forName(Long.class.getName());
boolean b1 = cls.isInstance(new Integer(37));
//b1->false
System.out.println("b1->"+b1);
boolean b2 = cls.isInstance(new Long(37));
//b2->true
System.out.println("b2->"+b2);
}
/**
* 3. 打印方法详细信息:方法名,所在类,参数信息,异常信息,返回类型
只列出当前方法的:
<---第2个method开始---
method name => reflectMethodsDetail
declaring class = class cn.htmlv5.bobshute.jse.javasihu.reflect.ReflectTest
method param [0] => class java.lang.Object
method param [1] => class java.lang.String
exception types [0] =>class java.lang.Exception
return type => void
---第2个method结束--->
*/
public static void reflectMethodsDetail(Object o,String str) throws Exception {
try {
Class cls = Class.forName("cn.htmlv5.bobshute.jse.javasihu.reflect7.ReflectTest");
Method methlist[] = cls.getDeclaredMethods();
for (int i = 0; i < methlist.length; i++) {
System.out.println("<---第"+i+"个method开始---");
Method m = methlist[i];
System.out.println("method name => " + m.getName());
System.out.println("declaring class = " + m.getDeclaringClass());
Class pvec[] = m.getParameterTypes();
for (int j = 0; j < pvec.length; j++)
System.out.println("method param [" + j + "] => " + pvec[j]);
Class evec[] = m.getExceptionTypes();
for (int j = 0; j < evec.length; j++)
System.out.println("exception types [" + j + "] =>" + evec[j]);
System.out.println("return type => " + m.getReturnType());
System.out.println("---第"+i+"个method结束--->");
}
} catch (Throwable e) {
e.printStackTrace();
}
}
/**
* 4.查询构造方法信息
*
<---第0个Constructor method开始---
declaredConstructors name => cn.htmlv5.bobshute.jse.javasihu.reflect.ReflectTest
declaredConstructors class => class cn.htmlv5.bobshute.jse.javasihu.reflect.ReflectTest
---第0个Constructor method结束--->
<---第1个Constructor method开始---
declaredConstructors name => cn.htmlv5.bobshute.jse.javasihu.reflect.ReflectTest
declaredConstructors class => class cn.htmlv5.bobshute.jse.javasihu.reflect.ReflectTest
param [0]=> class java.lang.String
param [1]=> int
---第1个Constructor method结束--->
<---第2个Constructor method开始---
declaredConstructors name => cn.htmlv5.bobshute.jse.javasihu.reflect.ReflectTest
declaredConstructors class => class cn.htmlv5.bobshute.jse.javasihu.reflect.ReflectTest
param [0]=> class java.lang.String
param [1]=> class [Ljava.lang.String;
---第2个Constructor method结束--->
*
*/
public static void reflectConstructor(){
try {
Class cls = Class.forName(cn.htmlv5.bobshute.jse.javasihu.reflect7.ReflectTest.class.getName());
Constructor ctorlist[] = cls.getDeclaredConstructors();
for (int i = 0; i < ctorlist.length; i++) {
System.out.println("<---第"+i+"个Constructor method开始---");
Constructor ct = ctorlist[i];
System.out.println("declaredConstructors name => " + ct.getName());
System.out.println("declaredConstructors class => " + ct.getDeclaringClass());
Class pvec[] = ct.getParameterTypes();
for (int j = 0; j < pvec.length; j++)
System.out.println("param [" + j + "]=> " + pvec[j]);
Class evec[] = ct.getExceptionTypes();
for (int j = 0; j < evec.length; j++)
System.out.println("exception types [" + j + "] =>" + evec[j]);
System.out.println("---第"+i+"个Constructor method结束--->");
}
} catch (Throwable e) {
e.printStackTrace();
}
}
/**
* 5.类的属性字段(域字段), 包括:属性名称,类型及修饰符
<---第0个field开始---
field name =>i
declaring class => class cn.htmlv5.bobshute.jse.javasihu.reflect.ReflectTest
type =>int
modifiers =>public static final
---第0个field结束--->
<---第1个field开始---
field name =>str
declaring class => class cn.htmlv5.bobshute.jse.javasihu.reflect.ReflectTest
type =>class java.lang.String
modifiers =>public
---第1个field结束--->
<---第2个field开始---
field name =>j
declaring class => class cn.htmlv5.bobshute.jse.javasihu.reflect.ReflectTest
type =>int
modifiers =>private
---第2个field结束--->
<---第3个field开始---
field name =>strArray
declaring class => class cn.htmlv5.bobshute.jse.javasihu.reflect.ReflectTest
type =>class [Ljava.lang.String;
modifiers =>private
---第3个field结束--->
*/
public static void reflectFields(){
try {
Class cls = Class.forName(ReflectTest.class.getName());
Field fieldlist[] = cls.getDeclaredFields();
for (int i = 0; i < fieldlist.length; i++) {
System.out.println("<---第"+i+"个field开始---");
Field fld = fieldlist[i];
System.out.println("field name =>" + fld.getName());
System.out.println("declaring class => " + fld.getDeclaringClass());
System.out.println("type =>" + fld.getType());
int mod = fld.getModifiers();
System.out.println("modifiers =>" + Modifier.toString(mod));
System.out.println("---第"+i+"个field结束--->");
}
} catch (Throwable e) {
e.printStackTrace();
}
}
/**
*
6. 实例化构造方法,通过构造方法实例化对象
Constructor->str:Constructor str,j:47
reflectobj.str->Constructor str,reflectobj.j->47
*/
public static void reflectNewInstance(){
try {
Class cls = Class.forName(ReflectTest.class.getName());
Class partypes[] = new Class[2];
partypes[0] = String.class;
partypes[1] = Integer.TYPE;
Constructor ct = cls.getConstructor(partypes); //准备构造方法
Object arglist[] = new Object[2];
arglist[0] = new String("Constructor str");
arglist[1] = new Integer(47);
ReflectTest reflectobj = (ReflectTest)ct.newInstance(arglist);//构造方法来实例化对象
System.out.println("reflectobj.str->"+reflectobj.str+",reflectobj.j->"+reflectobj.j);
} catch (Throwable e) {
e.printStackTrace();
}
}
/**
* 7.根据方法名称及参数执行方法
* reflectMethod-return->str147
*/
public static void reflectExecMethod(){
try {
Class cls = Class.forName(ReflectTest.class.getName());
Class partypes[] = new Class[2];
partypes[0] = String.class;
partypes[1] = Integer.TYPE;
Method meth = cls.getMethod("testMethod2", partypes);
// 先创建对象实例
Object obj = cls.newInstance();
// 然后调用方法
Object arglist[] = new Object[2];
arglist[0] = new String("str1");
arglist[1] = new Integer(47);
Object retobj = meth.invoke(obj, arglist);
String retval = (String) retobj;
System.out.println("reflectMethod-return->"+ retval);
} catch (Throwable e) {
System.err.println(e);
}
}
/**
* 8.修改类的属性
* 注意:静态属性不能改变, Can not set static final int field,
* private类型的也不行
*
str-1->null
str-2->changeStrValue
*/
public static void changeFiledValue() throws Exception{
Class cls = Class.forName(ReflectTest.class.getName());
Field fld = cls.getField("str");
Object obj = cls.newInstance();
System.out.println("str-1->" + ((ReflectTest) obj).str);
fld.set(obj, "changeStrValue");
System.out.println("str-2->" + ((ReflectTest) obj).str);
}
/**
* 9.操作数组1-普通数组
*
* this is a test5
*/
public static void reflectArray() throws Exception{
Class cls = Class.forName("java.lang.String");
Object arr = Array.newInstance(cls, 10);
Array.set(arr, 5, "this is a test5");
String s = (String) Array.get(arr, 5);
System.out.println(s);
}
/**
* 10.操作数组2-多维数组
*
cls->class [I
arrcast[3][5][10]->137
*/
public static void reflectArrayDim() throws Exception{
int dims[] = new int[] { 5, 10, 15 };
Object arr = Array.newInstance(Integer.TYPE, dims);
Object arrobj = Array.get(arr, 3);
Class cls = arrobj.getClass().getComponentType();
System.out.println("cls->"+cls);
arrobj = Array.get(arrobj, 5);
Array.setInt(arrobj, 10, 137);
int arrcast[][][] = (int[][][]) arr;
System.out.println("arrcast[3][5][10]->"+arrcast[3][5][10]);
}
//普通方法1
public void testMethod1(String str1,int ii){
System.out.println("testMethod1 is calling->str1:"+str1+",ii:"+ii);
}
//普通方法2
public String testMethod2(String str1,int ii){
System.out.println("testMethod2 is calling->str1:"+str1+",ii:"+ii);
return str1+ii;
}
//Constructor-构造方法1
public ReflectTest(){
}
//Constructor-构造方法2
public ReflectTest(String str,int j){
System.out.println("Constructor->str:"+str+",j:"+j);
this.str = str;
this.j = j;
}
//Constructor-构造方法3
public ReflectTest(String str, String [] strArray){
this.str = str;
this.strArray = strArray;
}
}
反射获取注解情况
//注意:只有@Retention(RetentionPolicy.RUNTIME)为runtime时才能通过注解获取到
public class TestMyAnno {
/**
* flag->true
ma.myfiled()->myfiledvalue,ma.myfiled2()->myfiledvalue2
*/
public static void main(String[] args) throws Exception {
Class c = Class.forName(UseAnno.class.getName());
System.out.println("c->"+c.getName());
//判断时候存在注解
boolean flag = c.isAnnotationPresent(MyAnno.class);
System.out.println("flag->"+flag);
if (flag) {
MyAnno ma = (MyAnno) c.getAnnotation(MyAnno.class);
System.out.println("ma.myfiled()->"+ma.myfiled()+",ma.myfiled2()->"+ma.myfiled2());
}
}
}
2.注解
2.1概述
元数据
所谓元数据就是数据的数据。也就是说,元数据是描述数据的。就象数据表中的字段一样,每个字段描述了这个字段下的数据的含义。元数据可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译时检查。许多元数据工具,如 XDoclet,将这些功能添加到Java中,成为 Java 编程功能的一部分。
元数据的好处分为三类:文档编制、编译器检查和代码分析。代码级文档最常被引用。元数据提供了一种有用的方法来指明方法是否取决于其他方法,它们是否完整,特定类是否必须引用其他类,等等。
注解
注解就是 Java 源代码的元数据,也就是说注解是用来描述 Java 源代码的。基本语法就是@后面跟注解的名称。Java5 以上的版本都支持,有预定义的注解,也可以自定义注解。
如: Override(覆盖父类方法),Deprecated(已过期),SuppressWarnings(抑制警告).
2.2 自定义注解
//自定义注解
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//父类的注解并不会被子类继承。加上Inherited注解后可以继承
@Inherited
//默认生成文档时不保留,加上该注解生成文档时保留
@Documented
//注解保持性(有效性),注意,只有为runtime时才可以被反射获取到
@Retention(RetentionPolicy.RUNTIME)
//target指明注解的使用范围,只有type和method
@Target({ ElementType.TYPE, ElementType.METHOD })
public @interface MyAnno {
public String myfiled(); //成员
public String myfiled2() default "filed2"; //有默认值的成员
}
//使用注解
@MyAnno(myfiled="myfiledvalue",myfiled2 = "myfiledvalue2")
public class UseAnno {
}
2.3 对注解的注解
- Target 允许何种程序元素具有定义的注解类型
package java.lang.annotation;
public enum ElementType {
TYPE, // Class, interface, or enum (but not annotation)
FIELD, // Field (including enumerated values)
METHOD, // Method (does not include constructors)
PARAMETER, // Method parameter
CONSTRUCTOR, // Constructor
LOCAL_VARIABLE, // Local variable or catch clause
ANNOTATION_TYPE, // Annotation Types (meta-annotations)
PACKAGE // Java package
}
- Retention 设置保持性,元注释和Java 编译器处理注解的注解类型的方式有关.
public enum RetentionPolicy {
SOURCE, // Annotation is discarded by the compiler
CLASS, // Annotation is stored in the class file, but ignored by the VM
RUNTIME // Annotation is stored in the class file and read by the VM
}
source://注解仅存在于源码中,在class字节码文件中不包含
class://默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,
runtime:// 注解会在class字节码文件中存在,在运行时可以通过反射获取到
Documented
在默认的情况下在使用 javadoc 自动生成文档时,注解将被忽略掉。如果想在文档中也包含注解,必须使用 Documented 为文档注解。Inherited
在默认的情况下,父类的注解并不会被子类继承。如果要继承,就必须加上 Inherited 注解。
2.4 获取类注解情况
//注意:只有@Retention(RetentionPolicy.RUNTIME)为runtime时才能通过注解获取到
public class TestMyAnno {
/**
* flag->true
ma.myfiled()->myfiledvalue,ma.myfiled2()->myfiledvalue2
*/
public static void main(String[] args) throws Exception {
Class c = Class.forName(UseAnno.class.getName());
System.out.println("c->"+c.getName());
//判断时候存在注解
boolean flag = c.isAnnotationPresent(MyAnno.class);
System.out.println("flag->"+flag);
if (flag) {
MyAnno ma = (MyAnno) c.getAnnotation(MyAnno.class);
System.out.println("ma.myfiled()->"+ma.myfiled()+",ma.myfiled2()->"+ma.myfiled2());
}
}
}