您的位置:首页 > 其它

System.out.printf使用以及注意点

2019-12-05 15:34 513 查看

一、System.out.printf格式化输出

1、常用控制符

控制符

说明

%d

按十进制整型数据的实际长度输出。

%ld

输出长整型数据。

%md

m 为指定的输出字段的宽度。如果数据的位数小于 m,则左端补以空格,若大于 m,则按实际位数输出。

%u

输出无符号整型(unsigned)。输出无符号整型时也可以用 %d,这时是将无符号转换成有符号数,然后输出。但编程的时候最好不要这么写,因为这样要进行一次转换,使 CPU 多做一次无用功。

%c

用来输出一个字符。

%f

用来输出实数,包括单精度和双精度,以小数形式输出。不指定字段宽度,由系统自动指定,整数部分全部输出,小数部分输出 6 位,超过 6 位的四舍五入。

%.mf

输出实数时小数点后保留 m 位,注意 m 前面有个点。

%o

以八进制整数形式输出,这个就用得很少了,了解一下就行了。

%s

用来输出字符串。用 %s 输出字符串同前面直接输出字符串是一样的。但是此时要先定义字符数组或字符指针存储或指向字符串,这个稍后再讲。

%x(或 %X 或 %#x 或 %#X)

以十六进制形式输出整数,这个很重要。

代码演示:

public static void main(String[] args) {
2         //最常用的主要是三个:字符串 %s, 整型%d, 浮点型保留小数位%.mf(m表示小数点后m位), \n表示换行符
3         System.out.printf("*学生资料*\n 姓名:%s\n 年龄:%d岁\n 考试成绩(保留两位小数): %.2f\n",
"小明", 15, 98.456);
4     }

控制台显示:

class StringTest {

public static void main(String[] args) {
//  testOperatorPlus();
//testAppend();
testFormat();
}

private static void testFormat() {
Runtime runtime = Runtime.getRuntime();
long memory;
long prev_time;
int i;
long time;
StringBuilder sb = new StringBuilder();
memory = runtime.freeMemory();
prev_time = System.currentTimeMillis();
for (i = 0; i < 10000; i++) {
String s = String.format("Blah %d Blah %d Blah %d", i, i, i);
}
long ww=runtime.freeMemory();
time = System.currentTimeMillis() - prev_time;
memory = memory - ww;
System.out.println("Time: " + time + "    Memory Usage: " + memory);
}

private static void testAppend() {
Runtime runtime = Runtime.getRuntime();
long memory;
long prev_time;
int i;
long time;
StringBuilder sb = new StringBuilder();
memory = runtime.freeMemory();
prev_time = System.currentTimeMillis();
for (i = 0; i < 10000; i++) {
sb.append("Blah ");
sb.append(i);
sb.append("Blah ");
sb.append(i);
sb.append("Blah ");
sb.append(i);
}
time = System.currentTimeMillis() - prev_time;
memory = memory - runtime.freeMemory();
System.out.println("Time: " + time + "    Memory Usage: " + memory);
}

private static void testOperatorPlus() {
Runtime runtime = Runtime.getRuntime();
long memory;
long prev_time;
int i;
long time;
StringBuilder sb = new StringBuilder();
memory = runtime.freeMemory();
prev_time = System.currentTimeMillis();
for (i = 0; i < 1000000; i++) {
String s = "Blah " + i + "Blah " + i + "Blah " + i;
}
time = System.currentTimeMillis() - prev_time;
memory = memory - runtime.freeMemory();
System.out.println("Time: " + time + "    Memory Usage: " + memory);
}
}
View Code 结果如下

Method Time(ms) Memory Usage(long)
‘+’ operator 102 44053736
StringBuilder.append 6 884768
String.foramt 110 22639000

 

 

 

 

        可以看到
StringBuilder.append
的执行时间和内存占用都是最优的。'+'运算符比直接调用
StringBuilder.append
要慢上不少,特别是要连接的字符串数量较多时,内存占用也特别大。
String.format
由于每次都有生成一个
Formatter
对象,较慢也是情理之中。 分析下String.format源码可以看到底层也用到了StringBuilder
public static String format(String format, Object... args) {
return new Formatter().format(format, args).toString();
}
public Formatter() {
this(Locale.getDefault(Locale.Category.FORMAT), new StringBuilder());
}

四、由此引发的优化探讨

在编码中 System.out.println将对象结果输出到控制台,会花费大量的CPU资源,因此发布的代码中不要包含System.out.println 或 System.out.printf。

使用日志框架代替,生产环境注意控制输出级别。

即便使用日志框架也要注意输出编码方式,例如 反例(不要这么做):
logger.debug("Processing trade with id: " + id + " symbol: " + symbol);

字符串拼接,这样会产生很多String对象,占用空间,影响性能。

另外关于日志输出其他建议:

1、使用[]进行参数变量隔离

如有参数变量,应该写成如下写法:

logger.debug("Processing trade with id:[{}] and symbol : [{}] ", id, symbol);
这样的格式写法,可读性更好,对于排查问题更有帮助。 2、并不是所有的service都进行出入口打点记录,单一、简单service是没有意义的(job除外,job需要记录开始和结束,)。 反例(不要这么做):
public List listByBaseType(Integer baseTypeId) {
log.info("开始查询基地");
BaseExample ex=new BaseExample();
BaseExample.Criteria ctr = ex.createCriteria();
ctr.andIsDeleteEqualTo(IsDelete.USE.getValue());
Optionals.doIfPresent(baseTypeId, ctr::andBaseTypeIdEqualTo);
log.info("查询基地结束");
return baseRepository.selectByExample(ex);
}

对于复杂的业务逻辑,需要进行日志打点,以及埋点记录,比如电商系统中的下订单逻辑,以及OrderAction操作(业务状态变更)。

如果所有的service为SOA架构,那么可以看成是一个外部接口提供方,那么必须记录入参。
调用其他第三方服务时,所有的出参和入参是必须要记录的(因为你很难追溯第三方模块发生的问题)

3、 生产环境需要关闭DEBUG信息

如果在生产情况下需要开启DEBUG,需要使用开关进行管理,不能一直开启。

      参考文章: https://www.jianshu.com/p/7eb224b9f064

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: