《Java项目开发实战入门》以一起来画画、通讯录系统、明日彩票预测系统、小小五子棋、企业进销存管理系统、企业QQ(局域网版)、九宫格记忆网和铭成在线考试系统8个精选项目为案例,从趣味性和实际应用角度出发,采用了当前主流技术,读者可以从这些项目中体验到编程的乐趣并获得实战经验。《Java项目开发实战入门》应用的主要技术及知识点有:Java AWT、Java Swing、MySQL数据库、Hibernate、BeautyEye外观样式、多线程、Socket编程、人机对战实现、Derby、JSP、JavaScript、CSS、Servlet、HTML5等
——优势——
√ 零基础实战入门——快速扫盲视频,预备知识入门学习;
√ 项目精彩,讲解到位——8个流行项目,6小时教学视频,代码注释详尽;
√ 书网结合——在线课程,PC端、移动端免费同步学习;
√ 4色真彩印刷——还原编程真实开发环境。
——随书附赠——
√ 《小白手册》——环境搭建、程序调试、排错秘籍,帮助用户轻松搭建开发环境,快速解决开发问题;
√ 光盘——24小时视频讲解、项目江姐视频、项目源码、资源文件、代码查错器、代码片段,方便读者学习。
√ 二维码——书中设置多种功能二维码,视频二维码、代码解释二维码、会员二维码等;手机看视频,手机看文档,多种资源手机一扫尽在掌握。
√ 技术支持——QQ、微信、论坛等均可获得图书内容相关的技术支持,可以获得全方位的学习资源和技术支持。
√ 光盘附赠开发资源库——732个实例与源码详细分析、15个经典模块开发过程完整展现、110套界面资源方案库
——读者对象——
√ 零基础编程的自学者
√ 编程爱好者
√ 大中专院校的老师和学生
√ 培训机构的老师和学生
√ 参加毕业设计的学生
√ 初级和中级程序开发人员
《Java项目开发实战入门》是一本让初学者通过项目实战开发学编程的超值图书。
《阿里巴巴 Java开发手册》读后感小结
只有光头才能变强
前一阵子一直在学Redis,结果在黄金段位被虐了,暂时升不了段位了,每天都拿不到首胜(好烦)。
趁着学校校运会,合理地给自己放了一个小长假,然后就回家了。回到家才发现当时618买了一堆书,这堆书还有没撕包装的呢…于是我翻出了最薄的一本《阿里巴巴 Java开发手册》
这本书一共就90多页,一天就可以通读完了,看完之后我又来水博文了。
PDF官方地址:https://github.com/alibaba/p3c
1.POJO是DO/DTO/BO/VO的统称,禁止命名为xxxPOJO
2.获取多个对象的方法中list作为前缀
3.获取统计值的方法用count作为前缀
4.POJO类中的布尔类型(Boolean)的变量都不要加is前缀,否则部分框架解析会引起序列化错误
5.如果是形容能力的接口名称,取对应的形容词为接口名(通常是-able的形式)
6.不允许任何魔法值(未经预先定义的常量)直接出现在代码中
7.Object的euqals方法容易抛出空指针异常,应使用常量或者有值的对象来调用equals。推荐使用java.util.Object#equals工具类
8.所有POJO类的属性全部使用包装数据类型,RPC的返回值和参数必须使用包装数据类型,所有的局部变量都使用基本数据类型。定义VO/DTO/DO等POJO类时,不要设定任何属性的默认值
9.构造方法禁止加入任何的业务逻辑,如果初始化逻辑可以放在init方法中。set/get方法也不要增加业务逻辑。 •如果set/get方法放入业务逻辑,有时候排查问题就变得很麻烦了
10.工具类Arrays.asList()把数组转成List时,不能使用其修改集合的相关方法。比如说add、clear、remove
11.在JDK7以及以上版本中,Comparator要满足三个条件,不然调用Arrays.sort()或者Collections.sort()会报异常。 •x,y 的比较结果和 y,x 的比较结果相反
12.使用entrySet遍历Map类集合K/V,而不是用keySet方式遍历 •keySet遍历了两次,一次是转成Iterator对象,一次是从hashMap中取出key所对应的value,如果JDK8可以使用Map.foreach方法
13.线程资源必须由线程池提供,不允许在应用中自行显示创建线程。线程池不允许用Executors创建,通过ThreadPoolExecutor的方式创建,这样的处理方式能够让编写代码的工程师更加明确线程池的运行规则,规避资源耗尽的风险。
14.SimpleDateFormat是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁,或者使用DateUtils工具类
15.避免Random实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一seed导致性能下降 •在JDK7之后,可以直接使用API ThreadLocalRandom,而在JDK7 之前,需要编码保证每个线程持有一个实例。
16.类、类属性、类方法的注释必须使用 Javadoc 规范,使用 /*内容/ 格式,不得使用 //xxx 方式
17.所有的抽象方法(包括接口中的方法)必须要用 Javadoc 注释,除了返回值、参数、异常说明外,还必须指出该方法做什么事情,实现什么功能。所有的类都必须添加创建者和创建日期。
18.对于暂时被注释掉,后续可能恢复使用的代码片断,在注释代码的上方,使用三个斜杠///来说明注释代码的理由
19.保证单元测试的独立性。为了保证单元测试稳定可靠且便于维护,单元测试之间不能互相调用,也不能依赖执行的先后顺序。
20.高并发服务器建议调小TCP协议的time_await超时时间,调大最大事件句柄数(fd),
1.1值得说明的点
例子:
Negative example:
//Magic values, except for predefined, are forbidden in coding.
if (key.equals {
//...
}
Positive example:
String KEY_PRE = ;
if (KEY_PRE.equals(key)) {
//...
}
ps:我猜是把先常量定义出来,后续引用/修改的时候就很方便了。
java.util.Object#equals
工具类java.util.Object#equals的源码(已经判断null的情况了)
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
因为返回的ArrayList是一个内部类,并没有实现集合的修改方法。后台的数据仍是数组,这里体现的是适配器模式。
Arrays.sort()或者Collections.sort()
会报异常。The implementor must ensure that sgn(compare(x, y)) == -sgn(compare(y, x)) for all x and y. (This implies that compare(x, y) must throw an exception if and only if compare(y, x) throws an exception.)
The implementor must also ensure that the relation is transitive: ((compare(x, y)>0) && (compare(y, z)>0)) implies compare(x, z)>0.
Finally, the implementor must ensure that compare(x, y)==0 implies that sgn(compare(x, z))==sgn(compare(y, z)) for all z.
1) x,y 的比较结果和 y,x 的比较结果相反。
2) 传递性:x>y,y>z,则 x>z。
3) 对称性:x=y,则 x,z 比较结果和 y,z 比较结果相同。
反例:下例中没有处理相等的情况,实际使用中可能会出现异常:
new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getId() > o2.getId() ? 1 : -1;
}
}
使用entrySet遍历Map类集合K/V,而不是用keySet方式遍历
首先我们来看一下使用keySet是如何遍历HashMap的:
new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getId() > o2.getId() ? 1 : -1;
}
}
再来看一下源码:
// 1. 得到keySet,如果不存在,则创建
public Set<K> keySet() {
Set<K> ks = keySet;
if (ks == null) {
ks = new KeySet();
keySet = ks;
}
return ks;
}
// 2.初始化ks (实际上就是Set集合[HashMap的内部类],在初始化时需要顺便初始化iterator)
ks = new AbstractSet<K>() {
public Iterator<K> iterator() {
return new Iterator<K>() {
private Iterator<Entry<K,V>> i = entrySet().iterator();
public boolean hasNext() {
return i.hasNext();
}
public K next() {
return i.next().getKey();
}
public void remove() {
i.remove();
}
};
}
};
再来看一下entrySet,可以直接拿到key和value,不用再使用get方法来得到value,所以比keySet更加推荐使用!
public static void main(String[] args) throws InterruptedException {
HashMap<String, String> hashMap = new HashMap<>();
hashMap.put
hashMap.put
hashMap.put
// 得到entrySet,遍历entrySet得到结果
Set<Map.Entry<String, String>> entrySet = hashMap.entrySet();
Iterator<Map.Entry<String, String>> iterator = entrySet.iterator();
while (iterator.hasNext()) {
Map.Entry<String, String> entry = iterator.next();
System.out.println("key = " + entry.getKey() + ", value = " + entry.getValue());
}
}
如果是JDK8的话,推荐直接使用Map.forEach()
就好了,我们也来看看用法:
public static void main(String[] args) throws InterruptedException {
HashMap<String, String> hashMap = new HashMap<>();
hashMap.put
hashMap.put
hashMap.put
// forEach用法
hashMap.forEach((key, value) -> System.out.println("key = " + key + ", value = " + value));
}
其实在源码里边我们可以发现,forEach实际上就是封装了entrySet,提供forEach给我们可以更加方便地遍历Map集合
// forEach源码
default void forEach(BiConsumer<? super K, ? super V> action) {
Objects.requireNonNull(action);
for (Map.Entry<K, V> entry : entrySet()) {
K k;
V v;
try {
k = entry.getKey();
v = entry.getValue();
} catch(IllegalStateException ise) {
// this usually means the entry is no longer in the map.
throw new ConcurrentModificationException(ise);
}
action.accept(k, v);
}
}
有以下的例子可以正确使用SimpleDateFormat:
// 1. 在方法内部使用,没有线程安全问题
private static final String FORMAT = "yyyy-MM-dd HH:mm:ss";
public String getFormat(Date date){
SimpleDateFormat dateFormat = new SimpleDateFormat(FORMAT);
return dateFormat.format(date);
}
// 2. 每次使用的时候加锁
private static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public void getFormat(){
synchronized (SIMPLE_DATE_FORMAT){
SIMPLE_DATE_FORMAT.format(new Date());
….;
}
// 3. 使用ThreadLocal,每个线程都有自己的SimpleDateFormat对象,互不干扰
private static final ThreadLocal<DateFormat> DATE_FORMATTER = new ThreadLocal<DateFormat>() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
}
};
// 4. 使用DateTimeFormatter(This class is immutable and thread-safe.)
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(timeFormatter.format(LocalDateTime.now()));
如果是JDK8应用,可以使用Instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替SimpleDateFormat。
1.表达是否概念的字段,必须使用isxxx的方式命名,数据类型是unsigned tinyint(1表示是,0表示否)
2.小数类型用decimal,禁止使用float和double。
3.varchar是可变字符串,不预选分配存储空间的话,长度不要超过5000个字符。如果超过则用text,独立一张表,用主键对应,避免影响到其他字段的索引效率。
4.表必备的三个字段:id(类型是unsigned bigint),gmt_create(创建时间),gme_modified(修改时间)
5.字段允许适当冗余,以提高查询性能,但必须考虑数据一致性。冗余的字段必须不是频繁修改的字段,不是varhar超长字段(更不能是text字段)。
6.单表行数超过500万行或者单表容量超过2GB才推荐进行分库分表(如果预计三年都达不到这个数据量,不要在创建表的时候就分库分表!)
7.超过三个表禁止使用join,需要join的字段,数据类型必须保持一致,当多表关联查询时,保证被关联的字段需要有索引!
8.在varchar字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,页面搜索严禁左模糊或者全模糊,如果需要则通过搜索引擎来解决。
9.利用延迟关联或者子查询优化超多也分场景。
10.如果有全球化需要,均以utf-8编码。如果需要存储表情,选择utf8mb4进行存储。
2.1值得说明的点
一、利用延迟关联或者子查询优化超多也分场景。
MySQL并不是跳过 offset行,而是取 offset+N行,然后返回放弃前offset行,返回N行,那当 offset特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行SQL改写。
例子:
// 优化前
SELECT id, cu_id, name, info, biz_type
, gmt_create, gmt_modified, start_time, end_time, market_type
, back_leaf_category, item_status, picuture_url
FROM relation
WHERE biz_type = '0'
AND end_time >= '2014-05-29'
ORDER BY id ASC
LIMIT 149420, 20;
// 优化后
SELECT a.*
FROM relation a, (
SELECT id
FROM relation
WHERE biz_type = '0'
AND end_time >= '2014-05-29'
ORDER BY id ASC
LIMIT 149420, 20
) b
WHERE a.id = b.id
解释:其实这里就是通过使用覆盖索引查询返回需要的主键,再根据主键关联原表获得需要的数据。这样就是充分利用了索引!
在看《手册》的时候还有一些知识点没看过、没实践过、涉及到的知识点比较多的,在这里先mark一下,后续再遇到或者有空的时候再回来补坑~
AtomicInteger count = new AtomicInteger(); count.addAndGet(1);
如果是 JDK8,推荐使用 LongAdder 对象,比 AtomicLong 性能更好(减少乐观锁的重试次数)。当然了,如果你有比较好的资料阅读,也可以在评论区告诉我。我也会mark住好好看看。
比如说:“3y,我发现Optional类有篇文章写得很不错,url是xxxx(书籍的名称是xxx)
由于现在没有一定的经验积累,所以以下的章节得回头看:
看我上面写的内容就知道,除了一些规范外,还有很多实用的小技巧,这些对我们开发是有帮助的。我这个阶段也有一些没怎么接触过的(“日志”,“设计”,“二方库”),这些都需要我在成长中不断的回看才行。
如果需要这本书籍的全部内容 可以私信联系我哦,记得一键三连,谢谢大家支持哦如需课件源码软件等资料添加小助手vx:xcw18874131605(备注:CSDN)
最新2021整理收集的一些高频面试题(都整理成文档),有很多干货,包含mysql,netty,spring,线程,spring cloud、jvm、源码、算法等详细讲解,也有详细的学习规划图,面试题整理等,需要获取这些内容的朋友请加Q君羊:547998459