1. 程式人生 > >利用反射實現可供任意類使用的toString方法

利用反射實現可供任意類使用的toString方法

記錄下對Java反射的學習,以實現此toString方法為例

package com.xxx.javatest;

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 static final String TAG = "ObjectAnalyzer";
    // 記錄已經被訪問過的物件,防止迴圈引用
    private ArrayList<Object> visited = new ArrayList<>();

    /**
     * 可供任意類使用的toString方法
     * @param obj an object
     * @return 物件內的每個值轉換為字串
     */
    public String toString(Object obj) {

        if (null == obj) {
            return null;
        }
        if (visited.contains(obj)) {
            return "...";
        }
        visited.add(obj);
        // getClass返回一個Class型別的例項,這個例項裡面儲存著這個物件執行時的型別資訊
        Class cl = obj.getClass();
        // 如果這個物件是String型別的,則可以直接返回String
        if (cl == String.class) {
            return (String) obj;
        }
        // 陣列型別,需要特殊處理
        if (cl.isArray()) {
            // getComponentType用於獲取陣列內部資料型別
            String r = cl.getComponentType() + "[]{";
            // 通過反射獲得陣列長度,然後遍歷每個元素
            for (int i = 0; i < Array.getLength(obj); i++) {
                // 陣列內元素用逗號分隔
                if (i > 0) {
                    r += ",";
                }
                // 通過反射獲得陣列內第i個元素
                Object val = Array.get(obj, i);
                // isPrimitive用來判斷陣列內元素是否是基本資料型別
                if (cl.getComponentType().isPrimitive()) {
                    // 是基本資料型別,則直接加上去
                    r += val;
                } else {
                    // 否則的話,遞迴呼叫toString
                    r += toString(val);
                }
            }
            return r + "}";
        }
        String r = cl.getName();
        // 開始遍歷這個物件的所有域
        do {
            r += "[";
            // 獲得這個類的全部域
            Field[] fields = cl.getDeclaredFields();
            // 將所有域設為可訪問
            AccessibleObject.setAccessible(fields, true);
            // 遍歷所有域,獲得域的名字和值
            for (Field f : fields) {
                // 不是靜態域
                if (!Modifier.isStatic(f.getModifiers())) {
                    if (!r.endsWith("[")) {
                        r += ",";
                    }
                    // 獲得域名
                    r += f.getName() + "=";
                    try {
                        // 獲得域的型別
                        Class t = f.getType();
                        // 獲得域的值
                        Object val = f.get(obj);
                        // 如果是基本型別,則直接加
                        if (t.isPrimitive()) {
                            r += val;
                        } else {
                            // 否則遞迴呼叫
                            r += toString(val);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            r += "]";
            // 處理超類
            cl = cl.getSuperclass();
        } while (cl != null);
        return r;

    }

    // 測試
    public static void main(String args[]) {
        ArrayList<Integer> sq = new ArrayList<>();
        sq.add(2);
        sq.add(3);
        sq.add(4);
        System.out.println(new ObjectAnalyzer().toString(sq));
    }

}

結果:
java.util.ArrayList[elementData=class java.lang.Object[]{java.lang.Integer[value=2][][],java.lang.Integer[value=3][][],java.lang.Integer[value=4][][],null,null,null,null,null,null,null},size=3][modCount=3][][]


相關推薦

利用反射實現任意使用的toString方法

記錄下對Java反射的學習,以實現此toString方法為例 package com.xxx.javatest; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Array; impo

利用反射實現的複製

利用反射實現類的複製 筆者年前在專案中遇到資料複製報錯,根據排查,最終鎖定問題出在類的複製上面。經過多種嘗試,仍不行,遂放棄common.lang包中的辦法,利用反射寫個類複製的工具類。閒話不多說,直接上程式碼。 package com.xq.util; import ja

利用java反射機制實現javaweb自動呼叫方法

public class BookServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequ

3-3利用生成器實現叠代對象

start info com cal prim 生成 rime shell div 包含yield語句的函數就是生成器函數。函數裏有yield關鍵字,則是生成器,生成器內置有__iter__方法,只不過調用__iter__返回的是生成器本身,利用這一特性,可以創建一個可叠

利用photoView實現點選放大到全屏顯示的控制元件,效果類似於微信朋友圈點開看大圖

此控制元件繼承自ImageView,實現效果與微信朋友圈點開看大圖相似,點選控制元件後進入沉浸模式全屏顯示大圖,全屏時雙擊或手指拉伸可放大圖片,單擊會退出全屏 老規矩,先上控制元件實現程式碼: /** * 可點選放大全屏顯示的imageView * Created by Administ

BeanUtils(利用反射實現物件間相同屬性的複製)

BeanUtils 話不多說直接貼程式碼 下面是測試: 話不多說直接貼程式碼 /** * 利用反射實現物件之間相同屬性複製 * * @param source *

PHP利用反射實現物件呼叫方法

寫個例子: <?php class Test { function phone() { return '13888888888'; } function

利用Python實現K-Means聚並進行圖形化展示

利用K-means進行聚類,顯示聚類結果的各類別的數量,最終進行圖形化展示 。 import pandas as pd import numpy as np import matplotlib.pyplot as plt from scipy import stats import c

利用模板實現簡單的棧(陣列和單鏈表)

主要的功能是實現一個後進先出的列表,有入棧、出棧、返回大小、判空等基本功能 #pragma once using namespace std; const int MAXSIZE = 0xfff;

利用反射從C#字串獲取的屬性值

問題 在lua裡面能很容易的去利用字串去訪問屬性,但是在C#裡面有時候就很棘手,特別是在字串比較多的情況下。 方法 比如我們要讀取player表裡面的ID,Name,Age,Position。。。。。。 但是玩家表裡面會有很多資料,我們在以上四項是比

利用反射實現簡單的Spring註解注入例項

一時興起,這兩天看了看Spring的原始碼,就想寫一個簡單的Spring利用註解注入!!Spring的註解注入方式給了我們很方便的好處!大家應該都瞭解Spring的注入原理,在這裡寫下一個非常簡單的使用註解來注入的例項,做個小小的筆記! 要使用註解,那就絕對和反射離不開。摘

網路程式設計——用執行緒實現多客戶端訪問的伺服器

#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <string.h> #includ

網路程式設計——用程序實現多客戶端訪問的伺服器

#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <string.h> #includ

利用反射實現JavaBean的自動賦值(六)

最近開發公司的一個專案,因專案不是很大的專案,所以僅僅採用了spring MVC框架,但是資料庫很多表中的欄位至少15個,這樣當每次將資料庫表中的資料取出來放入javabean中時,寫setXXX方法總是要寫很多遍,而且容易出錯,很是麻煩,所以採用了反射和泛型的方式,自動

利用反射實現對sqlite3資料庫的crud(增刪改查)操作的一個baseAndroidDao封裝,安卓開發中

1.說明 博主主要是做java web後臺這一塊,但是偶爾做點安卓,發現安卓上沒有像Hibernate這種orm框架(....其實也沒有去找), 又覺得每次增刪改查都自己寫程式碼的話肯定是非常麻煩的,所以就寫了一個簡單的baseAndroidDao來封裝一些簡單的增刪改查操

Java利用反射實現物件之間相同屬性複製

package com.utils; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collection; import java.util.List; /** *

excel利用反射動態匯入到實體

package com.gomsws.util; import org.apache.commons.lang.StringUtils; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.xss

利用python實現批量插入列印資訊的方法

使用列印資訊是除錯程式的必備手段,但是面對下面兩種情況: 1.如果程式程式碼/原始檔較多,而一時之間又無法確定問題範圍,這個時候可能需要在多個檔案插入列印資訊 2.剛剛接手維護大型模組,想要了解執行流程,需要在有可能執行到的地方都加入trace 上述情況,如果手動在每個函式的開頭

利用TeamViewer實現喚醒遠端電腦一例方法

1)要喚醒的遠端電腦所在區域網要有公網IP。(區域網對外沒有公網固定IP的可通過動態IP繫結域名的方式,可自行參看網上資料)2)遠端電腦支援LAN喚醒功能。3)要有修改遠端電腦所在區域網路由器引數的許可權。4)  本地電腦和遠端電腦都要安裝TeamViewer,並且兩臺電腦要在同一賬戶下。備註:下文中將家中電

一種在客戶端利用js實現對資料校驗的方法

   通常為了減輕伺服器端的壓力會在客戶端利用js或其他指令碼對使用者填寫的需要提交的資料進行校驗,同時也會帶來使用者體驗的提升。下面介紹一種在客戶端利用js實現對資料進行校驗的方法,僅供參考。      現在假設使用者需要在客戶端通過後臺進行對產品類別的新增操作,利用js