tceic.com
简单学习网 让学习变简单
当前位置:首页 >> 学科竞赛 >>

Core Java 经典教程十七


JAVA5.0 的注释 (Annotation) 描述代码的代码。给编译器看的代码,作用是规范编译器的语法。 class Student{ @Override public String toString(){ return “student”; } } 类型(接口) 1. 标记注释 标记注释中没有属性,所以也不需要为属性赋值 @Override 2. 单值注释 单值注释中只能定

义一个属性。 @注释名(prameter=10) int parameter 特例: @注释名 (value “134” )(当单值注释的属性名为 value 时,可以省略属性名,直接写值) @SuperessWarning({“ddd”,”aaa”,”ccc”}) //JVM 还没有实现这个注释 3.普通注释(多值注释) (key1=value,……) 4.自定义注释 public @interface Test{ } 在自定义注释时,要用注释来注释(描述)注释。 @Target(value={……}),用来描述自定义注释所适用的程序元素的种类。单值注释 这个注释的值只能是 ElementType 枚举值,只能使用以下的值 ANNOTATION_TYPE 注释类型声明 CONSTRUCTOR 构造方法声明 FIELD 属性声明(包括枚举常量) LOCAL_VARIABLE 局部变量声明 METHOD 方法声明 (常用) PACKAGE 包声明 PARAMETER 参数声明 TYPE 类、接口(包括注释类型)或枚举声明(常用)

例: @Target({ElementType.METHOD, ElementType .TYPE})//表示这个注释可用的范围, 这个注释可以用在方法和类型及接口。 @Retention(value=……),描述(注释)注释能够保留到什么时候。单值注释 其中的值只能是以下的 RetentionPolicy 枚举的值 CLASS 编译器将把注释记录在类文件中,但在运行时 VM 不需要保留注释。 RUNTIME 编译器将把注释记录在类文件中, 在运行时 VM 将保留注释, 因此可以反射性 地读取。 SOURCE 编译器要丢弃的注释。 例: @Retention(RetentionPolicy.RUNTIME) // 编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取。 @Documented 表示某一类型的注释将通过 javadoc 和类似的默认工具进行文档化 @Inherited 表示注释类型该注释会被自动继承 注释的属性类型可以是 8 种基本类型、String、Enum、Class、Annotation 以及它们的数组 例: @Test() public class MyClass2 { @Test() public void study(String name){ System.out.println("Study "+name); } @Test(value="Meal")//单值注释 @Author(value={@Name(firstName="Liu",lastName="Chunyang"),@Name(first Name="Xue",lastName="Hiloo")})//单值注释中是用数组类型地赋值方法 public void eat(String food){ System.out.println("Eat "+food); } } 自定义注释的写法 例: import java.lang.annotation.*; @Target({ElementType.METHOD}) //表示这个注释可用的范围,这个注释只能用在方法之上。 @Retention(RetentionPolicy.RUNTIME) // 编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取。 public @interface Author {

Name[] value(); /* 定义注释的属性,注意属性后面要价括号,这个属性既是属性又是方法,可以返回属 性的值 */ } import java.lang.annotation.*; @Target({ElementType.METHOD,ElementType.TYPE})//这个注释可用于类, 接口和方 法 @Retention(RetentionPolicy.RUNTIME) public @interface Test { String value() default "ABC" ;//定义注释的属性及其默认值 } 处理自定义注释的类 例: import java.lang.reflect.*; public class TestFramework { public static void main(String[] args) throws Exception { Class c=Class.forName("MyClass2");//获取有注释的类的类对象 Method[] ms=c.getMethods();//获得该类中有的方法对象 Object o=c.newInstance();//获得该类的实例 for(Method m:ms){ boolean flag=m.isAnnotationPresent(Test.class); /* isAnnotationPresent(Class c)这个方法是判断这个方法是不是加上了注 释注意这是方法对象的方法 */ if (flag){ Test t=m.getAnnotation(Test.class); /* getAnnotation(Class c)方法是获得该方法的注释,得到注释对象 t 可以通过注释对象 ”属性名()”也就是 value(),获得注释的属性的值 */ String value=t.value(); m.invoke(o,value); } flag=m.isAnnotationPresent(Author.class); if (flag){ Author a=m.getAnnotation(Author.class); Name[] ns=a.value(); for(Name n:ns){

String fn=n.firstName(); String ln=n.lastName(); System.out.println(fn+ " "+ ln); } } } } } 例 2: 定义注释 import java.lang.annotation.*; @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Test { String name(); String sex(); } 使用注释
public class TestAnntion { @Test(name="liucy",sex="man") public void test(String name,String sex){ System.out.println(name+" "+sex); } }

处理注释 import java.lang.reflect.Method; public class TestT { public static void main(String[] args) throws Exception { Class c=Class.forName(args[0]); Method[] ms=c.getMethods(); Object o=c.newInstance(); for(Method m:ms){ boolean flag=m.isAnnotationPresent(Test.class); if (flag){ Test t=m.getAnnotation(Test.class); String name=t.name(); String sex=t.sex();

m.invoke(o, name,sex); } } }

三个新加的多线程包 Java 5.0 里新加入了三个多线程包: java.util.concurrent, java.util.concurrent.atomic, java.util.concurrent.locks. java.util.concurrent 包含了常用的多线程工具,是新的多线程工具的主体。 java.util.concurrent.atomic 包含了不 用加锁 情况 下就能 改变值 的原子变 量,比 如说 AtomicInteger 提供了 addAndGet()方法。Add 和 Get 是两个不同的操作,为了保证别的 线程不干扰,以往的做法是先锁定共享的变量,然后在锁定的范围内进行两步操作。但用 AtomicInteger.addAndGet()就不用担心锁定的事了, 其内部实现保证了这两步操作是在原 子量级发生的,不会被别的线程干扰。 java.util.concurrent.locks 包包含锁定的工具。 Callable 和 Future 接口 Executor 接口替代了 Thread 类,他可以创建定量的和动态以及周期性的线程池。 ExecutorService 接口,线程池,用来存放线程来节省创建和销毁资源的消耗。 Callable 是类似于 Runnable 的接口,实现 Callable 接口的类和实现 Runnable 的类都是可 被其它线程执行的任务。 Callable 和 Runnable 有几点不同: Callable 规定的方法是 call(),而 Runnable 规定的方法是 run(). Callable 的任务执行后可返回值,而 Runnable 的任务是不能返回值的。 call()方法可抛出异常,而 run()方法是不能抛出异常的。 Future 对象可以获得线程运行的返回值 运行 Callable 任务可拿到一个 Future 对象,通过 Future 对象可了解任务执行情况,可取 消任务的执行,还可获取任务执行的结果。 以下是 Callable 的一个例子: public class DoCallStuff implements Callable{ // *1 private int aInt; public DoCallStuff(int aInt) { this.aInt = aInt; } public String call() throws Exception { //*2 boolean resultOk = false;

if(aInt == 0){ resultOk = true; } else if(aInt == 1){ while(true){ //infinite loop System.out.println("looping...."); Thread.sleep(3000); } } else { throw new Exception("Callable terminated with Exception!"); //*3 } if(resultOk){ return "Task done."; } else { return "Task failed"; } } } *1: 名为 DoCallStuff 类实现了 Callable,String 将是 call 方法的返回值类型。例子中用了 String,但可以是任何 Java 类。 *2: call 方法的返回值类型为 String,这是和类的定义相对应的。并且可以抛出异常。 *3: call 方法可以抛出异常,如加重的斜体字所示。 以下是调用 DoCallStuff 的主程序。 import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class Executor { public static void main(String[] args){ //*1 DoCallStuff call1 = new DoCallStuff(0); DoCallStuff call2 = new DoCallStuff(1); DoCallStuff call3 = new DoCallStuff(2); //*2 ExecutorService es = Executors.newFixedThreadPool(3); //*3 Future future1 = es.submit(call1); Future future2 = es.submit(call2); Future future3 = es.submit(call3); try { //*4 System.out.println(future1.get()); //*5 Thread.sleep(3000);

System.out.println("Thread future2.cancel(true));

2

terminated?

:"

+

//*6 System.out.println(future3.get()); } catch (ExecutionException ex) { ex.printStackTrace(); } catch (InterruptedException ex) { ex.printStackTrace(); } } } *1: 定义了几个任务 *2: 初始了任务执行工具。任务的执行框架将会在后面解释。 *3: 执行任务,任务启动时返回了一个 Future 对象,如果想得到任务执行的结果或者是异 常可对这个 Future 对象进行操作。Future 所含的值必须跟 Callable 所含的值对映,比如说 例子中 Future 对印 Callable *4: 任务 1 正常执行完毕,future1.get()会返回线程的值 *5: 任务 2 在进行一个死循环,调用 future2.cancel(true)来中止此线程。传入的参数标明 是否可打断线程,true 表明可以打断。 *6: 任务 3 抛出异常,调用 future3.get()时会引起异常的抛出。 运行 Executor 会有以下运行结果: looping.... Task done. //*1 looping.... looping....//*2 looping.... looping.... looping.... looping.... Thread 2 terminated? :true //*3 //*4 java.util.concurrent.ExecutionException: java.lang.Exception: Callable terminated with Exception! at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:205) at java.util.concurrent.FutureTask.get(FutureTask.java:80) at concurrent.Executor.main(Executor.java:43) ……. *1: 任务 1 正常结束 *2: 任务 2 是个死循环,这是它的打印结果 *3: 指示任务 2 被取消 *4: 在执行 future3.get()时得到任务 3 抛出的异常 lock 接口

实现类 ReentrantLock 我们可以用 lock 对象,来对临界资源加锁调用 lock 对象的 lock()方法,使得没有得到锁的 线程阻塞,解锁则调用 lock 对象的 unlock()方法,并且释放锁,只有获得 lock 对象才能访 问临界资源,如果没有获得 lock 对象,就会进入 lock 对象的锁池。trylock()方法会返回布 尔值,这个方法是用来判断这个锁对象是不是已经被线程获取,如果返回值为 true,则会直 接获得这个锁对象,如果返回 false,线程不会阻塞还会继续运行。 Lock lock=new ReentrantLock(); publci void test(){ try{ if(lock.trylock){//判断锁是否已经分配出去 lock.lock(); //如果锁没有被分配,就会获得锁,没有得到锁,就阻塞 }else{ ...... } .....//需要加锁的临界资源。 }finally{ lock.unlock();//解锁,释放锁。 } } ReadWriteLock 读写锁接口 ReentrantReadWriteLock 是 ReadWriteLock 的实现类。 ReentrantReadWriteLock 的 Lock readLock()方法会分配读锁对象,读锁可以分配多个 线程,但是在分配读锁后所有读锁释放前,写锁是不能被分配的。 ReentrantReadWriteLock 的 Lock writeLock()方法会分配写锁对象,且只能分配给一个 线程,在分配写锁后,在写锁释放前,读锁是不能被分配。 Condition 接口和实现类 Condition 是等待对列的对象,它是通过 lock 对象的 newCondition()方法得到的 Condition 实现类的 await()替代了 wait()方法。 notify(),notifyAll() 在 JDK5.0 中已经用 Condition 实现类的 signal() ,signalAll()方法 替换掉了,在 JDK5.0 中,可以使用多个等待队来存放等待的线程,并对线程进行分类。 Queue 接口(Collection 的子接口,队列接口) LinkedList 也实现了这个在 JDK5.0 中的新接口 Queue, 并且这个类自动的实现了生产者和 消费者的同步。

JDK5.0 的高级同步 Semaphore 类(信号量)也就是可以向线程分配许可证,指定许可证数量可以实现多线程 的同步。 Semaphore s=new Semaphore(4); //可以分配 4 个许可证,许可证都被分配出去时,得不到许可证的线程就会阻塞。 Semaphore 类的 acquire(…)方法,获得许可证。Semaphore 类的 release(…) 方法,释放 一个许可证,也有相应的方法指定释放和获得许可证的数量的方法。 CountDownLatch 类 CountDownLatch 中有个计数器,访问这个类的对象就会从计数器中减一,countDown()方 法会将原有的设置的计数器值减一, countdown 计数器为零时会使放所有 await()的线程。 当 CyclicBarrier 类 CyclicBarrier 和 CountDownLatch 比较相似 CyclicBarrier 在构造时给出线程数, 只有等待的线程数到了构造方法中指定的数量, 当最后 一个线程等待后,所有的线程都会被释放,这个类是一个多线程汇合的工具。 Exchanger 类,用 exchange()方法可以使两个线程间相互交换对象,在两线程的同步点, 等待第二个线程。在同步点时,交换对象,并同时被释放。


推荐相关:

核心java简明教程

核心java简明教程_IT/计算机_专业资料。还是比较全面的core java的学习资料。可以...char c3=97; 十七java 中的转义字符 1. 表示格式控制的转义字符(如:\n ...


Core java经典教程九

Core java经典教程九_计算机软件及应用_IT/计算机_专业资料。java中的图形界面java...Core Java 经典教程十七 9页 免费 Core Java 经典教程十五 12页 免费 ...


core java目录

core java目录_计算机软件及应用_IT/计算机_专业资料。core Java的知识点 ...17 1.2.9 High-Performance Multithreaded Dynamic 8 10 1.3 Java Applets ...


非常经典的solr教程

type="java.lang.String" value="${catalina.home}/webapps/solr/conf/...8080/solr 会显示出两个 core , solr 正常运行 7 配置分词 , 使用的是 ...


Java例16.15-16.23及例17.1-17.4

(2)完成教材17 章 写上详细注释) 三、实验步骤 //例 16.15:编程实现...(); } } } } //filename App16_20.java 对当前数据库 StudentScore 中表...


java从零基础到精通的整个详细笔记(带批注)

java 视频教程之基础知识及概念 《JAVA 开发实战经典...eg: history //可以显示用户过去使用的命令 17. !...如:java com.work.core.HelloWorld 后面的.class ...


java测试题

Java学习笔记(必看经典) 30页 免费 CoreJava考试试题--达内科... 4页 免费如...第十七,String 是最基本的数据类型吗 ?位于哪个包下?是什么类型的? 第十八,...


自己配置Hadoop2.2.0

java 安装程序路径: mkdir -p /usr/java 安装 JDK 1 将下 载好的 jdk-6u...core-1.8.jar:/home/hadoop/hadoop/share/hadoo p/hdfs/lib/log4j-1.2.17....


JEECG3.4.3-MAVEN版本手把手入门-国明篇

<natures> <nature>org.eclipse.jdt.core.java...289782002 17 JEECG 微云开发平台 maven 版本入门手册...绝对经典搞笑照片81份文档 笑话大全集 笑话大全爆笑...


Java复习题

(Core Java) try{ throw new ExampleB(“b”); }catch(ExampleA e){ ...例如:F(7)=1+3+5+7+11+13+17=58; 六:写一个方法,传递一个数字串,算...

网站首页 | 网站地图
All rights reserved Powered by 简单学习网 www.tceic.com
copyright ©right 2010-2021。
文档资料库内容来自网络,如有侵犯请联系客服。zhit325@126.com