如何使用 ToStringBuilder有效覆盖toString() 方法

ToStringBuilder 是 apache commons lang 库提供的实用程序类。
它提供了对数据的一致性和更好的控制,对象应该使用 toString() 方法以及以哪种格式公开。
它还可以通过消除在子类中覆盖 toString() 方法的需要来帮助消除代码大小。
它可用于构建某种设计模式以充分利用其提供的功能。

要在项目中包含 commons-lang,请在 maven 配置文件中添加以下依赖项。

<dependency>
	<groupId>commons-lang</groupId>
	<artifactId>commons-lang</artifactId>
	<version>2.5</version>
</dependency>

为了演示 ToStringBuilder 在各种场景中构建 toString() 方法的各种可能用法,我借助了三个模型类,例如:AbstractUser.java、WebUser.java 和 GuestUser.java。

AbstractUser.java

package com.onitroad.model;
import java.io.Serializable;
import org.apache.commons.lang.builder.ToStringBuilder;
import com.onitroad.style.CustomToStringStyle;
public abstract class AbstractUser implements Serializable
{
	private static final long serialVersionUID = 1L;

	private int id;
	private String firstName;
	private String lastName;
	private String age;

	//Setterss and getters
}

WebUser.java

public class WebUser extends AbstractUser 
{
	private static final long serialVersionUID = 1L;
	private Date lastLoggedIn;
	public Date getLastLoggedIn() {
		return lastLoggedIn;
	}
	public void setLastLoggedIn(Date lastLoggedIn) {
		this.lastLoggedIn = lastLoggedIn;
	}
}

GuestUser.java

public class GuestUser extends WebUser
{
	private static final long serialVersionUID = 1L;
	private String location;
	public String getLocation() {
		return location;
	}
	public void setLocation(String location) {
		this.location = location;
	}
}

各种使用示例

  1. toString() 方法是最顶级的超类,被所有子类完美使用

我们可以在最顶层的超类中使用一次 Object 类的覆盖 toString() 方法,例如:在我们的例子中是 AbstractUser.java。
如果所有子类没有提供自己版本的 toString() 方法,则此方法将可供所有子类使用。

@Override 
public String toString() 
{ 
	return ToStringBuilder.reflectionToString(this); 
}

如果 toString() 在子类中未被覆盖,则上述方法能够为类及其子类提供所有可用信息。

package com.onitroad;
import java.util.Date;
import com.onitroad.model.GuestUser;
import com.onitroad.model.WebUser;
public class ToStringDemoUsage 
{
	public static void main(String[] args) 
	{
		GuestUser guest = getGuestUser();
		System.out.println(guest);
	}

	public static GuestUser getGuestUser()
	{
		GuestUser user = new GuestUser();
		user.setId(100);
		user.setFirstName("Jamez");
		user.setLastName("Gupta");
		user.setAge("30");
		user.setLastLoggedIn(new Date());
		user.setLocation("New Amsterdam");
		return user;
	}
}

输出:

com.onitroad.model.GuestUser@d1f24bb[location=New Amsterdam,lastLoggedIn=Mon Jun 03 13:31:05 IST 2013,id=100,firstName=Jamez,lastName=Gupta,age=30]
  1. 任何字段类型的自定义格式,如日期

我们可以在 toString 方法中为任何字段类型强制执行自定义格式,这也与 toString() 实现不紧密耦合。
自定义格式化程序示例如下:

package com.onitroad.style;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.lang.builder.ToStringStyle;
public class CustomToStringStyle extends ToStringStyle
{
	private static final long serialVersionUID = 1L;
	protected void appendDetail(StringBuffer buffer, String fieldName, Object value) 
	{
	     if (value instanceof Date) 
	     {
	    	 value = new SimpleDateFormat("yyyy-MM-dd").format(value);
	     }
	     buffer.append(value);
	 }
}

要使用此格式化程序,请将其传递给这样的方法。

@Override 
public String toString() 
{ 
		return ToStringBuilder.reflectionToString(this, new CustomToStringStyle()); 
}

输出:

com.onitroad.model.GuestUser@7910769b[location=New Amsterdam,lastLoggedIn=2013-06-03,id=100,firstName=Jamez,lastName=Gupta,age=30]
  1. 通过简单的方法调用在子类中使用来自超类的信息

如果我们想覆盖子类中的 toString() 方法,并且我们想在向超类添加任何内容之前添加从超类检索到的信息,请这样做。

public class WebUser extends AbstractUser
{
	//Other code

	@Override
	public String toString() 
	{
		return new ToStringBuilder(this)
				.appendSuper(super.toString())
				.append("lastLoggedIn", lastLoggedIn).toString();
	}
}

输出:

com.onitroad.model.GuestUser@22aed3a5[location=New Amsterdam,lastLoggedIn=2013-06-03,id=100,firstName=Jamez,lastName=Gupta,age=30,CustomMessage=I have been added additionally]
  1. 仅使用特定级别的继承层次结构的信息

假设在任何子类中我们确实需要公开所有超类的所有字段,我们也可以通过这种方式将信息包含到某个级别:

public class GuestUser extends WebUser
{
	@Override
	public String toString() 
	{
		return ToStringBuilder.reflectionToString(this,new CustomToStringStyle(),true,WebUser.class);
	}
}

输出:

com.onitroad.model.GuestUser@18dd7404[location=New Amsterdam,lastLoggedIn=2013-06-03]
  1. 只包含你想要的信息

有时我们不想在 toString 方法中包含类中的所有字段。
好吧,你也有办法在这里做到这一点。

public abstract class AbstractUser implements Serializable
{
	//Other code

	@Override
	public String toString() {
		return new ToStringBuilder(this)
				.append("firstName", firstName)
				.append("lastName", lastName)
				.append("age", age).toString();
	}
}
public class GuestUser extends WebUser
{
	//Other code
	@Override
	public String toString() 
	{
		return new ToStringBuilder(this)
		.appendSuper(super.toString())
		.append("location", location).toString();
	}
}

输出:

com.onitroad.model.GuestUser@6483dae1[firstName=Jamez,lastName=Gupta,age=30,location=New Amsterdam]
日期:2020-09-17 00:09:23 来源:oir作者:oir