java 历年版本特征(简化)
无论是学习任何新知识,我都是从历史的角度着手,这让我对这些新知识是如何孕育出来的,有一个很好的理解
只从java 5-8,之后我也开始转nodejs了,感谢java伴随的这几年
Java5的新特性
特性列表
-
泛型
-
枚举
-
装箱拆箱
-
变长参数
-
注解
-
foreach循环
-
静态导入
-
格式化
-
线程框架/数据结构
-
Arrays工具类/StringBuilder/instrument
1、泛型
所谓类型擦除指的就是Java源码中的范型信息只允许停留在编译前期,而编译后的字节码文件中将不再保留任何的范型信息。也就是说,范型信息在编译时将会被全部删除,其中范型类型的类型参数则会被替换为Object类型,并在实际使用时强制转换为指定的目标数据类型。而C++中的模板则会在编译时将模板类型中的类型参数根据所传递的指定数据类型生成相对应的目标代码。
Map<Integer, Integer> squares = new HashMap<Integer, Integer>();
-
通配符类型:避免unchecked警告,问号表示任何类型都可以接受
-
限制类型
2、枚举
-
EnumMap
-
switch枚举
3、Autoboxing与Unboxing
将primitive类型转换成对应的wrapper类型:Boolean、Byte、Short、Character、Integer、Long、Float、Double
4、vararg(动态参数)
5、annotation
-
Inherited表示该注解是否对类的子类继承的方法等起作用
@Documented @Inherited @Retention(RetentionPolicy.RUNTIME) public @interface InProgress { }
-
指定Target
@Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.ANNOTATION_TYPE}) public @interface TODO { String value(); }
-
Target类型
public enum ElementType { /** Class, interface (including annotation type), or enum declaration */ TYPE, /** Field declaration (includes enum constants) */ FIELD, /** Method declaration */ METHOD, /** Parameter declaration */ PARAMETER, /** Constructor declaration */ CONSTRUCTOR, /** Local variable declaration */ LOCAL_VARIABLE, /** Annotation type declaration */ ANNOTATION_TYPE, /** Package declaration */ PACKAGE }
-
rentation表示annotation是否保留在编译过的class文件中还是在运行时可读。
public enum RetentionPolicy { /** * Annotations are to be discarded by the compiler. */ SOURCE, /** * Annotations are to be recorded in the class file by the compiler * but need not be retained by the VM at run time. This is the default * behavior. */ CLASS, /** * Annotations are to be recorded in the class file by the compiler and * retained by the VM at run time, so they may be read reflectively. * * @see java.lang.reflect.AnnotatedElement */ RUNTIME }
6、for/in
for/in循环办不到的事情:
(1)遍历同时获取index
(2)集合逗号拼接时去掉最后一个
(3)遍历的同时删除元素
7、静态import
import static java.lang.System.err; import static java.lang.System.out; import java.io.IOException; import java.io.PrintStream; public class StaticImporter { public static void writeError(PrintStream err, String msg) throws IOException { // Note that err in the parameter list overshadows the imported err err.println(msg); } public static void main(String[] args) { if (args.length < 2) { err.println("Incorrect usage: java com.oreilly.tiger.ch08 [arg1] [arg2]"); return; } out.println("Good morning, " + args[0]); out.println("Have a " + args[1] + " day!"); try { writeError(System.out, "Error occurred."); } catch (IOException e) { e.printStackTrace(); } } }
8、格式化
/** * java.text.DateFormat * java.text.SimpleDateFormat * java.text.MessageFormat * java.text.NumberFormat * java.text.ChoiceFormat * java.text.DecimalFormat */
9、threading
-
uncaught exception
-
blocking queue(阻塞队列)
-
线程池
著名的JUC类库。
-
每次提交任务时,如果线程数还没达到coreSize就创建新线程并绑定该任务。 所以第coreSize次提交任务后线程总数必达到coreSize,不会重用之前的空闲线程。
-
线程数达到coreSize后,新增的任务就放到工作队列里,而线程池里的线程则努力的使用take()从工作队列里拉活来干。
-
如果队列是个有界队列,又如果线程池里的线程不能及时将任务取走,工作队列可能会满掉,插入任务就会失败,此时线程池就会紧急的再创建新的临时线程来补救。
-
临时线程使用poll(keepAliveTime,timeUnit)来从工作队列拉活,如果时候到了仍然两手空空没拉到活,表明它太闲了,就会被解雇掉。
-
如果core线程数+临时线程数 >maxSize,则不能再创建新的临时线程了,转头执行RejectExecutionHanlder。默认的AbortPolicy抛RejectedExecutionException异常,其他选择包括静默放弃当前任务(Discard),放弃工作队列里最老的任务(DisacardOldest),或由主线程来直接执行(CallerRuns),或你自己发挥想象力写的一个。
10、其他
-
Arrays
Arrays.sort(myArray); Arrays.toString(myArray) Arrays.binarySearch(myArray, 98) Arrays.deepToString(ticTacToe) Arrays.deepEquals(ticTacToe, ticTacToe3)
-
Queue
避开集合的add/remove操作,使用offer、poll操作(不抛异常)
Queue q = new LinkedList(); 采用它来实现queue
-
Override返回类型
支持协变返回,意味着当一个重写方法时,重写方法的返回类型被允许为重写方法的返回类型的子类型。
-
单线程StringBuilder
线程不安全,在单线程下替换string buffer提高性能
-
java.lang.instrument
参考
Java6的新特性
特性列表
- JSR223脚本引擎
- JSR199--Java Compiler API
- JSR269--Pluggable Annotation Processing API
- 支持JDBC4.0规范
- JAX-WS 2.0规范
1、JSR223脚本引擎
Scripting for the Java Platform
- 基本使用
public class BasicScripting { public void greet() throws ScriptException { ScriptEngineManager manager = new ScriptEngineManager(); //支持通过名称、文件扩展名、MIMEtype查找 ScriptEngine engine = manager.getEngineByName("JavaScript"); // engine = manager.getEngineByExtension("js"); // engine = manager.getEngineByMimeType("text/javascript"); if (engine == null) { throw new RuntimeException("找不到JavaScript语言执行引擎。"); } engine.eval("println('Hello!');"); } public static void main(String[] args) { try { new BasicScripting().greet(); } catch (ScriptException ex) { Logger.getLogger(BasicScripting.class.getName()).log(Level.SEVERE, null, ex); } } }
- 绑定上下文
public class ScriptContextBindings extends JsScriptRunner { public void scriptContextBindings() throws ScriptException { ScriptEngine engine = getJavaScriptEngine(); ScriptContext context = engine.getContext(); Bindings bindings1 = engine.createBindings(); bindings1.put("name", "Alex"); context.setBindings(bindings1, ScriptContext.GLOBAL_SCOPE); Bindings bindings2 = engine.createBindings(); bindings2.put("name", "Bob"); context.setBindings(bindings2, ScriptContext.ENGINE_SCOPE); engine.eval("println(name);"); } public void useScriptContextValues() throws ScriptException { ScriptEngine engine = getJavaScriptEngine(); ScriptContext context = engine.getContext(); Bindings bindings = context.getBindings(ScriptContext.ENGINE_SCOPE); bindings.put("name", "Alex"); engine.eval("println(name);"); } public void attributeInBindings() throws ScriptException { ScriptEngine engine = getJavaScriptEngine(); ScriptContext context = engine.getContext(); context.setAttribute("name", "Alex", ScriptContext.GLOBAL_SCOPE); engine.eval("println(name);"); } /** * @param args the command line arguments */ public static void main(String[] args) throws ScriptException { ScriptContextBindings scb = new ScriptContextBindings(); scb.scriptContextBindings(); scb.useScriptContextValues(); scb.attributeInBindings(); } }
2、JSR199--Java Compiler API
public class JavaCompilerAPICompiler {
public void compile(Path src, Path output) throws IOException {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
try (StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null)) {
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects(src.toFile());
Iterable<String> options = Arrays.asList("-d", output.toString());
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, options, null, compilationUnits);
boolean result = task.call();
}
}
}
3、JSR269--Pluggable Annotation Processing API
一部分是进行注解处理的javax.annotation.processing,另一部分是对程序的静态结构进行建模的javax.lang.model
4、其他
- 支持JDBC4.0规范
- JAX-WS 2.0规范(包括JAXB 2.0)
- 轻量级HttpServer
Java7的新特性
特性列表
- suppress异常(新语法)
- 捕获多个异常(新语法)
- try-with-resources(新语法)
- JSR341-Expression Language Specification(新规范)
- JSR203-More New I/O APIs for the Java Platform(新规范)
- JSR292与InvokeDynamic
- 支持JDBC4.1规范
- Path接口、DirectoryStream、Files、WatchService
- jcmd
- fork/join framework
- Java Mission Control
1、suppress异常(新语法)
/**
* 记录异常,不被淹没
* addSuppressed
*/
class ReadFile {
public void read(String filename) throws BaseException {
FileInputStream input = null;
IOException readException = null;
try {
input = new FileInputStream(filename);
} catch (IOException ex) {
readException = ex;
} finally {
if (input != null) {
try {
input.close();
} catch (IOException ex) {
if (readException == null) {
readException = ex;
}else{
//使用java7的
readException.addSuppressed(ex);
}
}
}
if (readException != null) {
throw new BaseException(readException);
}
}
}
}
2、捕获多个异常(新语法)
public void handle() {
ExceptionThrower thrower = new ExceptionThrower();
try {
thrower.manyExceptions();
} catch (ExceptionA | ExceptionB ab) {
System.out.println(ab.getClass());
} catch (ExceptionC c) {
}
}
3、try-with-resources(新语法)
实现AutoCloseable
/**
* @created 2014-07-21
*/
public class CustomResource implements AutoCloseable {
public void close() throws Exception {
System.out.println("进行资源释放。");
}
public void useCustomResource() throws Exception {
try (CustomResource resource = new CustomResource()) {
System.out.println("使用资源。");
}
}
public static void main(String[] args) {
try {
new CustomResource().useCustomResource();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
4、JSR341-Expression Language Specification(新规范)
public static void main(String[] args){
ELProcessor el = new ELProcessor();
assert (el.eval("Math.random()") instanceof Double);
}
5、JSR203-More New I/O APIs for the Java Platform(新规范)
- bytebuffer
- filechannel
6、JSR292与InvokeDynamic
JSR 292: Supporting Dynamically Typed Languages on the JavaTM Platform,支持在JVM上运行动态类型语言。在字节码层面支持了InvokeDynamic。
- 方法句柄MethodHandle
public class ThreadPoolManager { private final ScheduledExecutorService stpe = Executors .newScheduledThreadPool(2); private final BlockingQueue<WorkUnit<String>> lbq; public ThreadPoolManager(BlockingQueue<WorkUnit<String>> lbq_) { lbq = lbq_; } public ScheduledFuture<?> run(QueueReaderTask msgReader) { msgReader.setQueue(lbq); return stpe.scheduleAtFixedRate(msgReader, 10, 10, TimeUnit.MILLISECONDS); } private void cancel(final ScheduledFuture<?> hndl) { stpe.schedule(new Runnable() { public void run() { hndl.cancel(true); } }, 10, TimeUnit.MILLISECONDS); } /** * 使用传统的反射api */ public Method makeReflective() { Method meth = null; try { Class<?>[] argTypes = new Class[]{ScheduledFuture.class}; meth = ThreadPoolManager.class.getDeclaredMethod("cancel", argTypes); meth.setAccessible(true); } catch (IllegalArgumentException | NoSuchMethodException | SecurityException e) { e.printStackTrace(); } return meth; } /** * 使用代理类 * @return */ public CancelProxy makeProxy() { return new CancelProxy(); } /** * 使用Java7的新api,MethodHandle * invoke virtual 动态绑定后调用 obj.xxx * invoke special 静态绑定后调用 super.xxx * @return */ public MethodHandle makeMh() { MethodHandle mh; MethodType desc = MethodType.methodType(void.class, ScheduledFuture.class); try { mh = MethodHandles.lookup().findVirtual(ThreadPoolManager.class, "cancel", desc); } catch (NoSuchMethodException | IllegalAccessException e) { throw (AssertionError) new AssertionError().initCause(e); } return mh; } public static class CancelProxy { private CancelProxy() { } public void invoke(ThreadPoolManager mae_, ScheduledFuture<?> hndl_) { mae_.cancel(hndl_); } } }
- 调用
public class ThreadPoolMain { /** * 如果被继承,还能在静态上下文寻找正确的class */ private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private ThreadPoolManager manager; public static void main(String[] args) { ThreadPoolMain main = new ThreadPoolMain(); main.run(); } private void cancelUsingReflection(ScheduledFuture<?> hndl) { Method meth = manager.makeReflective(); try { System.out.println("With Reflection"); meth.invoke(hndl); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); } } private void cancelUsingProxy(ScheduledFuture<?> hndl) { CancelProxy proxy = manager.makeProxy(); System.out.println("With Proxy"); proxy.invoke(manager, hndl); } private void cancelUsingMH(ScheduledFuture<?> hndl) { MethodHandle mh = manager.makeMh(); try { System.out.println("With Method Handle"); mh.invokeExact(manager, hndl); } catch (Throwable e) { e.printStackTrace(); } } private void run() { BlockingQueue<WorkUnit<String>> lbq = new LinkedBlockingQueue<>(); manager = new ThreadPoolManager(lbq); final QueueReaderTask msgReader = new QueueReaderTask(100) { @Override public void doAction(String msg_) { if (msg_ != null) System.out.println("Msg recvd: " + msg_); } }; ScheduledFuture<?> hndl = manager.run(msgReader); cancelUsingMH(hndl); // cancelUsingProxy(hndl); // cancelUsingReflection(hndl); } }
7、支持JDBC4.1规范
- abort方法
public class AbortConnection { public void abortConnection() throws SQLException { Connection connection = DriverManager .getConnection("jdbc:derby://localhost/java7book"); ThreadPoolExecutor executor = new DebugExecutorService(2, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()); connection.abort(executor); executor.shutdown(); try { executor.awaitTermination(5, TimeUnit.MINUTES); System.out.println(executor.getCompletedTaskCount()); } catch (InterruptedException e) { e.printStackTrace(); } } private static class DebugExecutorService extends ThreadPoolExecutor { public DebugExecutorService(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); } public void beforeExecute(Thread t, Runnable r) { System.out.println("清理任务:" + r.getClass()); super.beforeExecute(t, r); } } public static void main(String[] args) { AbortConnection ca = new AbortConnection(); try { ca.abortConnection(); } catch (SQLException e) { e.printStackTrace(); } } }
- 自动关闭
public class SetSchema { public void setSchema() throws SQLException { try (Connection connection = DriverManager .getConnection("jdbc:derby://localhost/java7book")) { connection.setSchema("DEMO_SCHEMA"); try (Statement stmt = connection.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM author")) { while (rs.next()) { System.out.println(rs.getString("name")); } } } } public static void main(String[] args) { SetSchema ss = new SetSchema(); try { ss.setSchema(); } catch (SQLException e) { e.printStackTrace(); } } }
- 自动映射
public class UseSQLData { public void useSQLData() throws SQLException { try (Connection connection = DriverManager .getConnection("jdbc:derby://localhost/java7book")) { Map<String,Class<?>> typeMap = new HashMap<String,Class<?>>(); typeMap.put("java7book.Book", Book.class); try (Statement stmt = connection.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM book")) { while (rs.next()) { System.out.println(rs.getObject(1, Book.class)); } } } } public static void main(String[] args) { UseSQLData usd = new UseSQLData(); try { usd.useSQLData(); } catch (SQLException e) { e.printStackTrace(); } } }
8、Path接口(重要接口更新)
public class PathUsage {
public void usePath() {
Path path1 = Paths.get("folder1", "sub1");
Path path2 = Paths.get("folder2", "sub2");
path1.resolve(path2); //folder1\sub1\folder2\sub2
path1.resolveSibling(path2); //folder1\folder2\sub2
path1.relativize(path2); //..\..\folder2\sub2
path1.subpath(0, 1); //folder1
path1.startsWith(path2); //false
path1.endsWith(path2); //false
Paths.get("folder1/./../folder2/my.text").normalize(); //folder2\my.text
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
PathUsage usage = new PathUsage();
usage.usePath();
}
}
9、DirectoryStream
public class ListFile {
public void listFiles() throws IOException {
Path path = Paths.get("");
try (DirectoryStream<Path> stream = Files.newDirectoryStream(path, "*.*")) {
for (Path entry: stream) {
//使用entry
System.out.println(entry);
}
}
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws IOException {
ListFile listFile = new ListFile();
listFile.listFiles();
}
}
10、Files
public class FilesUtils {
public void manipulateFiles() throws IOException {
Path newFile = Files.createFile(Paths.get("new.txt").toAbsolutePath());
List<String> content = new ArrayList<String>();
content.add("Hello");
content.add("World");
Files.write(newFile, content, Charset.forName("UTF-8"));
Files.size(newFile);
byte[] bytes = Files.readAllBytes(newFile);
ByteArrayOutputStream output = new ByteArrayOutputStream();
Files.copy(newFile, output);
Files.delete(newFile);
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws IOException {
FilesUtils fu = new FilesUtils();
fu.manipulateFiles();
}
}
11、WatchService
public class WatchAndCalculate {
public void calculate() throws IOException, InterruptedException {
WatchService service = FileSystems.getDefault().newWatchService();
Path path = Paths.get("").toAbsolutePath();
path.register(service, StandardWatchEventKinds.ENTRY_CREATE);
while (true) {
WatchKey key = service.take();
for (WatchEvent<?> event : key.pollEvents()) {
Path createdPath = (Path) event.context();
createdPath = path.resolve(createdPath);
long size = Files.size(createdPath);
System.out.println(createdPath + " ==> " + size);
}
key.reset();
}
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws Throwable {
WatchAndCalculate wc = new WatchAndCalculate();
wc.calculate();
}
}
12、jcmd utility
jcmd是为了替代jps出现了,包含了jps的大部分功能并新增了一些新的功能。
- jcmd -l
列出所有的Java虚拟机,针对每一个虚拟机可以使用help列出它们支持的命令。
jcmd -l
15308 org.eclipse.jetty.xml.XmlConfiguration /tmp/start4070493346048555702.properties /opt/educat/apps/conf/jetty8.xml
5624 sun.tools.jcmd.JCmd -l
20967 org.apache.flume.node.Application --no-reload-conf -f /opt/educat/flume_agent/conf/flume.conf -n log_agent
- jcmd pid help
For more information about a specific command use 'help <command>'.
- jcmd pid VM.flags查看启动参数
13、fork/join
Java7提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。
14、Java Mission Control
在JDK7u40里头提供了Java Mission Control,这个是从JRockit虚拟机里头迁移过来的类似JVisualVm的东西。
15、其他
- Binary Literals支持
- Numeric Literals的下划线支持
- Strings in switch Statements
参考
特性列表
-
lamda表达式(重磅)
-
集合的stream操作
-
提升HashMaps的性能
-
Date-Time Package
-
java.lang and java.util Packages
-
Concurrency
lamda表达式(重磅)
集合的stream操作
提升HashMaps的性能
当hash冲突时,以前都是用链表存储,在java8里头,当节点个数>=TREEIFY_THRESHOLD - 1时,HashMap将采用红黑树存储,这样最坏的情况下即所有的key都Hash冲突,采用链表的话查找时间为O(n),而采用红黑树为O(logn)。
Date-Time Package
Java 8新增了LocalDate和LocalTime接口,一方面把月份和星期都改成了enum防止出错,另一方面把LocalDate和LocalTime变成不可变类型,这样就线程安全了。
java.lang and java.util Packages
-
ConcurrentHashMap的stream支持