原文请参考:https://bbs.csdn.net/topics/392062347
jdk5新特性
1、自动装箱和拆箱
2、枚举
3、静态导入
4、可变参数
5、內省
是Java语言对Bean类属性、事件的一种缺省处理方法。例如类A中有属性name,那我们可以通过getName,setName来得到其值或者设置新的值。通过getName/setName来访问name属性,这就是默认的规则。Java中提供了一套API用来访问某个属性的getter,setter方法,通过这些API可以使你不需要了解这个规则,这些API存放于包java.beans中。
一般的做法是通过类Introspector来获取某个对象的BeanInfo信息,然后通过BeanInfo来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的getter/setter方法,然后我们就可以通过反射机制来调用这些方法。
6、泛型
7、For-Each循环
jdk6新特性
1、Desktop类和SystemTray类
AWT新增加了两个类:Desktop,SystemTray。
Desktop可以用来打开系统默认浏览器指定的URL,打开系统默认邮件客户端给指定的邮件账号发邮件,用默认应用程序打开或编辑文件(比如,用记事本打开txt文件),用系统默认的打印机打印文档
SystemTray可以用来在系统托盘区创建一个托盘程序
2、使用JAXB2来实现对象与XML之间的映射
也就是对象与XML之间的映射(OXM),也可以通过XMLBeans和Castor等来实现同样的功能。
3、StAX
StAX是The Streaming API for XML的缩写,一种利用拉模式解析(pull-parsing)XML文档的API.StAX通过提供一种基于事件迭代器(Iterator)的API让 程序员去控制xml文档解析过程,程序遍历这个事件迭代器去处理每一个解析事件,解析事件可以看做是程序拉出来的,也就是程序促使解析器产生一个解析事件 然后处理该事件,之后又促使解析器产生下一个解析事件,如此循环直到碰到文档结束符;
SAX也是基于事件处理xml文档,但却 是用推模式解析,解析器解析完整个xml文档后,才产生解析事件,然后推给程序去处理这些事件;DOM 采用的方式是将整个xml文档映射到一颗内存树,这样就可以很容易地得到父节点和子结点以及兄弟节点的数据,但如果文档很大,将会严重影响性能。
4、使用Compiler API
使用JDK6的Compiler API去动态的编译Java源文件,Compiler API结合反射功能就可以实现动态的产生Java代码并编译执行这些代码。
5、轻量级Http Server API
6、插入式注解处理API
7、用Console开发控制台程序
8、对脚本语言的支持如:ruby,groovy,javascript
9、Common Annotations(公共注解)
jdk7新特性
1、switch中可以使用字符串
2、泛型的自动判断
3、自定义自动关闭类(实现AutoCloseable接口)
4、新增一些取环境信息的工具方法(System中的方法)
5、Boolean类型反转,空指针安全,参数与位运算
6、两个char间的equals
7、安全的加减乘除
另外:
1、对Java集合(Collections)的增强支持
1 List<String> list=["item"]; //向List集合中添加元素 2 String item=list[0]; //从List集合中获取元素 3 Set<String> set={"item"}; //向Set集合对象中添加元素 4 Map<String,Integer> map={"key":1}; //向Map集合中添加对象 5 int value=map["key"]; //从Map集合中获取对象的键值
但是经过自己测试,按照上面的使用方法,并不能创建集合。
2、int支持二进制数据
3、在try catch异常捕捉中,一个catch可以写多个异常类型
1 Connection conn = null; 2 try { 3 Class.forName("com.mysql.jdbc.Driver"); 4 conn = DriverManager.getConnection("","",""); 5 } catch(ClassNotFoundException|SQLException ex) { 6 ex.printStackTrace(); 7 }
4、try catch中资源定义好之后try catch自动关闭
1 try (BufferedReader in = new BufferedReader(new FileReader("in.txt")); 2 BufferedWriter out = new BufferedWriter(new FileWriter("out.txt"))) { 3 int charRead; 4 while ((charRead = in.read()) != -1) { 5 System.out.printf("%c ", (char)charRead); 6 out.write(charRead); 7 } 8 } catch (IOException ex) { 9 ex.printStackTrace(); 10 }
jdk8新特性
1、接口的默认方法
Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用default关键字即可,这个特征又叫做扩展方法,示例如下:
1 public interface Formula { 2 double calculate(int a); 3 default double sqrt(int a) { 4 return Math.sqrt(a); 5 } 6 }
Formula接口在拥有calculate方法之外同时还定义了sqrt方法,实现了Formula接口的子类只需要实现一个calculate方法,默认方法sqrt将在子类上可以直接使用。
1 Formula formula = new Formula() { 2 @Override 3 public double calculate(int a) { 4 return sqrt(a * 100); 5 } 6 }; 7 System.out.println(formula.calculate(100)); // 100.0 8 System.out.println(formula.sqrt(16)); // 4.0
文中的formula被实现为一个匿名类的实例
2、Lambda表达式
1 List<String> names = Arrays.asList("tom","jace","mike"); 2 Collections.sort(names, new Comparator<String>() { 3 @Override 4 public int compare(String o1, String o2) { 5 return o2.compareTo(o1); 6 } 7 });
只需要给静态方法Collections.sort传入一个List对象以及一个比较器来指定顺序排列。通常做法都是创建一个匿名的比较器对象,然后将其传递给sort方法。
在Java 8中提供了更简洁的语法,lambda表达式:
1 Collections.sort(names, (String a, String b) -> { 2 return b.compareTo(a); 3 });
还可以更简洁:
Collections.sort(names, (String a, String b) -> b.compareTo(a));
去掉大括号以及return关键字
Collections.sort(names, (a,b) -> b.compareTo(a));
Java编译器可以自动推导出参数类型,所以可以不用再写一次类型。
3、函数式接口
Lambda表达式是如何在java的类型系统中表示的呢?
每一个lambda表达式都对应着一个类型,通常是接口类型。而“函数式接口”是指仅仅只包含一个抽象方法的接口,每一个该类型的lambda表达式都会被匹配到这个抽象方法。因为默认方法不算抽象方法,所以也可以给自己的函数式接口添加默认方法。
我们可以将lambda表达式当做一个抽象方法的接口类型,确保自己的接口一定达到这个要求,你只需要给你的接口添加 @FunctionalInterface注解,编译器如果发现标注了这个注解的接口有多于一个抽象方法的时候就会报错。也就是说 @FunctionalInterface注解标注的接口只能有一个抽象方法。
例如:
1 @FunctionalInterface 2 public interface Converter<F, T> { 3 T convert(F from); 4 } 5 Converter<String, Integer> converter = (from) -> Integer.valueOf(from); 6 Integer converted = converter.convert("123"); 7 System.out.println(converted);
以上代码不需要@FunctionalInterface注解也是正确的。
4、方法与构造函数引用
上面的代码也可以通过静态方法引用来表示:
1 Converter<String, Integer> converter = Integer::valueOf; 2 Integer converted = converter.convert("123"); 3 System.out.println(converted);
Java8允许使用 :: 关键字来传递方法或者构造函数引用,
上面的代码展示了如何引用一个静态方法,我们也可以引用一个对象的方法:
1 public class Person { 2 3 String firstName; 4 String lastName; 5 6 Person() { 7 } 8 9 public Person(String firstName, String lastName) { 10 this.firstName = firstName; 11 this.lastName = lastName; 12 } 13 14 }
指定一个用来创建Person对象的对象工厂接口:
1 public interface PersonFactory<P extends Person> { 2 P create(String fisrtName, String lastName); 3 }
创建Person对象
1 PersonFactory<Person> personFactory = Person::new; 2 Person person = personFactory.create("Peter","Parker”);
我们只需要使用Person::new 来获取Person类构造函数的引用,Java编译器就会自动根据PersonFactory.create方法的签名来选择合适的构造函数。
5、Lambda作用域
在lambda表达式中访问外层作用域和老版本的匿名对象中的方式很相似。你可以直接访问标记了final的外层局部变量,或者实例的字段以及静态变量。
6、访问局部变量
我们可以直接在lambda表达式中访问外层的局部变量
1 final int num = 1; 2 Converter<Integer, String> stringConverter = (from) -> String.valueOf(from + num); 3 stringConverter.convert(2);
但是和匿名对象不同的是,这里的变量num可以不用声明为final,该代码同样正确。
7、访问对象字段与静态变量
和本地不良不同的是,lambda内部对于实例的字段以及静态变量是即可读又可写。该行为和匿名对象是一致的:
1 static int outerStaticNum; 2 int outerNum; 3 public void testScopes() { 4 Converter stringConverter1 = (from) -> { 5 outerNum = 23; 6 return String.valueOf(from); 7 }; 8 Converter stringConverter2 = (from) -> { 9 outerStaticNum = 72; 10 return String.valueOf(from); 11 }; 12 }
8、访问接口的默认方法
9、Date API
10、Annotation注解