Java技术杂记

本文是临时记录在本子上Java技术的初步整理, 一来举一反三, 二来练习双拼打字. 发现双拼方案里的自然码挺好用的. 搜狗双拼方案对单韵母的字采用”o+韵母”, 比如”安oj”, “二or”等. 自然码则是”安an”, “二er”, 符合传统拼音思维. 但是, 自然码美中不足的是”昂ang”为了兼容双拼2个键出字的规则, 强行将a作声母, 原本是”ang”的”H”键改为”ng”作韵母.


目录:

  • 代码规范
    • 硬编码
    • 其他问题
  • Java Enum
    • Enum的适用场景
    • Enum和switch结构的联系
    • Enum和switch结构的区别
  • Java基本类型和四则运算
    • 1 负数的余数如何优雅地避免数组下标越界
    • 3 强制转换和加减乘除的优先级
    • 2 你确定你的if判断式里是而不是
  • Java最多能开多少线程
  • 你必须了解的5条关于成员内部类的事
  • mysql语法
  • Eclipse调试
    • Eclipse调试快捷键
    • 多线程调试
    • 服务器后端调试
      • 显示Server栏目 配置tomcat
      • 部署项目
  • springHibernateTemplate
  • 可热插拔的软件架构实践_基于Spring框架的DI
  • Java文件输入输出
  • Java读取网页
    • 找不到网页时FileNotFoundException
  • JQuery语法
  • 最简单的多线程架构_Producer-Consumer BlockingQueue
  • 英语单词
  • javautilconcurrent
  • log4j2入门 配置 HelloWorld
  • java 15 不定长参数 17 switchString 调用equals
  • java没有unsigned int2开头的十位数 YYYYMMDD8位 int已够用
  • java synchronized多线程的本质
    • 夺权
  • Wizard项目管理
  • javaio
    • Reader和InputStream的区别
    • BufferedReaderWriterInputStreamOutputStream
  • Interface无修饰符 包访问权限
  • Serializeable Id用来保持和DB中的版本一致
  • Its never legal to start a thread more than once
  • 不考虑多线程安全 StringBuilder比StringBuffer快
  • 方法中定义的变量线程安全因为本质上是private的
  • 跨域CORS
  • web后端使用java 6语法是最佳实践
  • Java文件可以没有public class
  • 实际上静态内部类和外部类是一个级别的
  • -
    • ListMap实用初始化方法
    • 实现Map接口的类不允许重复主键
      • IdentityHashMap来帮忙
      • 为什么不用LinkedListEntryObjectObject
    • LinkedHashMapentrySetiterator按插入顺序遍历
  • 异常处理
    •  异常的栈信息输出到日志
    •  异常处理性能损失
    •  异常处理的必要性
    •  try-catch块后的代码在catch了Exception后依然被执行 所以最佳实践是把整个方法代码放在try-catch块中
  • 两种线程安全的HashMap
  • java7的多个异常必须相互之间没有继承关系
  • Java读取Excel doc pdf 图片
  • java传引用数组collection类 普通对象
  • 删除满足条件的链表元素
  • jericho用来解析html
  • iteye Java社区的巅峰-SOFOSC站长红薯是Java程序员
  • Redis 32 kv数据库
  • OSC莆田系插件技术改变生活
  • Gone with the windMargaret Mitchell飘乱世佳人
  • Hadoop版本
  • Apache oozie
  • Apache赞助商目录
  • by page存储过程 调用次数小粒度大 by function 便于重用
  • RESTFUL设计url规范
  • KPIKill person Idea
  • xml11和10区别
  • 如果不重用就不要写成方法
  • 区块连
  • 一切不logger的异常都是耍流氓
  • Java自带的代码API文档生成器 - jdkbinjavadocexe
    • 含中文注释的编码gbk的不可映射字符解决办法


代码规范

硬编码

在计算机程序或文本编辑中,硬编码是指将可变变量用一个固定值来代替的方法。用这种方法编译后,如果以后需要更改此变量就非常困难了。大部分程序语言里,可以将一个固定数值定义为一个标记,然后用这个特殊标记来取代变量名称。当标记名称改变时,变量名不变,这样,当重新编译整个程序时,所有变量都不再是固定值,这样就更容易的实现了改变变量的目的。尽管通过编辑器的查找替换功能也能实现整个变量名称的替换,但也很有可能出现多换或者少换的情况,而在计算机程序中,任何小错误的出现都是不可饶恕的。最好的方法是单独为变量名划分空间,来实现这种变化,就如同前面说的那样,将需要改变的变量名暂时用一个定义好的标记名称来代替就是一种很好的方法。通常情况下,都应该避免使用硬编码方法。 
java小例子: int a=2,b=2;
硬编码:if(a==2) return false;
不是硬编码 if(a==b) return true;
一个简单的版本:
顾名思义, 就是把数值写成常数而不是变量
如求圆的面积 的问题 PI(3.14)
3.14*r*r (这个3.14就是hardcode)
PI*r*r (这里的PI用的是变量形式,就不是hardcode)
C++例子:
int user[120];
如果突然在程序中出现下面一段代码
for (int i=0; i<120; i++){

}
120是什么,为什么是120?这里的120就属于数字式“硬编码”,这不仅让程序很难读,而且不易维护。如果要修改120,就的修改程序中所有与此有关的120。应将数字式“硬编码”声明成一个宏,这样程序不仅易读,而且还可以一改全改。

#define MAX_USER_CNT 120
for (int i=0; i1]

其他问题

1. If…else…语句块不要太长。较长代码块可以拆成独立方法 (位置:FangController.getRoomDetail())
3. 抽取多重嵌套代码try…catch,定义单独方法
4. 在catch块中的log应该把堆栈信息打印出来:logger.info(this.getClass().getName() + eee.getMessage()); -> logger.info(this.getClass().getName() + eee.getMessage(), eee);
5. if (!token.equals(TOKEN))改写为if (!TOKEN.equals(token))
6. 在catch块中如不需任何处理,则直接在方法签名上通过“throws ***Exception“抛出异常,方法体中省略try…catch代码块 (位置:Api3_RoomDetailPriceSamples .fromAPI())
7. 如对业务执行逻辑没有起到提示作用,代码中去掉冗余的日志打印(logger.debug, logger.info)

Java Enum

Enum的适用场景

有限个个体, 每个个体包括了确定的属性
例子: Color.RED其实包含了(int R=255, int G=0, int B=0)

Enum和switch结构的联系

Enum可以直接用在switch语句

Color color=Color.RED;  
Color color=Color.BLUE;
switch(color){  
        case RED: System.out.println("it's red");break;  
        case BLUE: System.out.println("it's blue");break;  
        case BLACK: System.out.println("it's blue");break;  
}  

Enum和switch结构的区别

Enum本质上是一个有限的已知的集合, 集合元素之间可以区分
switch结构本质上是Key-value, 其中, Key未知, 但是给出一个Key, 对应的Value是已知的.

1 Java基本类型和四则运算

1.1 负数的余数,如何优雅地避免数组下标越界

-1%3=?
有两种答案:-1和2
java中用的是第一种,为了避免出现-1,抛出ArrayIndexOut的Error,所以获取数组上一个元素应该这么写,
elementBefore(int x)
{
return array[ (array.length + x - 1) % array.length ];
}
避免了使用if语句判读是否越界,优雅。

1.3 强制转换和加减乘除的优先级

float a=(float) 7/4; //1.75
float a=(float) (7/4); //1.0

1.2 你确定你的if判断式里是’==’而不是=?

2 Java最多能开多少线程?

p1
Thread数量:
OS 32bit, Memory 2G, JDK 1.7
令堆内存大小在运行期间保持恒定:
-Xms=-Xmx=512MB

名称 32bitOS 64bitOS
-Xss线程栈 最小64KB 最小128KB
Thread数量 1737 31842

其他影响因素:
proc/sys/vm/max_map_count
proc/sys/kernal/thread-max
proc/sys/kernal/pid-max


你必须了解的5条关于成员内部类的事

  1. 静态内部类是用static修饰的一种特殊的成员内部类, 具有额外的几条性质:


String StringBuffer StringBuild都声明为final, 因此你无法创建一个类extends这些类.


mysql语法

  1. TRUNCATE TABLE tbDELETE FROM tb效率更高, 因为后者需要逐条删除. 不过后者比较灵活, 可以附上where子句. 此外, 前者属于DDL语言, 不能rollback.
  2. INSERT INTO tName VALUES ();
  3. where ID = 123 or 124; – 错误, 但仍执行, 且where子句无效
    where ID = 123 or ID = 124;

Eclipse调试

Eclipse调试快捷键

F5 进入当前行调用的函数内部
F6 下一行
F7 直接跳出当前方法
F8 继续运行, 直至下一个断点

多线程调试

某线程卡在断点不影响其他线程继续运行
Logger %t 输出线程名
原生的junit4 不能测多线程, 因为System.exit()杀死所有进程. 可以写main方法测. 也可以用第三方包.

服务器后端调试

1 显示Server栏目, 配置tomcat

打开Windows -> Show Views -> Servers栏目
默认已经下载了tomcat7
new server: 选择tomcat7文件夹

2 部署项目

右键Servers栏目下的tomcat服务器, 选择右键菜单的”Add and Remove”, 添加项目如下图

Java技术杂记_第1张图片

点击Servers栏目的debug按钮, 如下图

这里写图片描述

在src的Controller类添加断点
通过浏览器或测试类发送http请求, 会被断点捕获. 接下去就和普通的Java程序调试一样了.

spring.HibernateTemplate

可热插拔的软件架构实践_基于Spring框架的DI

Task定时运行
DI赋予了类A不显式调用类B的能力, AB之间弱耦合.
用数据库的一张表保存任务执行进度, 必须清楚地说明每个字段的含义.
把POJO的值保存为json字符串, 存入数据库
用不用Spring DI 必须在概设前决定, 对类依赖影响大


用Java内存模型管理博客


UUID文件名


Java文件,输入输出

3.1 (zz)文件编码,java读写文件时的编码

原文
http://blog.sina.com.cn/s/blog_43eb83b90102dvj6.html

Java代码

File f = new File(“E:\eclipse\workspace\box\Data\2003-3-7-100.inc”);
InputStreamReader read = new InputStreamReader (new FileInputStream(f),”UTF-8”);
BufferedReader reader=new BufferedReader(read);
String line;
while ((line = reader.readLine()) != null)
{ System.out.println(line); }
File f = new File(“E:\eclipse\workspace\box\Data\2003-3-7-100.inc”);
InputStreamReader read = new InputStreamReader (new FileInputStream(f),”UTF-8”);
BufferedReader reader=new BufferedReader(read);String line; while ((line = reader.readLine()) != null)
{System.out.println(line);
}
通过打开文件是指定文件编码的方法把这个问题轻松的解决了。
最后总结一下:java要读取数据流的时候一定要指定数据流的编码方式(至少读取
String流的时候要这么作。

2.写文件
File file = new File(“c:\a.test”);
Writer writer = new OutputStreamWriter(new FileOutputStream(file), “UTF-8”);
writer.write(“中文测试”);
writer.close();

Java读取网页

用自带的URLConnection获得html页面,再配合jericho等html解析工具包提供的方法足矣.
POST请求的Head参数用properties方式保存.
Osgi包?

一串唯一字符串Boundary分割Head和
POST Form, 最后以Boundary+”–”表示请求结束.

java

找不到网页时FileNotFoundException


JQuery语法

$.fn.extend()拓展方法

$.fn.extend({
    searchBtn: function(){
        alter($(this).val());
    }
})  
// call
$("#input".searchBtn();

PostgreSQL 9.4.5特性
免费开源(任何意义上)
NoSQL support(支持json)
全外链接
Mysql2013年被Oracle收购, 商用受限
sudo apt-get install prostgresql-client prostgresql


java三目必须在等式右边, 这也限制了它的用途.


最简单的多线程架构_Producer-Consumer + BlockingQueue

考虑的要点:
Producer-Consumer 各自的粒度: 按关键词, 页, 类生产/消费
只有I/O可以靠多线程提高效率.
Queue和Pro-Con的关系:
1. 不推荐. 告诉Pro-Con有Queue
2. 推荐. Pro-Con有类变量Queue
__
python类变量和”私有”变量
类变量:

class A:
    a1=0 //可省略
    def __init__(self, a2):
        delf.a2 = a2
    def set(self, a3):

“私有”变量

事实上, 仍然你可以通过类名."私有"变量名的方式访问到. python里没什么是私有的.


英语单词

deflate 缩小
any 后名词: 否定/疑问句any+s, 表任何 不加s.


java.util.concurrent

concurrent包的精髓就是用底层是乐观锁的Lock, 替代了底层是悲观锁的synchronized. 只对写加锁, 大大提高了效率.

ConcurrentHashMap LockStripping 原理:
BlockingQueue:
put()/take() - await()/signal()+Condition类
add()/remove()/element() - 基于offer()/poll()/peek() - ReentrantLock(可重入锁)类似递归. 前者报异常, 后者无异常.

volatile
线程为了提高效率,将某成员变量(如A)拷贝了一份(如B),线程中对A的访问其实访问的是B。只在某些动作时才进行A和B的同步。因此存在A和B不一致的情况。volatile就是用来避免这种情况的。volatile告诉jvm, 它所修饰的变量不保留拷贝,直接访问主内存中的(也就是上面说的A)


log4j2入门 配置 HelloWorld

简书

java 1.5 不定长参数 1.7 switch(String) // 调用equals?

java没有unsigned int<2开头的十位数 YYYYMMDD=8位 int已够用

java synchronized多线程的本质

任何时刻, 对象的控制权(monitor)可能被一个线程拥有, 且它是wait/notify/notifyall的前提.
JVM不保证线程的时序
IllegalMonitorStateException

夺权

  1. 执行对象的synchronized实例方法
  2. 执行类的 static synchronized方法
  3. 执行加锁的同步块(不能在块中修改synchronized(Object o)的实例o)
synchronized(flag) {
    flag="haha"; // lose monitor
    flag.notify(); // Exception
}

解决办法: 把flag作为数组/JavaBean的元素


太平人寿
机器学习工程师


讲礼貌
您, 夏总

Wizard项目管理


java.io

InputStreamRead(new FileInputStream(f, boolean isAppend),”utf-8”);
InputStreamReader
BufferedReader
FileWriter
BufferedWriter
Java读取Windows的记事本的txt文件第一行需要处理一个”“空字符

Reader和InputStream的区别

例子: FileReader按字符(一个中文是一个字符, 两个字节)读文件, FileInputStream按字节读文件. FileReader还能指定解码方式为utf-8, gb2312等, 处理中文文件很方便.

Buffered(Reader|Writer|InputStream|OutputStream)

BufferedReader提供readline方法, 最好用.

BufferedReader br = new BufferedReader(new InputStreamReader(resStream, charset));
                  StringBuffer resBuffer = new StringBuffer();
                  String resTemp = "";
                  while ((resTemp = br.readLine()) != null) {
                    resBuffer.append(resTemp);
                  }

BufferedInputStream只提供了read()逐个字节读取缓存中的内容.
BufferedInputStream依附于其它InputStream, 不能独立存在.
BufferedInputStream重写了InputStream的read()方法, 加入缓存机制提高了效率.

问: 为什么缓存提高效率呢?

答: 读内存数据比读硬盘数据快(即使硬盘是SSD也只有内存速度的一成). 打个比方,您和朋友去登山,你朋友走一会儿就要休息,而您根本不需要休息,所以每当他休息的时候,您得等着他,您那时候什么也干不了,这就叫堵塞. 堵塞就是说您有能力干某事,但是迫于某种原因您什么也干不了,只能干等。所以您朋友休息的次数越少,你们两个到达山顶所花费的时间就越少。

同样的, CPU访问硬盘的次数越少,程序就越快。BufferedInputStream在小型文件中的性能优势无法体现出来,假设您将以个2G大小的文件从D盘完全复制到E盘,性能之优势便展露无疑!

例子: FileInputStream对文件按字节输入, 每个字节都访问一次磁盘, 资源占用多, 效率低. 把FileInputStream的实例作为参数new BufferedInputStream(fileInputStream), 就是提供了一个默认8072字节的缓存区, 缓存满了或调用flush()方法才从缓存读入内存, 比原来节约了8071次写内存.

import java.io.*;
public class Test {
    public static void main(String[] args) throws Exception {
        File f = new File("d:\\大型数据库文件.mdf");   
        FileInputStream fis = new FileInputStream(f);
        FileOutputStream fos = new FileOutputStream("e:\\" + f.getName());  
        // 如果使用BufferedOutputStream来修饰则带来更好的性能现。
        // BufferedOutputStream bos = new BufferedOutputStream(fos);
        int length = 0;
        byte[] b = new byte[1024]; // BufferedOutputStream内置缓存,不用这样写
        while((length = fis.read(b)) != -1)
        {
            fos.write(b, 0, length);
        }
        fos.close();
        fis.close();
    }
}

Interface无修饰符 包访问权限

Serializeable Id用来保持和DB中的版本一致

It’s never legal to start a thread more than once

不考虑多线程安全, StringBuilder比StringBuffer快

10000条append()操作, 前者0ms, 后者16ms

方法中定义的变量线程安全,因为本质上是private的

跨域CORS

jsp: request.setHeader();
java的servlet(如Tomcat, WebLogic, WebSphere, Apache, JBoss)的Filter中: request.setHeader();

web后端使用java 6语法是最佳实践


Java文件可以没有public class?

即使没有public, 也能编译通过并运行

class A{
    public static void main(String[] args){
        System.out.println("s");    
    }
}

实际上,静态内部类和外部类是一个级别的

内部类的应用:java.util.collection中的节点, 如LinkedList中的Entry.
减少了文件数目, 提高了高内聚.

Java-collection

List,Map实用初始化方法

new xxxList{{add();add();}}; //限制是必须显示制定<>中类型, 不能使用jdk7的diamond表达式

实现Map接口的类不允许重复主键

IdentityHashMap来帮忙

为什么不用LinkedList>

然后看到这里http://stackoverflow.com/questions/3110547/java-how-to-create-new-entry-key-value

ArrayList> arrayList = new 
    ArrayList>();
arrayList.add(new AbstractMap.SimpleEntry(1, 9));

LinkedHashMap.entrySet().iterator()按插入顺序遍历

异常处理

 异常的栈信息输出到日志

try{
    //
} catch(Exception e){
    logger.info("",e);
}

 异常处理性能损失

TRY CATCH那点性能损失可以忽略不计。别担心性能问题,现在项目的性能瓶颈只会出现在数据库上.

异常最大的开销是创建异常时需要回溯栈信息,如果没有异常的时候几乎不会影响性能

转自http://www.blogjava.net/stone2083/archive/2010/07/09/325649.html

结论:
1. Exception的性能是差,原因在于ThrowablefillInStackTrace()方法
2. 可以通过改写业务异常基类的方法,提升性能
3. try…catch和if…else的性能开销在同一数量级
4. 至于是否使用异常进行业务逻辑的控制,主要看代码风格.(我个人挺喜欢业务异常的)

 异常处理的必要性

没有任何东西是100%可靠的
数据库, 网络通信, 甚至是一个小小的Null都会让整个程序崩溃
绝大多数时候, 健壮性>性能

 try-catch块后的代码在catch了Exception后依然被执行, 所以最佳实践是把整个方法代码放在try-catch块中.

推荐catch块中 throw Exception把问题暴露给调用方, 由调用方统一处理Exception并记录
catch中的return null需要额外的logger信息辅助记录Exception原因.
虽然System.exit()可以在catch中杀死程序, 但是在多线程程序中禁止使用, 因为exit命令会杀死jvm, 所有的线程都被杀死.

两种线程安全的HashMap:

  1. 不推荐 Collections.synchronizedMap() 悲观锁,独享对象
  2. 推荐 java.util.concurrent.ConcurrentHashMap 乐观锁.写时检查
    底层实现 JNI Java CAS LockSupport.park() unpark()

java7的多个异常必须相互之间没有继承关系

Java读取Excel, doc, pdf, 图片

excel/doc apache POI HSSF/XSSF
图像OCR tesseract 中文库39.5MB
PDF pdfbox

java传引用,数组,collection类, 普通对象

方法内不能=new修改传入参数的指向.
巧用这个性质简化List实现类的批量删除子List

parentList.sublist(0,parentList.size()-1+1).clean();
//parentList中也被删除了

删除满足条件的链表元素

for(int i=0;;i++){
    if(i>test.size()-1)
        break;
    if(/*judge*/){
        test.remove(i);
        i--;
    }
}

对ArrayList,每次都需要Arrays.copyOf(old, size), 效率低下

jericho用来解析html

getChildElements()
getFirstElementByClass()
getElementById()
getTextExtractor().toString()只获得标签内容

iteye Java社区的巅峰->SOF,OSC(站长红薯是Java程序员)

Redis 3.2 kv数据库

OSC莆田系插件,技术改变生活

Gone with the wind(Margaret Mitchell)飘,乱世佳人

Hadoop版本

1.x.x 支持hbase, hive
2.x.x 速度提升, HDFS NameNode, JobRacjer YARN

Apache oozie

Wordcount

Apache赞助商目录:

赞助金额/年 赞助厂商
$100,000 Google,MS,FB,yahoo
$40,000 IBM,hp,ARM
$20,000 redhat, aliyun, huawei
$ 5,000

by page存储过程 调用次数小,粒度大, by function 便于重用

RESTFUL设计url规范

Representational State Transfer
资源(内容)的位置由URI(Identifier)唯一确定
http无状态, 状态保存在服务端, 用户通过GET,POST,PUT,DELETE命令操作资源(内容)
不要把资源(内容)更新频率不同的api放在一起

KPI(Kill person Idea)

只适合缺乏自制,目标和公司目标不同的员工
A: 好代码
B: 差代码 - 加班 - 升职
点评: 要适应KPI, 适度犯错, 全力补救

xml1.1和1.0区别

如果不重用就不要写成方法

区块连

一切不logger的异常都是耍流氓

Exception还可能暴露敏感信息给客户端

Java自带的代码API文档生成器 - jdk/bin/javadoc.exe

Eclipse中生成API文档, 参考http://www.blogjava.net/soddabao/archive/2007/04/09/109434.html

含中文注释的”编码gbk的不可映射字符”解决办法

转自http://blog.sina.com.cn/s/blog_899678b90101dnug.html

在Eclipse Export –> Java –> Javadoc 的向导中, 一直点Next, 不要点Finish. 直到向导的最后一页.
如果注释中有中文,那么必须在VM options中输入-encoding UTF-8 -charset UTF-8,
不然出现”编码gbk的不可映射字符”

你可能感兴趣的:(java)