控制符html |
说明编程 |
%d数组 |
按十进制整型数据的实际长度输出。架构 |
%ldapp |
输出长整型数据。框架 |
%mdide |
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 }
控制台显示:
另外System.out.printf有必定程度的输出格式化效果
输出结果:
若是 使用System.out.print(ln)格式就出现了明显不一样
package system.out; public class Printf { public static void main(String[] args) { //%表明格式化 //f表明输出浮点数,9表明输出长度,若是浮点数长度不足,则补空格,若是浮点数长度超出,则按实际长度输出,2表明保留小数点后几位小数 System.out.printf("%9.2f",1111.3); System.out.println(); //-号表明向左对齐,默认向右对齐 System.out.printf("%-9.2f", 1111.3); System.out.println(); //+号表明显示正负号 System.out.printf("%+9.2f", 1111.3); System.out.println(); //+-号表明显示正负号,且向左对齐 System.out.printf("%+-9.2f", 1111.3); System.out.println(); //d表明输出整数 System.out.printf("%4d",15); System.out.println(); //o表明输出8进制整数 System.out.printf("%-4o",15); System.out.println(); //x表明输出16进制整数 System.out.printf("%-4x",15); System.out.println(); //#x表明输出带有16进制标志的整数 System.out.printf("%#x",15); System.out.println(); //s表明输出字符串 System.out.printf("%-8s", "咱们是中心"); System.out.println(); //x$,整数加$表示第几个变量,若是不加,变量按默认顺序排列 System.out.printf("%2$-5s:夺得世界杯总冠军,进球数:%1$3d,对方进球:%3$2d", 4,"法国",2); } }
public PrintStream printf(String format, Object ... args) { return format(format, args); }
public PrintStream format(String format, Object ... args) { try { synchronized (this) { ensureOpen(); if ((formatter == null) || (formatter.locale() != Locale.getDefault())) formatter = new Formatter((Appendable) this); formatter.format(Locale.getDefault(), format, args); } } catch (InterruptedIOException x) { Thread.currentThread().interrupt(); } catch (IOException x) { trouble = true; } return this; }
能够看到和String.format底层实现相似调用Formatter()类的format方法。
public static String format(String format, Object... args) { return new Formatter().format(format, args).toString(); }
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); } }
结果以下
Method | Time(ms) | Memory Usage(long) |
‘+’ operator | 102 | 44053736 |
StringBuilder.append | 6 | 884768 |
String.foramt | 110 | 22639000 |
StringBuilder.append
的执行时间和内存占用都是最优的。'+'运算符比直接调用
StringBuilder.append
要慢上很多,特别是要链接的字符串数量较多时,内存占用也特别大。
String.format
因为每次都有生成一个
Formatter
对象,较慢也是情理之中。
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对象,占用空间,影响性能。
另外关于日志输出其余建议:
一、使用[]进行参数变量隔离
若有参数变量,应该写成以下写法:
logger.debug("Processing trade with id:[{}] and symbol : [{}] ", id, symbol);
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操做(业务状态变动)。
三、 生产环境须要关闭DEBUG信息
若是在生产状况下须要开启DEBUG,须要使用开关进行管理,不能一直开启。