API 是调用方和被调用方之间的约定。最常见的 API 滥用是由于调用方未能遵守此约定的终止导致的。例如,如果某个程序在调用 chroot() 后未能调用 chdir(),则违反了用于指定如何安全地更改活动根目录的约定。库滥用的另一个典型示例是期望被调用方向调用方返回可信的 DNS 信息。在这种情况下,调用方通过对被调用方行为做出某种假设(返回值可用于身份验证目的)滥用其 API。另一方也可能违反调用方-被调用方约定。例如,如果编码器子类化 SecureRandom 并返回一个非随机值,则将违反此约定。
Equals()
的对象上调用了 Equals()
。Equals()
的类(或任何超类/接口)上调用 Equals()
会导致调用继承自 System.Object
的 Equals()
方法。Object.Equals()
将比较两个对象实例,查看它们是否相同,而不是比较对象成员字段或其他属性。尽管可以合法地使用 Object.Equals()
,但这通常表示存在错误代码。
public class AccountGroup
{
private int gid;
public int Gid
{
get { return gid; }
set { gid = value; }
}
}
...
public class CompareGroup
{
public bool compareGroups(AccountGroup group1, AccountGroup group2)
{
return group1.Equals(group2); //Equals() is not implemented in AccountGroup
}
}
equals()
的对象上调用了 equals()
方法。equals()
的类(或任何超类/接口)上调用 equals()
会导致调用继承自 java.lang.Object
的 equals()
方法。Object.equals()
将比较两个对象实例,查看它们是否相同,而不是比较对象成员字段或其他属性。尽管可以合法地使用 Object.equals()
,但这通常表示存在错误代码。
public class AccountGroup
{
private int gid;
public int getGid()
{
return gid;
}
public void setGid(int newGid)
{
gid = newGid;
}
}
...
public class CompareGroup
{
public boolean compareGroups(AccountGroup group1, AccountGroup group2)
{
return group1.equals(group2); //equals() is not implemented in AccountGroup
}
}
finalize()
方法应该调用 super.finalize()
。finalize()
方法调用 super.finalize()
是一种非常好的做法 [1]。super.finalize()
。
protected void finalize() {
discardNative();
}
private void writeObject(java.io.ObjectOutputStream out) throws IOException;
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;
private void readObjectNoData() throws ObjectStreamException;
getOutputStream
之后调用 getWriter()
也是错误的做法,反之亦然。HttpServletRequest
、重定向 HttpServletResponse
或者刷新 servlet 的输出流缓冲区会导致提交相关的数据流。后续执行的任何缓冲区重置或数据流提交操作,例如额外的刷新或重定向,将会导致出现 IllegalStateException
。ServletOutputStream
或 PrintWriter
(但不能同时使用)将数据写入响应数据流。调用 getOutputStream()
之后调用 getWriter()
或者反向调用,也会导致出现 IllegalStateException
。IllegalStateException
会阻止响应处理程序完成运行,轻易地使其中断响应。这会导致服务器不稳定,也间接表明 servlet 实现不正确。例 2:相反,以下代码在请求转发之后会尝试写入并刷新
public class RedirectServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
...
OutputStream out = res.getOutputStream();
...
// flushes, and thereby commits, the output stream
out.flush();
out.close(); // redirecting the response causes an IllegalStateException
res.sendRedirect("http://www.acme.com");
}
}
PrintWriter
的缓冲区。
public class FlushServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
...
// forwards the request, implicitly committing the stream
getServletConfig().getServletContext().getRequestDispatcher("/jsp/boom.jsp").forward(req, res);
...
// IllegalStateException; cannot redirect after forwarding
res.sendRedirect("http://www.acme.com/jsp/boomboom.jsp");
PrintWriter out = res.getWriter();
// writing to an already-committed stream will not cause an exception,
// but will not apply these changes to the final output, either
out.print("Writing here does nothing");
// IllegalStateException; cannot flush a response's buffer after forwarding the request
out.flush();
out.close();
}
}
Content-Length
头文件设为负值。Content-Length
请求标题表示开发者对0
或Content-Length
。
URL url = new URL("http://www.example.com");
HttpURLConnection huc = (HttpURLConnection)url.openConnection();
huc.setRequestProperty("Content-Length", "-1000");
Content-Length
头文件设为负值。Content-Length
请求标题表示开发者对0
或Content-Length
头文件设置为负值:
xhr.setRequestHeader("Content-Length", "-1000");
ToString()
在数组上被调用。ToString()
表示开发者希望将数组内容作为字符串返回。然而,在数组上直接调用 ToString()
将返回一个字符串值,它包含该数组的类型。System.String[]
。
String[] stringArray = { "element 1", "element 2", "element 3", "element 4" };
System.Diagnostics.Debug.WriteLine(stringArray.ToString());
toString()
在数组上被调用。toString()
表示开发者希望将数组内容作为字符串返回。然而,在数组上直接调用 toString()
将返回一个字符串值,它包含内存中该数组的类型和哈希码。[Ljava.lang.String;@1232121
。
String[] strList = new String[5];
...
System.out.println(strList);