军规
军规一:【避免在程序中使用魔鬼数字,必须用有意义的常量来标识。】
军规二:【明确方法的功能,一个方法仅完成一个功能。】
军规三:【方法参数不能超过5个】
军规四:【方法调用尽量不要返回null,取而代之以抛出异常,或是返回特例对象(SPECIAL CASE object,SPECIAL CASE PATTERN);对于以集合或数组类型作为返回值的方法,取而代之以空集合或0长度数组。】
军规五:【在进行数据库操作或IO操作时,必须确保资源在使用完毕后得到释放,并且必须确保释放操作在finally中进行。】
军规六:【异常捕获不要直接catch (Exception ex) ,应该把异常细分处理。】
军规七:【对于if „ else if „(后续可能有多个else if …)这种类型的条件判断,最后必须包含一个else分支,避免出现分支遗漏造成错误;每个switch-case语句都必须保证有default,避免出现分支遗漏,造成错误。】
军规八:【覆写对象的equals()方法时必须同时覆写hashCode()方法。】
军规九:【禁止循环中创建新线程,尽量使用线程池。】
军规十:【在进行精确计算时(例如:货币计算)避免使用float和double,浮点数计算都是不精确的,必须使用BigDecimal或将浮点数运算转换为整型运算。】
碎拾
- 没有什么就new什么
- 普通方法可以和构造方法同名,因为调用方式不同!
- main方法也可以重载哦!
- while和do_while都是while条件不满足时退出循环!!!!!
- 形参是局部变量!
- 注意:子类 instanceof 父类 ===> true
- 一个数据的读和写不可能同时存在
- 数据类型分为基本数据类型(或叫做原生类、内置类型)和引用数据类型。
- java中 除基本数据类型不是对象外,其他数据类型都是对象
- Java关键字都是小写
- =赋值是将原值直接覆盖
- A is a B A继承B
A has a B B是A的一属性 - Java中注意反斜杠\转义
如:不能直接输入正则化:"\w+" 则必须为:
String[] ss = str.split("\\w+");
String filePath = "C:\\必须两斜杠.txt"
- 接口其实也是个父类!也可以: 子类 instanceof 接口(可以去判断该类是否实现此接口动作)
- 类在强制类型转换中,如果类转换成接口类型。那么类和接口之间不需要存在继承关系,也可以转换。(五中口中的骚操作)
- ASCLL码是7位编码【因为发现7个就够了】,一共可组合成128个不同的ASCLL码,其中可以打印的有95个【可以从键盘上输入的字符,包括Shift、空格】,而不可打印的有33个。
- Map集合下key永远都是不可重复的!!!(LinkedHashMap只是有序了而已)
- 所有的数据结构都是在内存中实现、使用的!(硬盘就是将内存中的数据结构序列化后存储)
- 排序compareTo(); 查找equals();
- 只要数组一创建就会初始化默认值(数组就是个对象啊,对象初始化属性值肯定会赋默认值)
- Arrays中对于集合类的sort()方法主要采用TimSort算法(优化的归并算法);
对于数组的算法主要采用DualPivotQuicksort.sort()(优化的快速排序算法) - A%B = C;取模运算,余数符号与被除数符号相同(A与C同符号)
- 指针: 8 字节(或者是 4 字节,这个大小跟 CPU、操作系统、编译器等有关)
- 数组copy只记这个就行了System.arraycopy(stones,0,stones,0,length);
- 小顶堆变大顶堆🤡:PriorityQueue heap = new PriorityQueue<>((x,y) -> (y-x));
- 基本数据类型运算会至少转为int类型:if(‘a’ > ‘b’)
- 选中一段代码ctrl+Alt+T
- Thread.currentThread()永远是.start这个线程的线程实例
- 注意foreach永远只能遍历,可不能赋值。
- join只能放在start之后:没有start的话,join后发现线程并没有运行,所以不会阻塞,直接跳到下一句。(程序只会顺序执行,遇见start后可不会回头去join)
- notify()并不会立即释放锁,会等到同步代码块全部执行完。(他只是把等待池中的线程叫道锁池中啊)
- interrupt()也可以通过异常唤醒wait()/sleep()线程。
- wait(long timeout): timeout:最大等待时间(毫秒),超过会被唤醒,再次进入锁池
- Integer.bitCount(int i):计算i在转换为二进制数后1的数量。
- Timer的schedule(),ScheduledExecutorServic的scheduleAtFixedRate()中当任务执行时常超过间隔时间,则任务执行完立即执行下次任务! (scheduleWithFixedDelay()则是执行完后计时)
- 线程中的任务就是run(){…作业…}
- 提高锁性能:(1)减少持有锁时间;(2)减少锁的粒度(即锁的大小);(3)建议使用ReentrantReadWriteLock。(4)锁分离思想:LinkedBlockingQueue中take()一把锁(操作队列头部);put()一把锁(操作队列尾部),两个可以同时进行。
- JVM对锁优化:(1)锁偏向:一个线程释放完锁,很容易再次得到锁。
- try中语句执行才会去执行finally,try不执行,finally不会执行(是一个整体撒子呦!)
- 定时器一般都是守护线程,或者用cancel()终止Timer,不然会一直运行下去,程序不结束
- Arrays中: public static List asList(T… a)
- Callable< V >是 任务.get() 获得返回值
- 比较器:基本数据类型用静态方法compare(),如:Integer.compare(int x, int y) ;引用数据类型实现了Comparable< T >,所以使用实例方法compareTo() (基本数据类型也实现了,但是包装后才能用)
- Deque< Integer > stack = new ArrayDeque<>(); 代替栈
- 日期总结对比:
范围 | 常用语法 | 参数口诀 |
---|---|---|
Java | java.util.Date中的 new Date(),java.time下的LocalDateTime.now() | 小大小大小小大 |
MySQL | now(),curdate(),curtime() | 只有两大Y、H |
Linux | date | 只有两小m、d |
- 类路径下找resource只需要写文件名(getResource和ResourceBundle)【放到源码src下也没事,编译器也会copy到类路径下(字节码)】
- T 和 < T > T的区别:
所在class使用泛型:(常用)
private T getListFisrt(List<T> data) { }
所在class没有使用泛型:【不用类型强转了!!!】
private <T> T getListFisrt(List<T> data) { }
- 单元测试 Ctrl + Shift + T
- goto、const为保留字(以后要使用的关键字)
- 不报错!!!!输出true!!!!
if(flag = true){
System.out.println("true");}
- 多态不止重写,还有重载!!!
- 运行速度StringBuilder>StringBuffer>String
- 即使有static,但是代码还是得按行执行啊!!!
- input往内存的缓存数组中读读读!!!!!!!
- 注意:真实开发中使用引用数据类型,不要使用基本数据类型。使用Integer,不要使用int!!! 因为Integer可以为null(比如自增长的id就可以设为null进行插入!!!)
- 啊啊啊数组:Arrays.toString(数组)!!!
- 永远是父类的方法先执行(super()默认在所有构造方法第一行!但super()只是利用构造方法实例化变量,并不是单独创建对象!!!)
- 枚举类是单例模式,所以构造方法只能是private【因为枚举实例化一次,以后不再变了,所以使用单例模式,大家共同使用】
- 当一个线程需要调用对象的 wait()方法的时候,这个线程必须拥有该对象的锁!! ,所以要使用synchronized(对象)中对象的wait()方法!!!
- synchronize自旋:
很多 synchronized 里面的代码只是一些很简单的代码,执行时间非常快。不妨让等待锁的线程不要被阻塞,而是在 synchronized 的边界做忙循环,这就是自旋。如果做了多次循环发现还没有获得锁,再阻塞,这样可能是一种更好的策略。 - 线程池中 submit() 和 execute() 方法有什么区别?
接收参数:execute()只能执行 Runnable 类型的任务。submit()可以执行 Runnable 和 Callable 类型的任务。
返回值:submit()方法可以返回持有计算结果的 Future 对象,而execute()没有
几种数据结构的Java用法
栈stack
Deque<T> stack = new ArrayDeque<>();
添加元素: stack.push(T);
弹出栈顶元素: stack.pop(); //removes and returns the first element
队列queue
Queue<T> deque = new LinkedList<>();
队尾入队: deque.add(T);
队头出队: deque.poll(); //Retrieves and removes the head of this queue
修饰查询【不允许记忆!!!别记!!!】
static | final | 访问权限 | |
---|---|---|---|
成员变量 | Y | Y | Y |
普通方法 | Y | Y | Y |
内部类 | Y | Y | Y |
普通类 | Y | Y | |
局部变量 | Y | ||
构造方法 | Y |
注:内部类 内部情况就和正常类一样了
访问权限设置的是权限;
ststic设置的是存放位置;
final保证不变!
GC
JVM内存结构
java.lang.System
System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
经典
- 先初始化判断null、范围等
- 不考虑特殊,常规思路做循环
- 判断:
if(特殊点){
......
}else{//常规化
......
}
经典toString()
- 判断是否为null
- 创建循环,直至达到结束标志,直接return
经典
单链表删除元素
- 判断范围
- 常规情况做循环
- 判断特殊情况做出不同对策
经典while
好多都有返回值呀
你品,你细品:
java中能返回一个确定值的所有方法都有返回值,eg:
- add(元素);返回boolean
- remove(index);返回被删除的元素
- remove(Object);返回boolean
- append(Object);返回append后的StringBuilder
- 赋值语句返回被赋予的值!
也有一些void方法(一般没有参数的方法):
6. it.remove();
7. list.clear();
四种引用
强引用:不会被GC回收的对象,哪怕内存不够,JVM宁愿抛出异常OutOfMemoryError也不会去回收。
软引用:如果内存空间足够,GC就不会去回收这个对象,如果内存不足,就会回收,软引用可有和ReferenceQueue(引用队列)联合使用,如果软引用所引用的对象被GC回收,JVM就会把这个软引用加入到引用队列中。常常被用来实现缓存技术,比如网页缓存,图片缓存等
弱引用:一旦发现只有弱引用的对象,不管当前内存空间是否足够,都会回收它的内存。 真是因为这个特性,所以弱引用常用于Map数据结构中,引用占用空间内存较大的对象。
虚引用:也成幽灵引用,是最弱的引用,如果一个引用只有虚引用,那么他就和没有引用一样,随时可能被回收。 他的构造方法必须传递RefenceQueue参数,当GC准备回收一个对象时,发现它还有虚引用,就会在回收前,把虚引用加入到引用队列中,程序可以通过判断队列中是否加入虚引用来判断被引用的对象是否将要GC回收,从而可以在finalize方法中采取措施。