P200
程序清单5-14 objectAnalyzer/ObjectAnalyzerTest.java
import java.util.ArrayList;
public class ObjectAnalyzerTest
{
public static void main(String[] args)
{
ArrayList<Integer> squares = new ArrayList<>();
for (int i = 1; i <= 5; i++)
squares.add(i * i);
System.out.println(new ObjectAnalyzer().toString(squares));
}
}
P200
程序清单5-15 objectAnalyzer/ObjectAnalyzer.java
- 代码
- 分析
- 重要API
1.代码
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
public class ObjectAnalyzer
{
private ArrayList<Object> visited = new ArrayList<>();
/**
* Converts an object to a string representation that lists all fields.
* @param obj an object
* @return a string with the object's class name and all field names and
* values
*/
public String toString(Object obj)
{
if (obj == null) return "null";//false
if (visited.contains(obj)) return "...";//false
visited.add(obj);
Class cl = obj.getClass();
if (cl == String.class) return (String) obj;//false
if (cl.isArray())//true
{
//获取cl数组的Class对象
String r = cl.getComponentType() + "[]{";
for (int i = 0; i < Array.getLength(obj); i++)
{
if (i > 0) r += ",";
Object val = Array.get(obj, i);
//判断cl数组的Class对象是否为原始类型
if (cl.getComponentType().isPrimitive()) r += val;
else r += toString(val);
}
return r + "}";
}
String r = cl.getName();
// inspect the fields of this class and all superclasses
do
{
r += "[";
getDeclaredFields请参考程序清单5-13
Field[] fields = cl.getDeclaredFields();
//将fields的 accessible 标志设置为指示的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查。
AccessibleObject.setAccessible(fields, true);
// get the names and values of all fields
for (Field f : fields)
{
//Modifier.isStatic请参考程序清单5-13
if (!Modifier.isStatic(f.getModifiers()))
{
if (!r.endsWith("[")) r += ",";
r += f.getName() + "=";
try
{
//获取f的类型
Class t = f.getType();
Object val = f.get(obj);
if (t.isPrimitive()) r += val;
else r += toString(val);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
r += "]";
//getSuperclass请参考程序清单5-13
cl = cl.getSuperclass();
}
while (cl != null);
return r;
}
}
2.分析
1st PART
理解getComponentType()
//获取cl数组的Class对象
String r = cl.getComponentType() + "[]{";
我们直接通过一个代码示例来理解getComponentType()
:
代码:
import java.lang.reflect.Array;
public class GetComponentType {
public static void main(String [] args){
Class<char[]> aa = (Class<char[]>) char.class.getComponentType();
System.out.println("the componentType of the char is :" + char.class.getComponentType());
System.out.println("the componentType of the char[] is :" + char[].class.getComponentType());
System.out.println("the componentType of the String is :" + String.class.getComponentType());
System.out.println("the componentType of the String[] is :" + String[].class.getComponentType());
System.out.println("the componentType of the int is :" + int.class.getComponentType());
System.out.println("the componentType of the int[] is :" + int[].class.getComponentType());
System.out.println("the componentType of the Integer is :" + Integer.class.getComponentType());
System.out.println("the componentType of the Integer[] is :" + Integer[].class.getComponentType());
try {
char c = (char)Array.newInstance(char.class.getComponentType(), 10);
} catch (Exception e) {
e.printStackTrace();
}
char[] charArray = (char [])Array.newInstance(char[].class.getComponentType(), 100);
System.out.println("the length of the charArray is :" + charArray.length);
try {
String c = (String)Array.newInstance(String.class.getComponentType(), 10);
} catch (Exception e) {
e.printStackTrace();
}
String[] strArray = (String [])Array.newInstance(String[].class.getComponentType(), 10);
System.out.println("the length of the strArray is :" + strArray.length);
}
}
输出:
the componentType of the char is :null
the componentType of the char[] is :char
the componentType of the String is :null
the componentType of the String[] is :class java.lang.String
the componentType of the int is :null
the componentType of the int[] is :int
the componentType of the Integer is :null
the componentType of the Integer[] is :class java.lang.Integer
java.lang.NullPointerException
at java.lang.reflect.Array.newArray(Native Method)
at java.lang.reflect.Array.newInstance(Array.java:70)
at com.ips.reflect.GetComponentType.main(GetComponentType.java:23)
the length of the charArray is :100
java.lang.NullPointerException
at java.lang.reflect.Array.newArray(Native Method)
at java.lang.reflect.Array.newInstance(Array.java:70)
at com.ips.reflect.GetComponentType.main(GetComponentType.java:31)
the length of the strArray is :10
参考链接:Java编程:Java的反射机制中的 getComponentType() 方法
2nd PART
理解isPrimitive()
//判断cl数组的Class对象是否为原始类型
if (cl.getComponentType().isPrimitive()) r += val;
isPrimitive()
:
判断Class是否为原始类型(boolean、char、byte、short、int、long、float、double)。
我们看一个代码示例:
public static void main(String[] args){
Class stringClass=String.class;
System.out.println("String is primitive type:"+stringClass.isPrimitive());
Class booleanClass=Boolean.class;
System.out.println("Boolean is primitive type:"+booleanClass.isPrimitive());
Class booleanType=boolean.class;
System.out.println("boolean is primitive type:"+booleanType.isPrimitive());
Class byteType=byte.class;
System.out.println("byte is primitive type:"+byteType.isPrimitive());
Class charType=char.class;
System.out.println("char is primitive type:"+charType.isPrimitive());
Class shortType=short.class;
System.out.println("short is primitive type:"+shortType.isPrimitive());
Class intType=int.class;
System.out.println("int is primitive type:"+intType.isPrimitive());
Class longType=long.class;
System.out.println("long is primitive type:"+longType.isPrimitive());
Class floatType=float.class;
System.out.println("float is primitive type:"+floatType.isPrimitive());
Class doubleType=double.class;
System.out.println("double is primitive type:"+doubleType.isPrimitive());
}
输出:
String is primitive type:false
Boolean is primitive type:false
boolean is primitive type:true
byte is primitive type:true
char is primitive type:true
short is primitive type:true
int is primitive type:true
long is primitive type:true
float is primitive type:true
double is primitive type:true
参考链接:java.lang.Class.isPrimitive()用法解析
3rd PART
理解AccessibleObject.setAccessible
//将fields的 accessible 标志设置为指定的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查。
AccessibleObject.setAccessible(fields, true);
AccessibleObject.setAccessible
:
将此对象的 accessible 标志设置为指定的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查。
如果 flag 为 true ,并且不能更改此对象的可访问性(例如,如果此元素对象是 Class 类的 Constructor 对象),则会引发 SecurityException。
4th PART
理解getType()
//获取f的类型
Class t = f.getType();
我们通过一个代码示例来理解:
另外,在程序清单5-13中我们学习了无参的getFields()
方法,通过以下示例代码可以加深对有参方法getField(String name)
的理解。
代码:
import java.lang.reflect.Field;
import java.util.ArrayList;
public class TypeTest {
public static void main(String[] args) throws NoSuchFieldException,
SecurityException, IllegalArgumentException, IllegalAccessException {
Field field = SampleClass.class.getField("sampleField");
Field field2 = SampleClass.class.getField("sampleField2");
Field field3 = SampleClass.class.getField("sampleField3");
Field field4 = SampleClass.class.getField("sampleField4");
System.out.println("Integer Field: " + field.getType());
System.out.println("int Field: " + field2.getType());
System.out.println("long Field: " + field3.getType());
System.out.println("ArrayList<Double> Field: " + field4.getType());
}
}
class SampleClass {
public static Integer sampleField = 5999;
public static int sampleField2 = 5999;
public static long sampleField3 = 5999;
public static ArrayList<Double> sampleField4;
}
输出:
Integer Field:class java.lang.Integer
int Field:int
long Field:long
ArrayList<Double> Field:class java.util.ArrayList
3.重要API
-
void setAccessible(boolean flag)
为反射对象设置可访问标志。flag为true表明屏蔽Java语言的访问检查,使得对象的私有属性也可以被查询和设置。boolean isAccessible()
返回反射对象的可访问标志的值。static void setAccessible(AccessibleObject[] array,boolean flag)
是一种设置对象数组可访问标志的快捷方法。
-
Field getField(String name)
Field getField()
返回指定名称的公有域,或包含所有域的数组。Field getDeclaredField(String name)
Field getDeclaredFields()
返回类中声明的给定名称的域,或者包含声明的全部域的数组。
-
Object get(Object obj)
返回obj对象中用Field对象表示的域值。void set(Object obj,Object newValue)
用一个新值设置Obj对象中Field对象表示的域。
java.lang.reflect.AccessibleObject
java.lang.Class
java.lang.reflect.Field
如有谬误或不完善之处,恳请斧正!