java togmtstring()_Java反射

java反射库(reflection library)提供了一个非常丰富且精心设计的工具集,以便编写能够动态操纵java代码的程序。这项功能被大量应用于JavaBeans中。

能够分析类能力的程序称为反射。反射机制作用:

1)运行时分析类的能力

2)运行时查看对象

3)实现通用的数组操作代码

4)利用Method对象,这个对象类似于c++函数指针。

Class类

程序运行期间,Java运行时系统始终为所有的对象维护一个被称为运行时的类型标识。这个信息跟踪着每个对象所属的类。虚拟机利用运行时类型信息选择相应方法执行。

常用相关方法:

static Class forName(String className)       //返回描述类名为className的Class对象

static String getClass(Class classString)     //返回描述类名的String

Object newInstance()  //返回这个类的新实例

Object newInstance(Object[] args)  //构造一个这个构造器所属类的新实例,参数由args给出

利用反射分析类

反射机制最重要的内容--检查类的结构

Class类中的相关方法:

Field[] getFields()  //返回一个包含Field对象的数组,记录了这个类与其超类的公有域

Field[] getDeclaredFields()  //返回一个包含Field对象的数组,记录了这个类的全部域

Method[] getMethods()  //返回一个包含Method对象的数组,记录了所有的公有方法

Method[] get DeclareMethods()  //返回一个包含Method对象的数组,记录了这个类所有或接口的所有方法

Constructor[] getConstructors()  //返回一个包含Constructor对象的数组,记录了所有公有构造器

Constructor[] getDeclareConstructors()  //返回一个包含Constructor对象的数组,记录了所有构造器

反射包中相关方法:

Class getDeclareClass()  //返回一个用于描述类中定义的构造器,方法或域的对象

Class getExceptionTypes()  //返回一个用于描述方法抛出异常类型的Class对象数组

int getModefiers()  //返回一个用于描述构造器,方法或域的修饰符的整形数值。使用Modefier类中的这个方法可以分析这个值

String getName()  //返回一个用于描述构造器,方法或域名的字符串

class[] getParrameterrTypes()  //返回一个用于描述参数类型的Class对象数组

Class getReturnType()  //返回一个用于描述返回类型的Class对象

static String toString(int modifiers)  //返回对应modefiers中位设置的修饰符的字符串表示

static boolean isAbatract【或isFinal/isInterface.....所有修饰符】 (int modefiers)   //检测修饰符对应位

以下是一个测试用例:

输入一个类,打印所有构造器,方法和域,包括他们的修饰符以及构造器和方法的参数

335b83df261c422459d4afc29ba290e5.png

d1b641f023dd079c9e4a800b96607d9d.gif

1 packagerefleection.company;2

3 import java.lang.reflect.*;4 importjava.util.Scanner;5

6 public classReflectionTest {7

8 public static voidmain(String[] args) {9 String name;10 if (args.length > 0) {11 name = args[0];12 } else{13 Scanner in = newScanner(System.in);14 System.out.println("Enter class name(e.g. java.util.Date):");15 name =in.next();16 }17

18 try{19 Class c1 = Class.forName(name);//获取对应类名的Class对象

20 Class superc1 = c1.getSuperclass();//获取超类对象

21 String modifiers = Modifier.toString(c1.getModifiers());//获取修饰符

22 if (modifiers.length() > 0) {23 System.out.print(modifiers + " ");24 }25 System.out.print("class " +name);26 if (superc1 != null && superc1 != Object.class) {27 //打印超类对象

28 System.out.print("extends" +superc1.getName());29 }30 System.out.print("\n{\n");31 printConstructors(c1);32 System.out.println();33 printMethods(c1);34 System.out.println();35 printFields(c1);36 System.out.println("}");37 } catch(ClassNotFoundException e) {38 e.printStackTrace();39 }40 System.exit(0);41 }42

43

44 public static voidprintConstructors(Class c1) {45 Constructor[] constructors = c1.getDeclaredConstructors();//获取所有构造器,存于数组

46

47 for(Constructor c : constructors) {48 String name =c.getName();49 System.out.print(" ");50 String modifiers = Modifier.toString(c.getModifiers());//getModifiers返回一个描述修饰符的整数值,转为字符串

51 if (modifiers.length() > 0) {52 System.out.print(modifiers + " ");53 }54 System.out.print(name + "(");55 Class[] paramTypes = c.getParameterTypes();//获取描述参数类型的对象数组

56 for (int j = 0; j < paramTypes.length; j++) {57 if (j > 0) {58 System.out.print(", ");59 }60 System.out.print(paramTypes[j].getName());61 }62 System.out.print(");");63 }64 }65

66 public static voidprintMethods(Class c1) {67 Method[] methods = c1.getDeclaredMethods();//获取所有方法,存于数组

68

69 for(Method m : methods) {70 Class retType = m.getReturnType();//获取描述返回类型的对象

71 String name =m.getName();72 System.out.print(" ");73 String modifiers = Modifier.toString(m.getModifiers());//描述修饰符的字符串

74 if (modifiers.length() > 0) {75 System.out.print(modifiers + " ");76 }77 System.out.print(retType.getName() + " " + name + "(");78 Class[] paramTypes = m.getParameterTypes();//获取描述参数类型的对象数组

79 for (int j = 0; j < paramTypes.length; j++) {80 if (j > 0) {81 System.out.print(", ");82 }83 System.out.print(paramTypes[j].getName());84 }85 System.out.println(");");86 }87 }88

89 public static voidprintFields(Class c1) {90 Field[] fields =c1.getDeclaredFields();91

92 for(Field f : fields) {93 Class type = f.getType();//域所属类型

94 String name =f.getName();95 System.out.print(" ");96 String modifiers = Modifier.toString(f.getModifiers());//域修饰符

97 if (modifiers.length() > 0) {98 System.out.print(modifiers + " ");99 }100 System.out.println(type.getName() + " " + name + ";");101 }102 }103 }

View Code

输入java.util.Date得到下面结果

335b83df261c422459d4afc29ba290e5.png

d1b641f023dd079c9e4a800b96607d9d.gif

1 Enter classname(e.g. java.util.Date):2 java.util.Date3 public classjava.util.Date4 {5 public java.util.Date(int, int, int, int, int, int); public java.util.Date(); public java.util.Date(int, int, int, int, int); public java.util.Date(java.lang.String); public java.util.Date(long); public java.util.Date(int, int, int);6 public void setYear(int);7 public intgetMonth();8 public void setMonth(int);9 public void setDate(int);10 public intgetDay();11 public intgetHours();12 public void setHours(int);13 public intgetMinutes();14 public void setMinutes(int);15 public intgetSeconds();16 public void setSeconds(int);17 private final longgetTimeImpl();18 static final longgetMillisOf(java.util.Date);19 private static finaljava.lang.StringBuilder convertToAbbr(java.lang.StringBuilder, java.lang.String);20 publicjava.lang.String toLocaleString();21 publicjava.lang.String toGMTString();22 public intgetTimezoneOffset();23 private finalsun.util.calendar.BaseCalendar$Date getCalendarDate();24 private static final sun.util.calendar.BaseCalendar getCalendarSystem(long);25 private static finalsun.util.calendar.BaseCalendar getCalendarSystem(sun.util.calendar.BaseCalendar$Date);26 private static final sun.util.calendar.BaseCalendar getCalendarSystem(int);27 private static final synchronizedsun.util.calendar.BaseCalendar getJulianCalendar();28 publicjava.time.Instant toInstant();29 public static long UTC(int, int, int, int, int, int);30 public intgetYear();31 public booleanbefore(java.util.Date);32 public booleanafter(java.util.Date);33 public void setTime(long);34 public longgetTime();35 public intgetDate();36 public booleanequals(java.lang.Object);37 publicjava.lang.String toString();38 public inthashCode();39 publicjava.lang.Object clone();40 public intcompareTo(java.util.Date);41 public volatile intcompareTo(java.lang.Object);42 public staticjava.util.Date from(java.time.Instant);43 private voidreadObject(java.io.ObjectInputStream);44 private voidwriteObject(java.io.ObjectOutputStream);45 private finalsun.util.calendar.BaseCalendar$Date normalize();46 private finalsun.util.calendar.BaseCalendar$Date normalize(sun.util.calendar.BaseCalendar$Date);47 public static longparse(java.lang.String);48

49 private static finalsun.util.calendar.BaseCalendar gcal;50 private staticsun.util.calendar.BaseCalendar jcal;51 private transient longfastTime;52 private transientsun.util.calendar.BaseCalendar$Date cdate;53 private static intdefaultCenturyStart;54 private static final longserialVersionUID;55 private static final[Ljava.lang.String; wtb;56 private static final[I ttb;57 }

输出结果

在运行时使用反射分析对象

有时候希望可以看到数据域的实际数据而不只是类型,用反射同样可以做到。可能用到下列函数

Object get(Object obj)  //返回obj对象中用Field对象表示的域值

void set(Object obj,Object newValue)  //用一个新值设置obj对象中Field对象表示的域

Field getField(String)  //获得指定名称的公有域

Field getDeclareField(String)  //获得给定名称的域

假设有一个Employee的类,该类有一个name私有域,根据以上函数,尝试获取域值

Employee e = newEmployee();

Class c1=e.getClass();

Field f= c1.getDeclareField("name");

Object v= f.get(e)

看似可行,实际上时不可行的,它会抛出一个IllegalAccessException异常。name是私有域,java安全机制不允许没有访问权限的客户读取私有域的值,那么就要用到以下函数

void setAccessible(boolean flag)  //为反射对象设置可访问标志

boolean isAccessible()  //返回反射对象的可访问标志的值

static void setAccessible(AccessibleObject[] array,boolean flag)  //设置对象数组可访问标志

那么上述例子增加一条语句,就不会抛出异常了。

f.setAccessable(true);

以下是一个实例,输入任意类,输出它的所有域以及相应的值

335b83df261c422459d4afc29ba290e5.png

d1b641f023dd079c9e4a800b96607d9d.gif

1 packageobjectAnalyzer;2

3 importjava.lang.reflect.AccessibleObject;4 importjava.lang.reflect.Array;5 importjava.lang.reflect.Field;6 importjava.lang.reflect.Modifier;7 importjava.util.ArrayList;8

9 public classObjectAnalyzer {10 private ArrayList visited = new ArrayList<>();11

12 publicString toString(Object obj){13 if (obj==null){14 return "null";15 }16 if(visited.contains(obj)){17 return "...";18 }19 visited.add(obj);20 Class c1 = obj.getClass();//获取类名

21 if (c1 == String.class){22 return(String)obj;23 }//若为String类型,直接返回String对象

24 if(c1.isArray()){25 String r = c1.getComponentType()+"[]{";//getComponent返回表示数组元素类型的字符串

26 for (int i = 0;i < Array.getLength(obj);i++){27 if (i>0){28 r += ",";29 }//获取每个数值

30 Object val =Array.get(obj,i);31 if (c1.getComponentType().isPrimitive()){//判断是否为基本类型

32 r +=val;33 }34 else{35 r +=toString(val);36 }37 }38 return r + "}";39 }40 String r = c1.getName();//非空,非String,非array,其他类

41 do{42 r += "[";43 Field[] fields = c1.getDeclaredFields();//获取所有域

44 AccessibleObject.setAccessible(fields,true);//设置为可见

45 for(Field f:fields){46 if (!Modifier.isStatic(f.getModifiers())){//非静态域

47 if(!r.endsWith("[")){48 r += ",";49 }50 r += f.getName() + "=";//获取名称

51 try{52 Class t =f.getType();53 Object val =f.get(obj);54 if (t.isPrimitive()){//判断是否为基本类型

55 r +=val;56 }57 else{58 r +=toString(val);59 }60 }catch(Exception e){61 e.printStackTrace();62 }63 }64 }65 r += "]";66 c1 =c1.getSuperclass();67 } while (c1 != null);68 returnr;69 }70 }

View Code

335b83df261c422459d4afc29ba290e5.png

d1b641f023dd079c9e4a800b96607d9d.gif

1 packageobjectAnalyzer;2

3 importjava.util.ArrayList;4

5 public classObjectAnalyzerTest {6 public static voidmain(String[] args){7 ArrayList squares = new ArrayList<>();8 for (int i = 1;i <= 5;i++){9 squares.add(i*i);10 }11 System.out.println(newObjectAnalyzer().toString(squares));12 }13

14 }

测试类

结果

335b83df261c422459d4afc29ba290e5.png

d1b641f023dd079c9e4a800b96607d9d.gif

1 java.util.ArrayList[elementData=class java.lang.Object[]{java.lang.Integer[value=1][][],java.lang.Integer[value=4][][],java.lang.Integer[value=9][][],java.lang.Integer[value=16][][],java.lang.Integer[value=25][][],null,null,null,null,null},size=5][modCount=5][][]

View Code

使用反射编写泛型数组代码

java反射包中的Array类允许动态地创建数组,将其拓展为更通用的方法,即可以拓展任意类型的数组。

public static Object goodCopyOf(Object a,intlength){

Class c1=a.getClass();if(!c1.isarray()){return null;

}

Class componentType=c1.getComponentType();int length =Array.getLength(a);

Object newArray=Array.newInstance(ComponentType, newLength);

System.arraycopy(a,0,newArray,0,Math.min(length,newLength));returnnewArray;

}

Array类的一些方法

static Object get(Object array,int index) //返回给定数组下标的内容

static xxx getXxx(Object array,int index) //返回给定数组下标的内容,xxx是基本类型

static void set(Object array,int index,Object newValue)  //设置指定下标内容

staticc int getLength(Object array)  //返回数组长度

static Object newInstance(Class componentType,int length)  //返回一个具有给定类型,维数的新数组

static Object newInstance(Class componentType,int[] length)

调用任意方法

Methods类中有一个invoke方法,允许调用包装在当前Method对象中的方法。如下:

public Object invoke(Object implicitParameter,Object[] explicitParamenters)  //调用这个对象描述的方法,传递给定参数,返回方法的返回值。对于静态方法,把null作为隐式参数传递。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值