序
这是Java语言特性系列的第一篇,从java5的新特性开始讲起。初衷就是可以方便的查看语言的演进历史。
特性列表 泛型
枚举
装箱拆箱
变长参数
注解
foreach循环
静态导入
格式化
线程框架/数据结构
Arrays工具类/StringBuilder/instrument
1、泛型
所谓类型擦除指的就是Java源码中的范型信息只允许停留在编译前期,而编译后的字节码文件中将不再保留任何的范型信息。也就是说,范型信息在编译时将会被全部删除,其中范型类型的类型参数则会被替换为Object类型,并在实际使用时强制转换为指定的目标数据类型。而C++中的模板则会在编译时将模板类型中的类型参数根据所传递的指定数据类型生成相对应的目标代码。Map squares = new HashMap();
通配符类型:避免unchecked警告,问号表示任何类型都可以接受
public void printList(List> list, PrintStream out) throwsIOException {for (Iterator> i =list.iterator(); i.hasNext(); ) {
out.println(i.next().toString());
}
}
限制类型
public static double sum(Box box1,Boxbox2){double total = 0;for (Iterator i =box1.contents.iterator(); i.hasNext(); ) {
total= total +i.next().doubleValue();
}for (Iterator i =box2.contents.iterator(); i.hasNext(); ) {
total= total +i.next().doubleValue();
}returntotal;
}
2、枚举
EnumMap
public void testEnumMap(PrintStream out) throwsIOException {//Create a map with the key and a String message
EnumMap antMessages =
new EnumMap(AntStatus.class);//Initialize the map
antMessages.put(AntStatus.INITIALIZING, "Initializing Ant...");
antMessages.put(AntStatus.COMPILING,"Compiling Java classes...");
antMessages.put(AntStatus.COPYING,"Copying files...");
antMessages.put(AntStatus.JARRING,"JARring up files...");
antMessages.put(AntStatus.ZIPPING,"ZIPping up files...");
antMessages.put(AntStatus.DONE,"Build complete.");
antMessages.put(AntStatus.ERROR,"Error occurred.");//Iterate and print messages
for(AntStatus status : AntStatus.values() ) {
out.println("For status " + status + ", message is: " +antMessages.get(status));
}
}
switch枚举
publicString getDescription() {switch(this) {case ROSEWOOD: return "Rosewood back and sides";case MAHOGANY: return "Mahogany back and sides";case ZIRICOTE: return "Ziricote back and sides";case SPRUCE: return "Sitka Spruce top";case CEDAR: return "Wester Red Cedar top";case AB_ROSETTE: return "Abalone rosette";case AB_TOP_BORDER: return "Abalone top border";caseIL_DIAMONDS:return "Diamonds and squares fretboard inlay";caseIL_DOTS:return "Small dots fretboard inlay";default: return "Unknown feature";
}
}
3、Autoboxing与Unboxing
将primitive类型转换成对应的wrapper类型:Boolean、Byte、Short、Character、Integer、Long、Float、Double
public static voidm1(Integer i){
System.out.println("this is integer");
}public static void m1(doubled){
System.out.println("this is double");
}
m1(1)输出的是double,方法匹配时线下兼容,不考虑boxing与unboxing。
4、vararg
privateString print(Object... values) {
StringBuilder sb= newStringBuilder();for(Object o : values) {
sb.append(o.toString())
.append(" ");
}returnsb.toString();
}
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 @interfaceTODO {
String value();
}
Target类型
public enumElementType {/**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 enumRetentionPolicy {/*** 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.
*
*@seejava.lang.reflect.AnnotatedElement*/RUNTIME
}
通过反射获取元信息
public classReflectionTester {publicReflectionTester() {
}public void testAnnotationPresent(PrintStream out) throwsIOException {
Class c= Super.class;boolean inProgress = c.isAnnotationPresent(InProgress.class);if(inProgress) {
out.println("Super is In Progress");
}else{
out.println("Super is not In Progress");
}
}public void testInheritedAnnotation(PrintStream out) throwsIOException {
Class c= Sub.class;boolean inProgress = c.isAnnotationPresent(InProgress.class);if(inProgress) {
out.println("Sub is In Progress");
}else{
out.println("Sub is not In Progress");
}
}public voidtestGetAnnotation(PrintStream out)throwsIOException, NoSuchMethodException {
Class c= AnnotationTester.class;
AnnotatedElement element= c.getMethod("calculateInterest",float.class, float.class);
GroupTODO groupTodo= element.getAnnotation(GroupTODO.class);
String assignedTo=groupTodo.assignedTo();
out.println("TODO Item on Annotation Tester is assigned to: '" +assignedTo+ "'");
}public voidprintAnnotations(AnnotatedElement e, PrintStream out)throwsIOException {
out.printf("Printing annotations for '%s'%n%n", e.toString());
Annotation[] annotations=e.getAnnotations();for(Annotation a : annotations) {
out.printf(" * Annotation '%s' found%n",
a.annotationType().getName());
}
}public static voidmain(String[] args) {try{
ReflectionTester tester= newReflectionTester();
tester.testAnnotationPresent(System.out);
tester.testInheritedAnnotation(System.out);
tester.testGetAnnotation(System.out);
Class c= AnnotationTester.class;
AnnotatedElement element= c.getMethod("calculateInterest",float.class, float.class);
tester.printAnnotations(element, System.out);
}catch(Exception e) {
e.printStackTrace();
}
}
}
6、for/in
for/in循环办不到的事情:
(1)遍历同时获取index
(2)集合逗号拼接时去掉最后一个
(3)遍历的同时删除元素
7、静态import
import staticjava.lang.System.err;import staticjava.lang.System.out;importjava.io.IOException;importjava.io.PrintStream;public classStaticImporter {public static voidwriteError(PrintStream err, String msg)throwsIOException {//Note that err in the parameter list overshadows the imported err
err.println(msg);
}public static voidmain(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*/
public classFormatTester {public static voidprintf() {//printf
String filename = "this is a file";try{
File file= newFile(filename);
FileReader fileReader= newFileReader(file);
BufferedReader reader= newBufferedReader(fileReader);
String line;int i = 1;while ((line = reader.readLine()) != null) {
System.out.printf("Line %d: %s%n", i++, line);
}
}catch(Exception e) {
System.err.printf("Unable to open file named '%s': %s",
filename, e.getMessage());
}
}public static voidstringFormat() {//Format a string containing a date.
Calendar c = new GregorianCalendar(1995, MAY, 23);
String s= String.format("Duke's Birthday: %1$tm %1$te,%1$tY", c);//-> s == "Duke's Birthday: May 23, 1995"
System.out.println(s);
}public static voidformatter() {
StringBuilder sb= newStringBuilder();//Send all output to the Appendable object sb
Formatter formatter = newFormatter(sb, Locale.US);//Explicit argument indices may be used to re-order output.
formatter.format("%4$2s %3$2s %2$2s %1$2s", "a", "b", "c", "d");//-> " d c b a"//Optional locale as the first argument can be used to get//locale-specific formatting of numbers. The precision and width can be//given to round and align the value.
formatter.format(Locale.FRANCE, "e = %+10.4f", Math.E);//-> "e = +2,7183"//The '(' numeric flag may be used to format negative numbers with//parentheses rather than a minus sign. Group separators are//automatically inserted.
formatter.format("Amount gained or lost since last statement: $ %(,.2f",6217.58);//-> "Amount gained or lost since last statement: $ (6,217.58)"
}public static voidmessageFormat() {
String msg= "欢迎光临,当前({0})等待的业务受理的顾客有{1}位,请排号办理业务!";
MessageFormat mf= newMessageFormat(msg);
String fmsg= mf.format(new Object[]{new Date(), 35});
System.out.println(fmsg);
}public static voiddateFormat(){
String str= "2010-1-10 17:39:21";
SimpleDateFormat format= new SimpleDateFormat("yyyyMMddHHmmss");try{
System.out.println(format.format(format.parse(str)));
}catch(ParseException e) {//TODO Auto-generated catch block
e.printStackTrace();
}
}public static voidmain(String[] args) {
formatter();
stringFormat();
messageFormat();
dateFormat();
printf();
}
}
9、threading
uncaught exception
public class BubbleSortThread extendsThread {private int[] numbers;public BubbleSortThread(int[] numbers) {
setName("Simple Thread");
setUncaughtExceptionHandler(newSimpleThreadExceptionHandler());this.numbers =numbers;
}public voidrun() {int index =numbers.length;boolean finished = false;while (!finished) {
index--;
finished= true;for (int i=0; i
if (numbers[i+1] < 0) {throw newIllegalArgumentException("Cannot pass negative numbers into this thread!");
}if (numbers[i] > numbers[i+1]) {//swap
int temp =numbers[i];
numbers[i]= numbers[i+1];
numbers[i+1] =temp;
finished= false;
}
}
}
}
}class SimpleThreadExceptionHandler implementsThread.UncaughtExceptionHandler {public voiduncaughtException(Thread t, Throwable e) {
System.err.printf("%s: %s at line %d of %s%n",
t.getName(),
e.toString(),
e.getStackTrace()[0].getLineNumber(),
e.getStackTrace()[0].getFileName());
}
}
blocking queue
public class Producer extendsThread {privateBlockingQueue q;privatePrintStream out;publicProducer(BlockingQueue q, PrintStream out) {
setName("Producer");this.q =q;this.out =out;
}public voidrun() {try{while (true) {
q.put(produce());
}
}catch(InterruptedException e) {
out.printf("%s interrupted: %s", getName(), e.getMessage());
}
}privateString produce() {while (true) {double r =Math.random();//Only goes forward 1/10 of the time
if ((r*100) < 10) {
String s= String.format("Inserted at %tc", newDate());returns;
}
}
}
}
线程池
著名的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
参考