-
人类不能理解flag代码
- 8-how-many-prime-numbers
package com.github.hcsp.controlflow;
public class Main {
public static void main(String[] args) {
System.out.println(howManyPrimeNumbers(5));
}
/**
* 给定一个数字n,返回1到n之间的质数(素数)个数,不包括n本身。
*
* <p>例如,n=5,返回2,因为1到5之间有2个质数:2和3。
*
* <p>提示:对于正整数n,如果用2到Math.sqrt(n)+1之间的所有整数去除,均无法整除,则n为质数。
*
* @param n 给定的数字
* @return 1到n之间(不包括n)质数的个数
*/
public static int howManyPrimeNumbers(int n) {
int k = 0;
for (int i = 2; i < n; i++) {
boolean flag = true;
for (int j = 2; j < Math.sqrt(n) + 1; j++) {
if ((i % j == 0) && (i != j)) {
flag = false;
break;
}
}
if (flag) {
k += 1;
}
}
return k;
}
}
复制代码
- 用人类更能理解的方式
- 写出让机器能阅读的代码一点都不难,难的是写出让人能阅读理解的代码
package com.github.hcsp.controlflow;
public class Main {
public static void main(String[] args) {
System.out.println(howManyPrimeNumbers(5));
}
/**
* 给定一个数字n,返回1到n之间的质数(素数)个数,不包括n本身。
*
* <p>例如,n=5,返回2,因为1到5之间有2个质数:2和3。
*
* <p>提示:对于正整数n,如果用2到Math.sqrt(n)+1之间的所有整数去除,均无法整除,则n为质数。
*
* @param n 给定的数字
* @return 1到n之间(不包括n)质数的个数
*/
public static int howManyPrimeNumbers(int n) {
int k = 0;
for (int i = 2; i < n; i++) {
if (isPrimeNumber(i)) {
k += 1;
}
}
return k;
}
private static boolean isPrimeNumber(int i) {
for (int j = 2; j < Math.sqrt(i) + 1; j++) {
if ((i % j == 0) && (i != j)) {
return false;
}
}
return true;
}
}
复制代码
什么是好的代码
- 短小精悍,且容易被人类阅读和理解
java中字符串是不可变的对象
- 如果执行+=操作就是创建了新的对象
1.png - 用StringBuilder比较好
package com.github.hcsp.controlflow;
public class Main {
/**
* 打印从start到end区间所有的奇数,包括start和end本身(若符合条件)。 注意,数字之间用英文逗号分隔。
*
* <p>例如,start=1,end=5,则打印1,3,5 又如,start=-2,end=2,则打印-1,1
*
* @param start 区间开始
* @param end 区间结束
*/
public static void printOddNumbersBetween(int start, int end) {
// String s = "";
// for (int i = start; i <= end; i++) {
// if (i % 2 != 0) {
// s += i + ",";
// }
// System.out.println(s);
// }
StringBuilder s = new StringBuilder();
for (int i = start; i <= end; i++) {
if (i % 2 != 0) {
s.append(i).append(",");
}
System.out.println(s);
}
}
public static void main(String[] args) {
printOddNumbersBetween(1, 5);
printOddNumbersBetween(-2, 2);
}
}
复制代码
不要用magic number,至少要写成常量
double IEEE 754 浮点数表 示
- Inf-> Infinity无限大, Nan-> Not a Number,不是实数
- 正浮点数除以0为+的nan,负浮点数除以0为-的nan
try-catch
- 成本非常高,try-catch的异常是有调用栈的
其次没法保证try...catch的异常是能希望被捕获的异常 - 除非没有办法,尽量不要用try...catch补获异常
代码可读性
- 避免多层嵌套
- 避免提交注释上去,如果之前能写出的代码之后肯定也能写出
git fetch的使用,添加远程仓库
3.png
pull request
- close中搜索模范 代码
重构的技巧
- refactor然后点击extract抽取成一个方法
- 好处,复用代码,有意义的名字有名字jvm会优化不用担心栈
reatainAll,hashmap和ArrayList的性能区别
- hashset是O(1)的
- ArrayList是O(n2)
代码写的越少越不容易出bug
循环创建新的对象
- 之前的对象会被垃圾回收
生成equals同时生成hash code的原因
- 这是一个最佳事件
碰到异常
- 最后抛出异常,不要只打印
- 如果一定要写ignored,就要仔细填写ignore的原因
catch (Exception ignored) {
// ignored
}
throw new RuntimeException(e);
复制代码
正则表达式
- 这个操作要放到全局,这样不会多次编译
java bean转json
- 只和getter有关系
警告错误的配置
- Inspections错误的配置
碰到重复代码
- 抽成方法
异或会有坑
- i和j相同会有问题
- 工程师的指责是保证程序正确稳定的运行,而不是为了炫技
尽量不要用flag
- 人阅读理解起来会很困难
- 绝大多数大学老师都不是合格的工程师
- 把if...else放到一个小的空间
不要把全局变量当作锁
多层人类理解起来很难
- 分层
optimize import
- 去掉无用导入
- 也可以对真哥哥文件夹使用快捷键,进行优化导入
Java命名约定
- 类大写
- 局部变量驼峰
- 常量大写字母+下划线
- 包纯小写
右键-inspect
- 找到代码的问题
- 然后一个个去解决
尽量导入不要用*
java doc
-
java的世界中有三种注释
- 单行
- 两个斜杠多行
- java doc非常特殊,是会被编译的。斜杠2个
*
号开始,会被渲染成html
@code 会被渲染成行内的html,好看的html
// @开头的是特殊的标签
复制代码
编译是怎么做的
- 文本文件 .java,首先会经历Lexer和Tokenizer变成一个个的词法单元,比如 int 空格 a = 123 ;,这个叫词法分析
- 然后会组织成词法树,语法分析用来检查parsing符不符合语法,lexing只是用来检测符不符合一个单元
- 有了树之后就可以做更多的检查,总之就是沿着树挨个去检查
避免空指针
// 不好
methodName.equals("getClass)
// 应该写成
"getClass".equals(methodName)
复制代码