jdk8已经出来好长时间了,这里本身学习时简单总结的jdk5,jdk6和jdk7的新特性:
本文提纲:java
一.jdk5的新特性程序员
二.jdk6的新特性数据库
三.jdk7的新特性编程
首先简单介绍一下各类特性及其使用安全
1.泛型(Generic)
C++经过模板技术能够指定集合的元素类型,而Java在1.5以前一直没有相对应的功能。一个集合能够听任何类型的对象,服务器
相应地从集合里面拿对象的时候咱们也不得不对他们进行强制得类型转换。猛虎引入了泛型,它容许指定集网络
Collection<String> c = new ArrayList(); c.add(new Date()); 编译器会给出一个错误: add(java.lang.String) in java.util.Collection<java.lang.String> cannot be applied to (java.util.Date)
A、类型安全并发
抛弃List、Map,使用List<T>、Map<K,V>给它们添加元素或者使用Iterator<T>遍历时,编译期就能够给你检查出类型错误app
B、方法参数和返回值加上了Type框架
抛弃List、Map,使用List<T>、Map<K,V>
C、不须要类型转换
List<String> list=new ArrayList<String>();
String str=list.get(i);
D、类型通配符“?”
假设一个打印List<T>中元素的方法printList,咱们但愿任何类型T的List<T>均可以被打印:
代码:
public void printList(List<?> list,PrintStream out)throws IOException{ for(Iterator<?> i=list.iterator();i.hasNext();){ System.out.println(i.next.toString()); } }
若是通配符?让咱们的参数类型过于普遍,咱们能够把List<?>、Iterator<?> 修改成
List<? Extends Number>、Iterator<? Extends Number>限制一下它。
2.For-Each循环
For-Each循环得加入简化了集合的遍历。假设咱们要遍历一个集合对其中的元素进行一些处理。典型的代码为:
void processAll(Collection c){ for(Iterator i=c.iterator(); i.hasNext();){ MyClass myObject = (MyClass)i.next(); myObject.process(); } } #使用For-Each循环,咱们能够把代码改写成: void processAll(Collection<MyClass> c){ for (MyClass myObject :c) myObject.process(); }
这段代码要比上面清晰许多,而且避免了强制类型转换。
3.自动装包/拆包(Autoboxing/unboxing)
自动装包/拆包大大方便了基本类型数据和它们包装类地使用。
自动装包:基本类型自动转为包装类.(int >> Integer)
自动拆包:包装类自动转为基本类型.(Integer >> int)
在JDK1.5以前,咱们老是对集合不能存放基本类型而耿耿于怀,如今自动转换机制解决了咱们的问题。
4.枚举(Enums)
JDK1.5加入了一个全新类型的“类”-枚举类型。为此JDK1.5引入了一个新关键字enmu,咱们能够这样来定义一个枚举类型。
public enum Color{ Red, White, Blue } #而后能够这样来使用Color myColor = Color.Red. #枚举类型还提供了两个有用的静态方法values()和valueOf(). 咱们能够很方便地使用它们,例如 for (Color c : Color.values()) System.out.println(c);
5.可变参数(Varargs)
可变参数使程序员能够声明一个接受可变数目参数的方法。注意,可变参数必须是函数声明中的最后一个参数。
假设咱们要写一个简单的方法打印一些对象,
在JDK1.5以前,咱们能够用重载来实现,可是这样就须要写不少的重载函数,显得不是颇有效。
若是使用可变参数的话咱们只须要一个函数就好了.
public void write(Object... objs) { for (Object obj: objs) System.out.println(obj); }
在引入可变参数之后,Java的 反射包也更加方便使用了。对于c.getMethod
("test", new Object[0]).invoke(c.newInstance(), new Object[0])),
如今咱们能够这样写了c.getMethod("test").invoke(c.newInstance()),这样的代码比 原来清楚了不少。
6.静态导入(Static Imports)
要使用用静态成员(方法和变量)咱们必须给出提供这个方法的类。使用静态导入可使被导入类的全部静态变量和静态方法在当前类直接可见,
使用这些静态成员无需再给出他们的类名。
import static java.lang.Math.*; …….
r = sin(PI * 2); //无需再写r = Math.sin(Math.PI);
可是,过分使用这个特性也会必定程度上下降代码地可读性。
6.Annotations 它是java中的metadata
A.Tiger中预约义的三种标准annotation
(1).Override 方法重载
指出某个method覆盖了superclass 的method当你要覆盖的方法名拼写错时编译不经过
(2).Deprecated 方法过期
指出某个method或element类型的使用是被阻止的,子类将不能覆盖该方法
(3).SupressWarnings 编译器警告
关闭class、method、field、variable 初始化的编译期警告,好比:List没有使用 Generic,则@SuppressWarnings("unchecked")去掉编译期警告。
B.自定义annotation
public @interface Marked{}
C.meta-annotation
或者说annotation的annotation
四种标准的meta-annotation所有定义在java.lang.annotaion包中:
Target
指定所定义的annotation能够用在哪些程序单元上
若是Target没有指定,则表示该annotation可使用在任意程序单元上
代码
@Target({ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.METHOD, ElementType.PACKAGE, ElementType.PARAMETER, ElementType.TYPE}) public @interface TODO {}
Annotation的反射
咱们发现java.lang.Class有许多与Annotation的反射相关的方法,如getAnnotations、isAnnotationpresent
咱们能够利用Annotation反射来作许多事情,好比自定义Annotation来作Model对象验证
代码
@Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.FIELD, ElementType.METHOD }) public @interface RejectEmpty { /** hint title used in error message */ String value() default ""; } @Retention(RetentionPolicy.RUNTIME) @Target( { ElementType.FIELD, ElementType.METHOD }) public @interface AcceptInt { int min() default Integer.MIN_VALUE; int max() default Integer.MAX_VALUE; String hint() default ""; }
使用@RejectEmpty和@AcceptInt标注咱们的Model的field,而后利用反射来作Model验证
7.新的格式化方法(java.util.Formatter)
formatter.format("Remaining account balance: $%.2f", balance);
8.新的线程模型和并发库Thread Framework
HashMap的替代者ConcurrentHashMap和ArrayList的替代者CopyOnWriteArrayList
在大并发量读取时采用java.util.concurrent包里的一些类会让你们满意BlockingQueue、Callable、Executor、Semaphore...
1.引入了一个支持脚本引擎的新框架
2.UI的加强
3.对WebService支持的加强(JAX-WS2.0和JAXB2.0)
4.一系列新的安全相关的加强
5.JDBC4.0
6.Compiler API
7.通用的Annotations支持
1.二进制字面量
JDK7开始,终于能够用二进制来表示整数(byte,short,int和long)。使用二进制字面量的好处是,能够是
代码更容易被理解。语法很是简单,只要在二进制数值前面加0b或者0B
byte nByte = (byte)0b0001; short nShort = (short)0B0010; int nInt = 0b0011; long nLong = 0b0100L;
2.数字字面量能够出现下划线
对于一些比较大的数字,咱们定义起来老是不方面,常常缺乏或者增长位数。JDK7为咱们提供了一种解决
方案,下划线能够出如今数字字面量。
int a = 10_0000_0000; long b = 0xffff_ffff_ffff_ffffl; byte c = 0b0001_1000;
注意:你只能将下划线置于数字之间,如下使用方法是错误的,
(1).数字的开头或者结尾
(2).小数点的先后
(3).‘F’或者‘f’的后缀
(4).只能用数字的位置
int err1 = _11,err2=11_; float err3=3._4,err4=3_.4; long err5=0x888_f;
3.switch 语句能够用字符串了
private static void switchString(String str){ switch(str){ case "one": System.err.println("1"); break; case "two": System.out.println("2"); break; default : System.out.println("err"); } }
4.泛型实例的建立能够经过类型推断来简化
之后你建立一个泛型实例,不须要再详细说明类型,只需用<>,编译器会自动帮你匹配
#例如
Map<String, List<String>> myMap = new HashMap<String, List<String>>();
#能够简化为
Map<String, List<String>> myMap = new HashMap<>();
5.在可变参数方法中传递非具体化参数(Non-Reifiable Formal Parameters),改进编译警告和错误
有些参数类型,例如ArrayList<Number> 和List<String>,是非具体化的(non-reifiable).在编译阶段,
编译器会擦除该类型信息。
Heap pollution 指一个变量被指向另一个不是相同类型的变量。例如
List l = new ArrayList<Number>(); List<String> ls = l; // unchecked warning l.add(0, new Integer(42)); // another unchecked warning String s = ls.get(0); // ClassCastException is thrown
回到咱们的主题,在jdk7中,当你定义下面的函数时
public static <T> void addToList (List<T> listArg, T... elements) { for (T x : elements) { listArg.add(x); } }
你会获得一个warning
warning: [varargs] Possible heap pollution from parameterized vararg type
在jdk7以前,当你调用一个含有非具体化参数的可变参数方法,你必须自行保证不会发生“heap
pollution”。这有一个问题,若是调用者对方法不熟悉,他根本没法判断。JDK7对此作了改进,在该方法被定
义时久发出警告
1.加 annotation @SafeVarargs 2.加 annotation @SuppressWarnings({"unchecked", "varargs"}) 3.使用编译器参数 –Xlint:varargs;
6.try-with-resources 语句
jdk7提供了try-with-resources,能够自动关闭相关的资源(只要该资源实现了AutoCloseable接口,jdk7为绝
大部分资源对象都实现了这个接口)
static String readFirstLineFromFile(String path) throws IOException { try (BufferedReader br = new BufferedReader(new FileReader(path))) { return br.readLine(); } }
try 语句块中还能够同时处理多个资源,能够跟普通的try语句同样catch异常,有finally语句块
try ( java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName); java.io.BufferedWriter writer = java.nio.file.Files.newBufferedWriter(outputFilePath, charset) ) { }catch(…){ }finally{ }
7.Catch多个Exception,rethrow exception 改进了类型检测
不少时候,咱们捕获了多个异常,却作了相同的事情,好比记日志,包装成新的异常,而后rethrow。这
时,代码就不那么优雅了,例如
catch (IOException ex) { logger.log(ex); throw ex; catch (SQLException ex) { logger.log(ex); throw ex; }
Jdk7容许捕获多个异常
catch (IOException|SQLException ex) { logger.log(ex); throw ex; }
注意,catch后面的异常参数是final的,不能从新再复制
当你从新抛出多个异常时,再也不须要详细定义异常类型了,编译器已经知道你具体抛出的是哪一个异常了。你
只需在方法定义的时候声明须要抛出的异常便可
public void call() throws ReflectiveOperationException, IOException { try { callWithReflection(arg); } catch (final Exception e) { logger.trace("Exception in reflection", e); throw e; } }
8.JDBC4.1更新了两个新特性
1. Connection,ResultSet 和Statement 都实现了Closeable 接口,全部在try-with-resources 语句中调
用,就能够自动关闭相关资源了
try (Statement stmt = con.createStatement()){ … }
2. RowSet 1.1:引入RowSetFactory接口和RowSetProvider类,能够建立JDBC driver支持的各类row sets
RowSetFactory myRowSetFactory = null; JdbcRowSet jdbcRs = null; ResultSet rs = null; Statement stmt = null; try { myRowSetFactory = RowSetProvider.newFactory();//用缺省的RowSetFactory 实现 jdbcRs = myRowSetFactory.createJdbcRowSet(); //建立一个 JdbcRowSet 对象,配置数据库链接属性 jdbcRs.setUrl("jdbc:myDriver:myAttribute"); jdbcRs.setUsername(username); jdbcRs.setPassword(password); jdbcRs.setCommand("select ID from TEST");
jdbcRs.execute();
}
RowSetFactory 接口包括了建立不一样类型的RowSet的方法
createCachedRowSet
createFilteredRowSet
createJdbcRowSet
createJoinRowSet
createWebRowSet
9.更新了NIO2.0文件系统
java.io.File 不够完美吧。Jdk7提供了一套新的文件系统,会让你满意的。
先来聊聊java.io.File的七宗罪吧:)
1.不少方法失败时候都没有抛出异常,很难查找缘由
2.方法 rename 在不一样平台中运行有问题
3.不能真正支持 symbolic links
4.不能读取文件的更详细属性,好比权限,全部者……
5.访问 文件的 metadata 效率低下
6.不少方法性能不行。例如处理比较大的目录
7.没法递归查找文件树,以及存在循环的symbolic links可能形成问题
主要包括:
FileSystem 提供了许多方法来得到当前文件系统的相关信息。
Path 处理路径(文件和目录),包括
建立path,Paths.get(String s)
得到path的详细信息 getName(),getXX()…
删除path的冗余信息 toRealPath
转换path toAbsolutePath()
合并两个path resolve()
在两个path之间建立相对路径 relativeze()
比较路径 equal() startsWith(),endWith()
Files 支持各类文件操做,包括
移动文件,
复制文件,
删除文件,
更详细的文件属性,包括文件权限,建立者,修改时间……
Walking the File Tree(递归遍历文件树)
Watch a Directory for Change (监听文件更改)
9.异步IO AIO
概述JDK7引入了Asynchronous I/O。I/O编程中,经常使用到两种模式:Reactor 和Proactor。Reactor就是Java的NIO。当有事件触发时,咱们获得通知,进行相应的处理。Proactor就是咱们今天要讲的AIO了。AIO进行I/O操做,都是异步处理,当事件完成时,咱们会获得通知。JDK7的AIO包括网络和文件操做。二者大同小异,本文经过一个完整的客户端/服务器Sample来详细说明aio的网络操做。AIO提供了两种异步操做的监听机制。第一种经过返回一个Future对象来事件,调用其get()会等到操做完成。第二种相似于回调函数。在进行异步操做时,传递一个CompletionHandler,当异步操做结束时,会调用CompletionHandler.complete 接口