安辰

stay hungry stay foolish

Java8前时代

在Java8版本以前,创建一个只读不可变的集合,先要初始化,然后塞数据,然后置为只读:

1
2
3
4
5
Set<String> set = new HashSet<>();
set.add("a");
set.add("b");
set.add("c");
set = Collections.unmodifiableSet(set);

上面的方式占用太多行,能不能用单行表达式呢?用如下方式:

1
2
3
4
Set<String> set = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("a", "b", "c")));
Set<String> set = Collections.unmodifiableSet(new HashSet<String>() {{
add("a"); add("b"); add("c");
}});

Java8

在Java8中可以用流的方法创建,具体可以看之前的一篇文章Java8新特性系列(Stream),实现方法如下:

1
Set<String> set = Collections.unmodifiableSet(Stream.of("a", "b", "c").collect(toSet()));

Java9前时代

在Java9之前,String的源码如下:

1
2
3
4
5
6
7
package java.lang;
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
...
}

可以看到,String的内部是一个char数组,每个字符占2个字节(16位)。

Java7前时代

在Java7之前每次声明泛型变量的时必须左右两边都同时声明泛型:

1
2
3
List<String> list = new ArrayList<String>();
Set<String> set = new HashSet<String>();
Map<String, List<String>> map = new HashMap<String, List<String>>();

这样看来右边的泛型声明就变得是多余的了?

Java7

在Java7中,对这一点进行了改进,就不必两边都要声明泛型,这种只适用<>标记的操作,称之为钻石操作符Diamond Operator

1
2
3
List<String> list = new ArrayList<>();
Set<String> set = new HashSet<>();
Map<String, List<String>> map = new HashMap<>();

对比之前的用法是不是很清晰很方便呢?

但是Java7中钻石操作符不允许在匿名类上使用:

1
2
3
4
5
6
List<String> list = new ArrayList<>();
List<String> list = new ArrayList<>(){};//报错
Set<String> set = new HashSet<>();
Set<String> set = new HashSet<>(){};//报错
Map<String, List<String>> map = new HashMap<>();
Map<String, List<String>> map = new HashMap<>(){};//报错

如果与匿名类共同使用,会报错:'<>' cannot be used with anonymous classes

Java7前时代的try

在Java7版本以前,try的使用方法如下(流等资源的关闭在finally中进行,否则会导致资源泄漏):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static void main(String[] args) {
InputStreamReader reader = null;
try {
reader = new InputStreamReader(System.in);
...
reader.read();
...
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

Java7

Java7中,可以实现资源的自动关闭,但前提是资源必须要在try的子语句中进行初始化,否则编译会报错:

1
2
3
4
5
6
7
8
9
public static void main(String[] args) {
try (InputStreamReader reader = new InputStreamReader(System.in)) {
...
reader.read();
...
} catch (IOException e) {
e.printStackTrace();
}
}

Java7中出了try作了改进,catch也同样作了改进:

  • Java7之前
1
2
3
4
5
6
7
8
9
try {
//逻辑代码
...
} catch (IOException ex) {
logger.log(ex);
} catch (SQLException ex) {
logger.log(ex);
}
...
  • Java7及Java7以上
1
2
3
4
5
6
7
try {
//逻辑代码
...
} catch (IOException | SQLException ex) {
logger.log(ex);
}
...

catch子语句中ex默认是final的,在catch语句块中不能改变ex,否则会编译报错。

Java8前时代的Interface

在Java8版本以前,Interface接口中所有的方法都是抽象方法常量

Java8

Java8接口相关的可以看之前的一篇文章Java8新特性系列(Interface)

静态成员

在Java8中Interface支持静态成员,成员默认是public final static的,可以在类外直接调用。

default函数

在Java8中,Interface中支持函数有实现,只要在函数前加上default关键字即可,如下:

static函数

在Java8中允许Interface定义static方法,这允许API设计者在接口中定义像getInstance一样的静态工具方法,这样就能够使得API简洁而精练。

@FunctionalInterface注解

  • 什么是函数式接口

函数式接口其实本质上还是一个接口,但是它是一种特殊的接口:SAM类型的接口(Single Abstract Method)。定义了这种类型的接口,使得以其为参数的方法,可以在调用时,使用一个Lambda表达式作为参数。@FunctionalInterface注解能帮我们检测Interface是否是函数式接口,但是这个注解是非必须的,不加也不会报错

  • 函数式接口的作用?

函数式接口,可以在调用时,使用一个lambda表达式作为参数。

Java8中的Interface扩展了Java8之前的接口,更像是一个抽象类。

0%