javaSE

javaSE

泛型

Java 提高篇(六) — 泛型

回调

经典的使用回调的方式
class A实现接口InA ——背景1

class A中包含一个class B的引用b ——背景2

class B有一个参数为InA的方法test(InA a) ——背景3

A的对象a调用B的方法传入自己,test(a) ——这一步相当于you call me

然后b就可以在test方法中调用InA的方法 ——这一步相当于i call you back

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//链接:https://www.zhihu.com/question/19801131/answer/26586203
public interface DoHomeWork {
void doHomeWork(String question, String answer);
}
public class Student implements DoHomeWork{
@Override
public void doHomeWork(String question, String answer) {
System.out.println("作业本");
if(answer != null) {
System.out.println("作业:"+question+" 答案:"+ answer);
} else {
System.out.println("作业:"+question+" 答案:"+ "(空白)");
}
}
public void ask(final String homework, final RoomMate roomMate) {
new Thread(new Runnable() {
@Override
public void run() {
roomMate.getAnswer(homework, Student.this);//a 调用 b,并且把自己(接口)传过去。
}
}).start();
goHome();
}
public void goHome(){
System.out.println("我回家了……好室友,帮我写下作业。");
}
public static void main(String[] args) {
Student student = new Student();
String homework = "当x趋向于0,sin(x)/x =?";
student.ask(homework, new RoomMate());
}
}
public class RoomMate {
public void getAnswer(String homework, DoHomeWork someone) {
//以接口的形式接受a类
if ("1+1=?".equals(homework)) {
someone.doHomeWork(homework, "2");
} else if("当x趋向于0,sin(x)/x =?".equals(homework)) {
System.out.print("思考:");
for(int i=1; i<=3; i++) {
System.out.print(i+"秒 ");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println();
someone.doHomeWork(homework, "1"); //b再调用a
} else {
someone.doHomeWork(homework, "(空白)");
}
}
}

模拟客户端和服务器:深入浅出: Java回调机制(异步)

小王向小李问问题:一个经典例子让你彻彻底底理解java回调机制

拷贝

深拷贝(deep clone)与浅拷贝(shallow clone):
  浅拷贝(浅复制、浅克隆):被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象。

​ 深拷贝(深复制、深克隆):被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深拷贝把要复制的对象所引用的对象都复制了一遍。

final

final关键字可以被家到属性或者变量的声明中,final属性或者变量一旦赋值之后就不允许再发生变化。对于基本类型(primitive type),比如int、double、long、byte等,一旦被生命为final,我们就可以将其当作常量来看待,但是对于引用类型或者数组(数组在java中也是对象)来说,则不是。虽然一个引用类型被赋值之后无法发生变化,但是我们仍然可以修改被引用的那个对象或者数组中的元素。

NUll

空指针:一个对象还没有没有正常初始化,就先调用它的方法。比如 Object obj=null; obj.toString(); 这就会抛出空指针异常 。牢记:使用对象时要先判断是否为空在掉方法。

预防方案:

1.从已知的String对象中调用equals()和equalsIgnoreCase()方法,而非未知对象。

判断字符串时使能确定不为空的对象去调用equals,如:””.equals(str);

2.当valueOf()和toString()返回相同的结果时,宁愿使用前者。

因为调用null对象的toString()会抛出空指针异常,如果我们能够使用valueOf()获得相同的值,那宁愿使用valueOf(),传递一个null给valueOf()将会返回“null”,尤其是在那些包装类,像Integer、Float、Double和BigDecimal。

3.使用null安全的方法和库有很多开源库已经为您做了繁重的空指针检查工作。其中最常用的一个的是Apache commons 中的StringUtils。你可以使用StringUtils.isBlank(),isNumeric(),isWhiteSpace()以及其他的工具方法而不用担心空指针异常。

4.避免从方法中返回空指针,而是返回空collection或者空数组。

5.使用annotation@NotNull和@Nullable

6.避免你的代码中不必要的自动包装和自动解包。

以上参见避免Java应用中NullPointerException的技巧和最佳实践

String

replace与replaceALL的区别

replace : 替换所有匹配到的

replaceAll:正则替换,replaceFirst:替换第一个匹配到的

参见java字符串的替换replace、replaceAll、replaceFirst的区别详解

技巧

30个java编程技巧(最佳实践)

ka总结博客

javaSE

java并发包学习

java学习笔记