大部分的修改都是为方便程序员,简化书写,提高阅读性。
1.支持将整数类型用二进制来表示,用0b或0B开头。
byte b = 0b111;//7
short s= (short) 0b0111111111111111;//32767
int i=0B11111;
long l=0b000011110001;
2.你可能会有这样的烦恼,不能一下子看出一个长的整数的位数,或者像上面那个二进制表示,我们通常会希望四位一组,这样阅读性更好,这个问题也在7中解决了,你可以像如下表示
short s= (short) 0b0111_1111_1111_1111;//32767
long l = 1234_5678_9012_3456L;
float pi = 3.14_15F;
long hexWords = 0xCAFE_BABE;
int i2 = 5_______2___4;
但是要注意下划线只能放在数字与数字中间,当然可以多个下划线相连,但是不能放在整个数的开头和末尾,也不能放在其他符号与数字之间。
比如下面的都是错误的表示:
//float pi1 = 3_.1415F;
//float pi2 = 3._1415F;
//long l= 999_99_9999_L;
//int x1 = _52;
//int x3 = 52_;
//int x5 = 0_x52;
//int x6 = 0x_52;
//int x8 = 0x52_;
//int x11 = 052_;
3.switch语句支持String类型
我们都知道switch语句以前只支持byte,short,char,int ,不支持字符串感觉很不方便,但是自此我们自由了
4.泛型简化
泛型实例的创建可以通过类型推断来简化 可以去掉后面new部分的泛型类型,只用<>就可以了。
List<String> list = new ArrayList<>();
Map<String, List<String>> map = new HashMap<>();
5.异常处理多catch合并
如果有两个异常我们处理的方式相同,不需要再写两个catch子句,只需要一个像这样
public static void main(String[] args){
try {
test();
} catch (IOException | SQLException e) {
}
}
public static void test() throws IOException, SQLException {
}
这里需要注意这时候异常对象是e是fianl类型的,不能对其赋值。
6.try_with_resource语句
我们以前需要释放资源时候,总要在fianally句中写一大坨代码,很繁琐。像下面这样。
File file=new File("ha.txt");
FileReader fr=null;
try {
fr = new FileReader(file);
int read = fr.read();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fr!=null){
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
不过以后就好多了。
File file=new File("ha.txt");
try(FileReader fr=new FileReader(file);FileWriter fw=new FileWriter(file)) {
fr.read();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
只要把要释放的资源放入try后的小括号中,就可以了。但是有一个前提,就是该类必须实现java.lang.AutoCloseable接口;按照声明逆序关闭资源 ;关于实现该接口的类可自行查找7以上的文档。
1.接口
java8做出了一开始有些令人难以接受的改变,接口可以定义方法的实现。可以有静态方法,也可以由default方法。如下所示
public interface InterfaceA {
static void a(){
System.out.print("静态方法");
}
default void b(){
System.out.print("默认方法");
}
}
其中静态方法同过接口名.方法名调用,但是实现类是不能通过类名来访问到接口的静态方法;
defaut方法可以通过实现类的实例来访问,当然实现类也可以重写接口的default方法,重写时不能有default关键字,此时的效果是和继承中的多态是一样的。
在java8中接口与抽象类最突出的不同的点是成员和方法的可访问性:抽象类允许非抽象和非final的属性,允许方法是public,private或protected的。而接口的属性本质上就是public、static和final的,而且所有方法都是public的。
2.lambda表达式
lambda表达式一开始你可以认为它是对一种特殊接口匿名内部类的一种简化书写。
简单示例:
public class Fan {
public interface Content {
void produceContent();
}
public static void main(String[] args) {
excute(()->{
String s1="world";
System.out.println(s1);
});
}
public static void excute(Content c){
c.produceContent();
}
}
为了配合lambda,jdk8引入了一个新的定义叫做:函数式接口(Functional interfaces)
函数式接口:
(1)是一个接口
(2)只有一个待实现的方法
因为jdk8开始,接口可以有default方法,所以,函数式接口也是可以有default方法的,但是,只能有一个未实现的方法。
与此对应,新引入了一个注解: @FunctionalInterface
这个注解只是起文档的作用,说明这个接口是函数式接口,编译器并不会使用这个注解来决定一个接口是不是函数式接口。
不管加不加@FunctionalInterface这个注解,下面的接口都是函数式接口:
public interface Content {
void produceContent();
}
lambda语法:
(Type1 param1, Type2 param2, ..., TypeN paramN) -> {
statment1;
statment2;
...
}
(param1,param2, ..., paramN) -> {
statment1;
statment2;
...
}
param1 -> {
statment1;
statment2;
...
}
param1 -> statment
如下所示:
public class Fan {
public interface Content {
String produceContent();
}
public static void main(String[] args) {
String s="hello";
excute(()->s);
}
public static void excute(Content c){
System.out.println(c.produceContent());
}
}
这里表示方法produceContent()的实现只有一条return语句,其中return省略掉了,返回值就是s;
当然如果没有实现的方法没有返回值时,这里可以是一些其他语句,比如
public class Fan {
public interface Content {
void produceContent();
}
public static void main(String[] args) {
excute(()->System.out.println("hello"));
}
public static void excute(Content c){
c.produceContent();
}
}
lambda眼中的this
在lambda中,this不是指向lambda表达式产生的那个SAM对象,而是声明它的外部对象。
3.方法引用(Method reference)和构造器引用(construct reference)
方法引用
方法引用可以在某些条件成立的情况下,更加简化lambda表达式的声明。方法引用语法格式有以下三种:
objectName::instanceMethod
ClassName::staticMethod
ClassName::instanceMethod
前两种方式类似,等同于把lambda表达式的参数直接当成instanceMethod|staticMethod的参数来调用。比如System.out::println等同于x->System.out.println(x);Math::max等同于(x, y)->Math.max(x,y)。
第一种示例:
public class Fan {
public interface Content {
void produceContent();
}
public static void main(String[] args) {
excute(System.out::println);
}
public static void excute(Content c) {
System.out.println("start");
c.produceContent();
System.out.println("end");
}
}
输出结果为:
start
end
中间有一个空行
第二种示例:
public class Fan {
public interface Content {
int produceContent(int x,int y);
}
public static void main(String[] args) {
// excute(Math::max);
excute((x,y)->Math.max(x,y));
//这两种写法是一样的
}
public static void excute(Content c) {
int x=100,y=1000;
System.out.println(c.produceContent(x,y));
}
}
最后一种方式,等同于把lambda表达式的第一个参数当成instanceMethod的目标对象,其他剩余参数当成该方法的参数。比如String::toLowerCase等同于x->x.toLowerCase()
public class Fan {
public interface Content {
String produceContent(String x);
}
public static void main(String[] args) {
//excute(x->x.toLowerCase());
excute(String::toLowerCase);
}
public static void excute(Content c) {
String x="HELLO WORLD";
System.out.println(c.produceContent(x));
}
}
构造器引用
构造器引用语法如下:ClassName::new,把lambda表达式的参数当成ClassName构造器的参数 。例如Integer::new等同于x->new Integer(x)。