今天做组件的时候需要连接微信测试号,GitHub上Action时代码没有出错,手机测试接不到消息。后来发现https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s中,%s误写为‘?’。好家伙,一个符号竟然浪费了许多时间,还是功夫不到家。
由此也引发了String.format()方法的延申思考。
在Java中,String.format()
方法用于创建格式化的字符串。在这个方法中,%s
是一个占位符,用于指示该位置将被后面参数列表中相应的字符串值所替换。具体来说,%s
对应于 String
类型的参数。
在正确的代码示例中:
java复制代码
String url = String.format("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s", accessToken); |
%s
将会被 accessToken
变量的值所替换。假设 accessToken
的值是 "YOUR_ACCESS_TOKEN_HERE"
,那么执行这行代码后,url
变量的值将会是:
https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=YOUR_ACCESS_TOKEN_HERE |
这种方式使得在构建需要动态插入数据的URL时非常方便和灵活。String.format()
方法还支持其他类型的占位符,如 %d
用于整数、%f
用于浮点数等,以便构建包含不同类型数据的字符串。
但是
如果尝试将 %s
替换为 ?
,在 String.format()
方法的上下文中,这会导致一个异常,因为 ?
不是一个有效的格式说明符。String.format()
方法期望在字符串中的每个 %
后面跟随一个有效的格式说明符,比如 %s
、%d
、%f
等,来指示如何格式化相应的参数。
当我写如下代码:
String url = String.format("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=?", accessToken); |
这里的 ?
不会被 accessToken
的值所替换,因为 ?
不是一个有效的占位符。相反,String.format()
会尝试将 ?
作为字符串的一部分直接保留在结果中,并且因为后面没有跟随有效的参数(在这个例子中,%s
才是期望的占位符),它可能会抛出一个 MissingFormatArgumentException
(如果后续还有其他有效的占位符和参数,但在这个特定例子中不会),或者更常见的是,如果 ?
后面没有其他占位符,它只会简单地忽略这个无效的格式说明符并继续处理字符串。
然而,在此例子中,由于 ?
后面没有其他占位符,并且 accessToken
参数没有被正确地用于替换任何占位符,所以 accessToken
的值实际上并没有被插入到字符串中。因此,url
变量的值将会是:
https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=? |
这并不是我们想要的结果,因为想要的是将 accessToken
的值插入到 URL 中。
为了修复这个问题,应该继续使用 %s
作为占位符,并确保它后面有相应的参数来替换它:
String url = String.format("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s", accessToken); |
这样,%s
就会被 accessToken
的值所替换,生成正确的 URL。
当然
“?”也是可以作为占位符使用的
?在JDBC的PreparedStatement
中用作参数占位符,这是另一种上下文,其中?
用于在执行SQL语句之前插入参数值。在PreparedStatement
中,可以使用setXXX()
方法(如setInt()
、setString()
等)为这些?
占位符提供值。
例如,在JDBC中,可能会看到这样的代码:
String sql = "SELECT * FROM users WHERE id = ?"; | |
PreparedStatement pstmt = connection.prepareStatement(sql); | |
pstmt.setInt(1, 123); // 将第一个?替换为整数123 | |
ResultSet rs = pstmt.executeQuery(); |
在这个例子中,?
是PreparedStatement
中用于参数化的占位符,它允许你在执行查询之前安全地设置参数值,从而防止SQL注入攻击。
但请注意,这种用法与String.format()
方法中的占位符(如%s
)是完全不同的。在String.format()
中,你需要使用%
后跟适当的格式说明符来指定如何格式化并插入参数值。如果你尝试在String.format()
中使用?
作为占位符,它将被视为普通字符,并且不会被任何参数值所替换。