Java核心技术卷I程序清单5-14及5-15

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


  1. 代码
  2. 分析
  3. 重要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 typefalse
Boolean is primitive typefalse
boolean is primitive typetrue
byte is primitive typetrue
char is primitive typetrue
short is primitive typetrue
int is primitive typetrue
long is primitive typetrue
float is primitive typetrue
double is primitive typetrue

参考链接: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

java.lang.reflect.AccessibleObject


void setAccessible(boolean flag)
为反射对象设置可访问标志。flag为true表明屏蔽Java语言的访问检查,使得对象的私有属性也可以被查询和设置。

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

static void setAccessible(AccessibleObject[] array,boolean flag)
是一种设置对象数组可访问标志的快捷方法。


java.lang.Class


Field getField(String name)
Field getField()
返回指定名称的公有域,或包含所有域的数组。

Field getDeclaredField(String name)
Field getDeclaredFields()
返回类中声明的给定名称的域,或者包含声明的全部域的数组。


java.lang.reflect.Field


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

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


如有谬误或不完善之处,恳请斧正!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值