Core Java第十七章知识点总结——JDK新特性
知识点预览
自动装箱/拆箱
静态引入
可变长参数
for…each循环
格式化输入/输出
泛型
枚举
标注
并发
JDK6/JDK7新特性
自动装箱/拆箱
1.自动装箱/拆箱概念
由Java编译器在编译的时候,自动的完成简单类型与包装类型的相互转换
//JDK5 以前 简单类型 --> 包转类型 Integer i = new Integer(50); //JDK5 以前 包转类型 --> 简单类型 int b = i.intValue(); //JDK5 以后 简单类型 --> 包转类型 Integer a = 10; //JDK5 以后 包装类型 --> 简单类型 int c = a;
2.自动装箱/拆箱是编译器在编译的时候自动完成的
3. JDK5.0以后简单数据类型可以直接在集合中使用
静态引入
通过静态引入可以在使用一个类型静态成员的时候,不用书写类名,直接使用静态成员即可。
import static java.lang.Math.*;
package chp17.ex02; import static java.lang.Math.*; import static java.lang.System.*; /** * * @Author: Wentasy * @FullName: TestStatic.java * @Description: 通过静态引入可以在使用一个类型静态成员的时候,不用书写类名,直接使用静态成员即可。 * @Create Date: 2012-8-21 */ public class TestStatic { public static void main(String args[]){ System.out.println(PI); System.out.println(abs(-1)); out.println(PI); } }
for…each循环
通过for…each循环可以遍历数组、集合。Hashmap的遍历
package chp17.ex03; import java.util.ArrayList; import java.util.List; /** * * @Author: Wentasy * @FullName: TestForEach1.java * @Description: 通过for…each循环可以遍历数组、集合 * @Create Date: 2012-8-21 */ public class TestForEach1 { public static void main(String args[]){ String[] s = {"a","b","c"}; for(String ss:s){ System.out.println(ss); } List list = new ArrayList(); list.add("s1"); list.add("s2"); for(Object l :list){ System.out.println(l); } } }
可变长参数
1.可以使方法的参数可变
public static void print(String…s);
调用时可以不传,传一个或者多个
2.可变长参数其实质实际上就是数组,单比定义数组更加灵活,可以使用for…each进行遍历
3.可以把main函数写出可变长参数
4. 一个方法中最多有一个可变长参数
5. 可变长参数必须作为方法的最后一个参数
格式化输入/输出
1.JDK5.0提供了新的输入输出语句
2.格式化输出语句
System.out.printf();
out.printf(“yourname is %s age is %d”, name, age);
//照顾C/C++程序员的编程习惯
3.提供了更为简单的从命令行获取输入的工具类
java.util.Scanner
常用:Scanner s = new Scanner(System.in);
System.in:从控制台获得内容
枚举类型
1.一个类所创建的对象个数是固定的
2.枚举本质上还是类(编译生成.class文件)
3.enum关键字
enum Season{
SPRING,
SUMMER,
AUTUMN,
WINTER
}
枚举类的对象:枚举值
4.在没有枚举类型前,可以通过如下代码模拟枚举类型:
一个类的属性可以使一个类的对象
构造方法私有:类的外部无法创建对象
构造方法公有:可以任意创建
5. 枚举特点
a) 枚举类型的父类:java.lang.Enum
i. name():获得枚举名
ii. ordinal():获得枚举值的顺序
iii. values():在API中看不到,返回枚举类型数组
b)枚举类型可以定义属性,并提供相应的方法
enum Season { SPRING, SUMMER, AUTUMN, WINTER; private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
c)枚举类型有构造方法,但只能是私有的(没加访问修饰符,默认是private)
d)枚举类型可以显示提供构造方法
enum Season { SPRING("春天"), SUMMER("夏天"), AUTUMN("秋天"), WINTER("冬天"); private String name; Season(String name){ this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
e)枚举类型不能够继承(父类是Enum)
f) 枚举类型是final修饰符修饰,也是不能被别的类继承的
g)枚举类型可以提供抽象方法(由对应的枚举对象实现)
Operator
package chp17.ex10; /** * * @Author: Wentasy * @FullName: TestEnum.java * @Description: 枚举类型可以提供抽象方法(由对应的枚举对象实现) * @Create Date: 2012-8-21 */ public class TestEnum { public static void main(String args[]){ Operator o = Operator.ADD; System.out.println(o.calculate(1, 2)); } } enum Operator{ ADD{ public double calculate(double a, double b) { return a+b; } }, SUBSTRACT{ public double calculate(double a, double b) { return a-b; } }, MULTIPLY{ public double calculate(double a, double b) { return a*b; } }, DIVIED{ public double calculate(double a, double b) { return a/b; } }; public abstract double calculate(double a,double b); }
泛型
1. 实现类型安全的集合
没有泛型的集合——不安全
2. 注意事项
a) 泛型集合存储数据时支持多态
b) 泛型集合必须保证引用类型的泛型和对象类型的泛型一致
c) java编译器在JDK5.0以后建议集合使用泛型,如果不使用泛型,编译器会提出警告
3. 泛型通配符
首先看几个List的定义:
List<String> l1 = new ArrayList<String>(); List<Integer> l2 = new ArrayList<Integer>(); List<Double> l3 = new ArrayList<Double>(); List<Number> l4 = new ArrayList<Number>(); List<Object> l5 = new ArrayList<Object>();
a) List<?>l:匹配所有
b) List<? extends Number> l:匹配数字类型,除去String和Object
c) List<? super Number> l:匹配Number或者Number的父类,在这里除去String
d) List<? extends Comparable>l:除去所有实现了Comparable接口,这里除去Object
4.泛型类
体现Java模板编程
最早在C++中产生,通用性提高
classMyClass<E>//E:泛型,占位符
自己使用机率不大,JDK API集合中常见
标注(Annotation)
1. 标注的概念
给程序看的注释
2.@标注名
3.JDK中提供的标注
a) @Override 检查覆盖方法是否正确
b)@Deprecated 用于声明某个类或者方法已经过期,不建议使用
c) @SuppressWarnings 让编译器忽略报警
4. 覆盖toString()方法(@Override)
使用标注后,编译器可以检查覆盖方法是否正确
标注:方法、属性、类
5. 标注的分类
a) 标记标注:没有任何属性,如@Override、@Deprecated
b) 单值标注:有一个属性,需要赋值如@test(value=””) 或者@test(“”)//value可省
c)多值/普通标注:有多个属性
6.标注的父类
java.lang.annotation.Annotation
7. 自定义标注(多用于框架开发)
public @interface标注名 如:public @interface Test
8. 元标注——定义标注时使用的标注
a)@Target 限定标注的使用目标
enum ElementType
TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE,ANNOTATION_TYPE,PACKAGE
b) @Retention
enum RetentionPolicy
i.SOURCE:标注信息只保留在源程序中,在类文件中不保存
ii. CLASS(Default):标注信息保存在类文件中,程序运行时不能通过反射找到
iii. RUNTIME(常用):标注信息保存在类文件中,程序运行时通过反射API可以找到
9. 完整的标注定义
10. 标注属性
@interfaceFirst{
Strinf value();
}
//public可以省略
11. 标注属性的类型
标注属性的类型共有24种,基本类型,Sting,Class,Enums,Annotations以及它们的数组
12. 标注案例
通过标注设计一个自动测试的工具
TestMethod
package chp17.ex16; /** * * @Author: Wentasy * @FullName: TestMethod.java * @Description: 通过标注设计一个自动测试的工具 * @Create Date: 2012-8-21 */ public class TestMethod { @Test(parameter="suns") public void m1(String s1){ System.out.println("method m1 "+s1); } public void m2(String s2){ System.out.println("method m2 "+s2); } }
Test标注的设计
package chp17.ex16; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * * @Author: Wentasy * @FullName: Test.java * @Description: Test标注的设计 * @Create Date: 2012-8-21 */ @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Test { String parameter(); }
自动测试工具类的设计
如何得知这个类拥有@Test标注
如何获得@Test标注中的参数
如何运行拥有标注的方法
package chp17.ex16; import java.lang.reflect.Method; /** * * @Author: Wentasy * @FullName: TestAnnotation.java * @Description: 自动测试工具类的设计 * @Create Date: 2012-8-21 */ public class TestAnnotation { public static void main(String args[])throws Exception{ //获得反射需要的类对象 Class c = TestMethod.class; TestMethod t = (TestMethod)c.newInstance(); //获得所有的方法 Method[] m = c.getDeclaredMethods(); for(Method mm:m){ //判断哪个方法拥有Test标注 if(mm.isAnnotationPresent(Test.class)){ //获得Test标注 Test tt = mm.getAnnotation(Test.class); //获得Parameter属性的值 String name = tt.parameter(); mm.invoke(t, name); } } } }
并发
1. JDK5以后引入了并发包,摒弃了原有的java线程框架
java.util.concurrent
2. Thread类中存在的问题
线程运行完,被销毁,不划算,创建线程需要销毁大量的资源,每个线程运行完销毁后,效率必遇到瓶颈
通过线程池取代了原有的线程类
java.util.concurrent.ExecutorService
TestConcurrent
package chp17.ex17; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * * @Author: Wentasy * @FullName: TestConcurrent.java * @Description: 线程池的使用 * @Create Date: 2012-8-21 */ class T1 implements Runnable{ public void run() { for(int i=1;i<=100;i++){ System.out.println("t1 $$$$"); } } } class T2 implements Runnable{ public void run() { for(int i=1;i<=100;i++){ System.out.println("t2 ###"); } } } public class TestConcurrent { public static void main(String args[]){ //创建线程池 ExecutorService es = Executors.newFixedThreadPool(2); //启动线程 es.submit(new T1()); es.submit(new T2()); //关闭线程池 es.shutdown(); } }
3. 摒弃了Runnable接口
a) Runnable接口弊端:run方法没有提供返回值 没有声明异常,需要try…catch自己消化
b) java.util.concurrent.Callable<T>
c) public T call() throws Exception
d)Future:Future 表示异步计算的结果。
package chp17.ex18; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; /** * * @Author: Wentasy * @FullName: TestConcurrent.java * @Description: 线程的创建——Callable的使用 * @Create Date: 2012-8-21 */ class T1 implements Callable<String>{ public String call()throws Exception { for(int i=1;i<=100;i++){ System.out.println("t1 $$$$"); } return "T1 is Ok"; } } class T2 implements Callable<String>{ public String call()throws Exception { for(int i=1;i<=100;i++){ System.out.println("t2 ###"); } return "T2 is Ok"; } } public class TestConcurrent { public static void main(String args[]) throws Exception{ //创建线程池 ExecutorService es = Executors.newFixedThreadPool(2); //获得返回结果 Future<String> f1 = es.submit(new T1()); Future<String> f2 = es.submit(new T2()); System.out.println(f1.get()); System.out.println(f2.get()); //关闭线程池 es.shutdown(); } }
4. 摒弃synchronized
a)synchronized弊端:锁客观存在,synchronized不符合面向对象的编程思想
b) java.util.concurrent.locks.Lock
i.lock():加锁
ii.unlock():解锁
iii.tryLock():尝试加锁,能加上,返回true,否则返回false
5. 摒弃wait()、notify()、notifyAll()
a) java.util.concurrent.locks.Condition
i. await():放弃锁,进入等待队列,等同于wait()
ii.signal():唤醒等待队列的线程,等同于notify()
iii. signalAll():唤醒等待队列的所有线程,等同于notifyAll()
6.应用并发包的生产者、消费者问题
package chp17.ex19; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * * @Author: Wentasy * @FullName: TestProducerConsumer.java * @Description: 应用并发包的生产者、消费者问题 * @Create Date: 2012-8-21 */ public class TestProducerConsumer { public static void main(String[] args) { //创建线程池 ExecutorService es = Executors.newFixedThreadPool(2); //创建临界资源 Stack s = new Stack(); //创建生产者 Callable c1 = new Producer(s); //创建消费者 Callable c2 = new Consumer(s); //启动线程 es.submit(c1); es.submit(c2); //关闭线程池 es.shutdown(); } } class Stack{ private char[] data=new char[6]; private int index=0; private Lock l = new ReentrantLock(); private Condition pool = l.newCondition(); private void print(){ for(int i=0;i<index;i++){ System.out.print(data[i]+" "); } System.out.println(); } public void push(char c){ l.lock(); while(index==data.length){ try {pool.await();} catch (InterruptedException e){} } data[index]=c; index++; pool.signalAll(); l.unlock(); System.out.print(c+" push stack:"); print(); } public void pop(){ l.lock(); while(index==0){ try{pool.await();} catch (InterruptedException e) {} } index--; char c=data[index]; data[index]=' '; pool.signalAll(); l.unlock(); System.out.print(c+" poped stack:"); print(); } } class Producer implements Callable{ Stack s; public Producer(Stack s) { this.s = s; } public Object call() throws Exception{ for(char c='A';c<='Z';c++){ s.push(c); try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } return null; } } class Consumer implements Callable{ Stack s; public Consumer(Stack s) { this.s = s; } public Object call() throws Exception{ for(int i=1;i<=26;i++){ s.pop(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } return null; } }
JDK6/JDK7新特性
1. Java SE 6脚本支持
为开发者提供了同一应用中使用不同语言的能量
使用Java库扩展脚本语言
2.Java SE 6监控和管理的问题
a)jps
b) jconsole
c)jmap
d)jhat:用于解释jmap的输出
e) jstack:显示栈使用情况
3.Java SE 6 访问编译器
提供对编译器javac的访问,用于动态生成代码
Java工具或框架开发经常使用
4. Java SE 7更好的整型字面值
二进制面值
int mask = 0b101001;
long l = 0b10010010L;
package chp17.ex20; /** * * @Author: Wentasy * @FullName: Test.java * @Description: Java SE 7更好的整型字面值 二进制面值 编译环境需要是JDK 7.0 * @Create Date: 2012-8-21 */ public class Test { public static void main(String args[]){ //int i = 0b101001; //System.out.println(i); } }