JAVA串烧(三)JDK版本新特性

 

前言

      我们都知道,Java是一门不断更新的语言!!如果我们不能够掌握其中的新特性(有些特性对于提高开发效率是真的赞),那么将止步于此!

特性介绍


JDK1.5

1)自动拆箱与装箱

我们知道,Java是一个面向对象的语言,但其中的八大基本数据类型就不是对象。为了解决这个问题,Java很早就给我们提供了相应的包装类:Boolean,Byte,Short,Integer,Long,Float,Double,Character。这八个代表其基本的数据类型boolean,byte,short,int,long,float,double,char

但是,在JDK1.5之前,一只存在着基本数据类型与包装类的类型转换问题,方法十分繁琐。JDK1.5引入了相应的方法和机制,在底层帮助我们进行类型转换。

//JDK1.5以前完成装箱
int a = 1;
Integer b = new Integer(a);
//JDK1.5以后完成装箱
int c = 1;
Integer d = c;//实质底层调用Integer.valueOf()方法
//JDK1.5以前完成拆箱
Integer e = new Integer(1);
int f = e.intValue();
//JDK1.5以后完成拆箱
Integer g = new Integer(1);
int h = g;//实质底层调用intValue()方法

2)枚举

我们知道,我们的项目中经常会需要一些常量,我们会把它定义为XXXConst.java,用来保存所有的常量值。有些情况是可以的。但是,一旦常量值过多,就会出现管理不当、添加重复常量、代码冗余等等问题。JDK1.5提出了枚举的概念,实质上就是将常量分类化,这样极大的提高开发效率(虽然如此,但是枚举高级特性不建议使用,将使程序复杂度大大提高!)

public class Const {

	//JDK1.5之前定义一组常量
	public static final String TIGER = "TIGER";
	public static final String CAT = "CAT";
	public static final String DOG = "DOG";
	public static final String RABBIT = "RABBIT";
	
	public static final Integer N = 0;
	public static final Integer Y = 1;
}

 常量无外乎都是String类型,个别的会有boolean、int等其他基本类型,所以JDK1.5枚举常量类定义如下:

package com.jwang.test;

//JDK1.5之后定义枚举类
public enum Animal {
	//其默认为String类型
	TIGER,CAT,DOG,RABBIT
}
package com.jwang.test;

public enum Num {
	//通过构造器创建整型常量,一般都为String常量
	N(1),Y(2);
	
	private int num;

	private Num(int num) {
		this.num = num;
	}

	@Override
	public String toString() {
		return String.valueOf(num);
	}
}

调用枚举常量的方法不再赘述。

3)静态导入

我们知道,java.lang.Math包中的方法和属性是用来做数学运算的,其中全部都是静态方法和属性。在JDK1.5之前,我们都是Math.XXX来进行调用,如果使用的方法多了,那么将是极大的烦人!

package com.jwang.test;
//静态导入
import static java.lang.Math.*;

public class Test{
	
	public static void main(String[] args) {
		//JDK1.5之前需要加上Math
		System.out.println(Math.max(1, 2));
		//JDK1.5以后无需麻烦,直接静态导入
		System.out.println(max(1, 2));
	}
}

4)可变参数

我们知道,有时候我们写出来的方法形参是不固定的,可能有一个,可能有多个。典型的例子就是计算若干个数的和。如果在JDK1.5之前,你可能想到重载啊,数组啊,递归啊等等等等,但是JDK1.5完美的解决了这个问题。

JDK1.5引入可变参数实例代码:

//JDK1.5之后完成若干数的和运算
public static int getSum2(int ... a){
	int sum = 0;
	for (int i = 0; i < a.length; i++) {
		sum += a[i];
	}
	return sum;
}

5)泛型

我们知道,在JDK1.5之前,定义集合类如List的定义是没有指定任何类型的,其默认为Object类型,如果我们用作其他类型的话,需要做许多强制转换的操作,显然这与我们关心的主要逻辑不符。JDK1.5提出泛型的概念解决了这一问题。简单的说,泛型就是为集合容器类加入了一个标签,其告诉编译器这个集合里装的是什么类型。

//JDK1.5之前List定义
List list1 = new ArrayList();
list1.add("1");
//需要强制转换
String a = (String) list1.get(0);
//JDK1.5以后List定义
List<String> list2 = new ArrayList<String>();
list2.add("1");
String b = list2.get(0);

6)foreach循环

我们知道,在JDK1.5以前,十分流行的循环方法就是最著名的for循环语句了。但是,有些时候我们是无需关注其下标值的,那么这个时候下标就显得十分多余,JDK1.5提出了新的循环方法改善这一问题。

String [] strs = {"a","b","c"};
//JDK1.5之前for循环
for (int i = 0; i < strs.length; i++) {
	System.out.println(strs[i]);
}
//JDK1.5以后for循环
for (String str : strs) {
	System.out.println(str);
}

以上为JDK1.5的新特性,特别的:我们不是非要用新特性,在某些必要的条件下,必须要用老的方式进行编码!


JDK1.6

说起JDK1.6,没什么跟我们相关的新特性的更新,大家自行百度读一下就好了,我不在赘述。


JDK1.7

1)二进制的书写

在JDK1.7以前,Java中只能表示诸如八进制、十进制、十六进制的数字,二进制迟迟无法展示。但是在JDK1.7,完美的解决了这一问题

//JDK1.7之前的表示法只有八进制、十进制、十六进制
System.out.println(011);//八进制:9   (0开头的)
System.out.println(11);//十进制:11
System.out.println(0x11C);//十六进制:284   (0x开头的)
//JDK1.7之后新增二进制表示法
System.out.println(0b101);//二进制:5  (0b开头的)

2)数字常量使用下划线

我们知道,JDK1.7之前定义一个大数字,需要写很多位数,阅读起来十分的不方便。JDK1.7帮我们解决了这个问题,引入了位数分隔符下划线“_”的概念,使得数字浅显易懂!

//JDK1.7之前定义整型变量
long a = 13213324123124144L;
//JDK1.7之后定义整型变量使用“_”分隔方便阅读
long b = 132_133_241_231_241_44L;

3)switch语句可以使用字符串作为变量

在JDK以前,我们一般不适用switch语句,因为它有一个局限性,那就是不能用字符串作为判断的标准!其只能使用byte、short、char、int或者枚举进行判断,十分的不友好!但是在JDK1.7圆满的解决了这个问题。

//JDK1.7使用字符串作为判断条件
String key = "a";
switch (key) {
case "a":
	System.out.println("a");
	break;
case "b":
	System.out.println("b");
	break;
default:
	System.out.println("b");
	break;
}

4)实例创建的类型推断

在JDK1.5以后,我们知道,集合类的定义使用了泛型极大的增加了程序的编写效率!但是,我们都是这样写的如:

List<String> list2 = new ArrayList<String>();

大家有没有觉得,后面的泛型String设置的有些多余,前面都已经指定了啊!JDK1.7完美解决了这个问题,提出了类型推断的概念

//JDK1.7之前定义集合类的方法
List<String> list1 = new ArrayList<String>();
Map<String, Object> map1 = new HashMap<String, Object>();

//JDK1.7之后定义集合类的方法,增加类型自动推断
List<String> list2 = new ArrayList<>();
Map<String, Object> map2 = new HashMap<>();

5)try-with-resources 资源的自动管理

在JDK1.7之前,我们使用IO流操作的时候,最烦的就是最后要关闭各种流的连接!!但是JDK1.7使用了try-with-resources自动管理定义的资源类,无需我们手动关闭!

//JDK1.7之前使用资源类
FileInputStream in = null;
try {
	in = new FileInputStream("F:\test.txt");
	//后续操作
} catch (FileNotFoundException e) {
	e.printStackTrace();
} finally {
	try {
		in.close();
	} catch (IOException e) {
		e.printStackTrace();
	}
}
//JDK1.7之后使用资源类
try (
	//资源定义,定义后无需考虑关闭
	FileInputStream in = new FileInputStream("F:\test.txt");
){
	//后续操作
} catch (IOException e) {
	e.printStackTrace();
} 

特别的:资源类必须实现了AutoCloseable或者Closeable接口才能使用该特性!

6)优化异常捕捉的代码

我们知道,在JDK1.7之前,如果一段代码的异常过多,那么我们try-catch语句块将会十分的复杂!JDK1.7完美的解决了这一问题!

//JDK1.7以前捕获多个异常
try {
	File file = new File("ss");
	file.createNewFile();
	Connection connection = DriverManager.getConnection("ss");
} catch (IOException e) {
	e.printStackTrace();
} catch (SQLException e) {
	e.printStackTrace();
}
//JDK1.7以后捕获多个异常
try {
	File file = new File("ss");
	file.createNewFile();
	Connection connection = DriverManager.getConnection("ss");
} catch (IOException | SQLException e) {
	e.printStackTrace();
}

以上就是JDK1.7的新特性!


JDK1.8

1)接口的默认方法

我们知道,在JDK1.8以前,我们定义的接口中有且只有抽象方法,不能添加其实现!JDK1.8为我们提供了相应的扩展功能,使得我们可以在接口中写入扩展方法!

//JDK1.8之前只允许定义抽象方法
public int add(int a,int b);
//JDK1.8允许定义扩展方法  使用default关键字
public default void play1() {
	System.out.println("JDK1.8新特性!");
}
//JDK1.8允许静态扩展方法  使用static关键字
public static void play2() {
	System.out.println("JDK1.8新特性!");
}

这样的话,实现该接口的子类可以直接使用该方法!

2)Lambda 表达式

我们知道,定义一个接口之后,如果想要引用,就必须实现该接口的抽象方法!当接口只有一个抽象方法时,使用匿名实现类显得十分复杂繁琐,程序可读性差!JDK1.8提出了Lambda表达式的概念,使得原本多余的代码更加简洁易懂!

比如:数字集合类实现倒排序

//JDK1.8之前实现集合倒排序
List<Integer> result = new ArrayList<>();
result.add(2);
result.add(3);
result.add(1);
Collections.sort(result, new Comparator<Integer>() {
	@Override
	public int compare(Integer o1, Integer o2) {
		return o2 - o1;
	}
});
for (Integer a : result) {
	System.out.println(a);
}
//JDK1.8之后实现数字集合倒排序
List<Integer> result = new ArrayList<>();
result.add(2);
result.add(3);
result.add(1);
Collections.sort(result, (o1,o2)-> o2 - o1);
for (Integer a : result) {
	System.out.println(a);
}

发现没,你甚至只需要这一行简要的代码,就实现了数字集合的倒排序!!是不是觉得异常方便!

特别的:Lambda表达式仅适用于仅仅只包含一个抽象方法的接口!

3)函数式接口

上面提到的,仅仅包含一个抽象方法的接口就是函数式接口,它其实是和Lambda表达式配套的!JDK1.8允许使用@FunctionalInterface 注解标注一个函数式接口,该接口只有一个抽象方法!

//JDK1.8允许使用该注解标注函数式接口
@FunctionalInterface
interface MyTest{
	public void play();
}

4)方法与构造函数引用

我们知道,通过Lambda表达式可以简化函数式接口的匿名实现类的编写,提高代码阅读效率!但是在某些情况下,比如实现代码已经有相关方法实现的时候,我们还可以做到更短!!

  • 类::静态方法名
package com.jwang.test;

public class Test {
	public static void main(String[] args) {
        //传统Lambda表达式写法
        MyTest test1 = s -> Integer.parseInt(s);
        //使用方法引用
        MyTest test2 = Integer::parseInt;
	}
}
interface MyTest{
	public Integer play(String s);
}
  • 对象::实例方法名
package com.jwang.test;

public class Test{
	public static void main(String[] args) {
		A a2 = new B()::getInt;
		System.out.println(a2.parseInt("2"));
	}
}

@FunctionalInterface
interface A {
	public Integer parseInt(String s);
}

class B {
	public Integer getInt(String a){
		return Integer.parseInt(a);
	}
}
  • 类::实例方法名

注意:若lambda参数列表中的第一个参数是实例方法的调用者,而第二个参数是实例方法的参数时可以使用!

package com.jwang.test;

public class Test{
	public static void main(String[] args) {
		C c = String::equals;
		System.out.println(c.isEquals("a", "a"));
	}
}

@FunctionalInterface
interface A {
	public Integer parseInt(String s);
}

@FunctionalInterface
interface B {
	public C getC();
}

@FunctionalInterface
interface C {
	public boolean isEquals(String a,String b);
}
  • 类::new

该表达式返回一个类的构造器的引用

package com.jwang.test;

public class Test{
	public static void main(String[] args) {
		B b = C::new;
		System.out.println(b.getC().getInt("2"));
	}
}

@FunctionalInterface
interface A {
	public Integer parseInt(String s);
}

@FunctionalInterface
interface B {
	public C getC();
}

class C {
	public Integer getInt(String a){
		return Integer.parseInt(a);
	}
}

5)新的时间类

除了之前的Date、Calendar以外,JDK1.8提供了新的实践类简化程序编写:LocalDate/LocalTime/LocalDateTime

该处大家参考下API自行先去理解,博主也正在消化中,惭愧之至!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值