2017-07-26 26 views
2

在我們的項目中某些數據類(POJO used for API Request & Response)被overridding的toString()方法,以提供有意義的信息 - 但某些數據類覆蓋toString()如何找到其數據類沒有覆蓋toString()方法的Java項目

當應用程序打印其中toString()未被覆蓋的數據類的logs時,它們不打印他們只稱爲對象類toString()的有意義的信息。

所以我們想識別那些數據類並且提供toString()implementation

有沒有什麼方法可以識別toString()方法不是implemented

尋找每個數據類和檢查toString()方法是繁瑣和耗時的任務。

有沒有更好的方法來做到這一點,使用一些像日食或其他工具?

回答

1

的一種方法是使用Reflections Library獲得給定包裹內的所有類,請注意,這並不像匿名的,私人的,局部的,人跡罕至,...等,所以最好的辦法類的工作是做手工按@GhostCat答案

現在你應該走這條路,這是怎麼做的,首先通過Reflections Library獲得課程,從this answer引用@Staale

Reflections reflections = new Reflections("my.project.prefix"); 

Set<Class<? extends Object>> allClasses = 
      reflections.getSubTypesOf(Object.class); 

然後遍歷類,並檢查的toString是在類本身

for(Class clazz : allClasses) 
{ 
    if(!clazz.getMethod("toString").getDeclaringClass().getName().equals(clazz.getName())) 
     System.out.println("toString not overridden in class "+clazz.getName()); 
} 
+0

上面的方法適用於我,因爲沒有匿名類。 –

1

使用反射。在我的項目中,我爲每個域對象編寫測試。測試檢查toString方法是否來自Object班或來自我的班級。代號爲測試

/** 
    * Passes if class has overridden toString method. Fails otherwise. 
    */ 
    public static void toStringTest(Object o) throws NoSuchMethodException { 
     Class<?> clazz = o.getClass().getMethod("toString").getDeclaringClass(); 
     assertThat(clazz).isNotEqualTo(Object.class) 
       .withFailMessage("expecting method toString to be defined in actual class"); 
     assertThat(o.toString()).isNotEmpty(); 
    } 

然後有SomeClass類,在SomeClassTest我調用它,如下所示

public void shouldOverrideToString() throws NoSuchMethodException { 
     TestUtils.toStringTest(new SomeClassTest()); 
    } 

如果你想找出不重寫的toString所有類,您可以編寫工具,將掃描classpath併爲每個類(從你的包中)調用這樣的測試。但是這種方法有侷限性。並不是所有的類都需要toString。服務類,REST控制器等不需要toString。所以自動化會給你帶來很多誤報。您可以只掃描包含模型類的包(如果您將模型保存在單獨的包中)或使用自定義註釋對模型類進行註釋(然後只掃描帶註釋的類),但我認爲這樣的解決方案不值得付出努力。

最後,你可以使用https://projectlombok.org/https://immutables.github.io/https://github.com/google/auto/tree/master/value 這些庫使用代碼生成/ anotation處理自動生成等號/哈希碼/的toString。我使用Immutables,它工作得很好。即使將遺留數據模型遷移到Immutables也很簡單。

在我的項目中,我爲每個域對象編寫了這樣的測試。

+0

'New SomeClassTest()':這意味着該類必須是已知的。OP明確指出,他希望快速識別那些不會覆蓋'toString'方法的類。 – Seelenvirtuose

+0

編輯我的答案如何擴展我的解決方案。 –

2

當類不是覆蓋toString()時 - 它必須使用默認的實現,其中包含的類名。因此:檢查您的日誌並向後工作!

或者,你可以使用反射:

  • 啓動一個JVM運行包含在類路徑中的所有你的類
  • 掃描所有類的類路徑(或如果可能:那些類似於你的POJO)
  • 檢查每個類是否實現toString()

顯然這是很多工作 - 但沒有技術上的原因,爲什麼不應該這樣做。當然,這裏的主要問題可能是減少要查看的類的數量 - 包含500個類的列表也不會太有用。

和另外一個(潛在的)選項:創建一個使用反射實現toString()和可能等於(一PojoBase類)/ hashCode()方法 - 然後只需確保您所有的POJO類擴展基類。 (免責聲明:當然是你要明白做這樣的事情的後果,但我們最近建立使得使用Apache下議院EqualsBuilder一個BaseBean,...調用這個方法。)

2

這裏聲明是,如果你的數據類有一個是工作的想法共同的抽象類他們繼承。

在超介紹一個抽象toString()

public abstract String toString(); 

這將迫使所有子類覆蓋它,你會得到,如果他們不編譯錯誤。

不幸的是這種方法有一個主要的限制。如果你有這樣的事情:

abstract class A { 
    public abstract String toString(); 
} 

class B extends A { 
    public String toString() { 
     return "foo"; 
    } 
} 

class C extends B { 
} 

它不會注意到C失蹤toString()

這種方法可能不適合你,但我想我會發布它,所以也許它會幫助其他人閱讀你的問題。