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);
}
}