Thinking in Java 中闪耀的星星(二)
来源:互联网 发布:两个excel表格匹配数据 编辑:程序博客网 时间:2024/05/21 18:40
26.如果要实现某些方法,比如倒序顺序,建议用匿名内部类
看代码:第一个方法是倒序,第二个是打乱顺序
public class MultiIterableClass extends IterableClass{ public Iterable<String> reversed(){ return new Iterable<String>(){ public Iterator<String> iterator(){ return new Iterator<String>(){ int current =words.length-1; public boolean hasNext(){ return ccurrent>-1; } public String next(){ return words[current--]; } public void remove(){ throw new UnsupportedOperationException(); } }; } }; } public Iterable<String> randomized(){ return new Iterable<String>(){ public Iterator<String> iterator(){ List<String> shuffled=new ArrayList<String>(Arrays.asList(words)); Collections.shuffled(shuffled,new Random(47)); return shuffled.iterator(); } }; }
27.异常的作用
异常是Java的重要组成部分。结合Thinking in Java,我的理解是:
1)..异常类似于美国人的未来型消费,就是保证类库,基层代码的可用性,安全性,健壮性,把风险扔给高层处理。
2).把程序的异常集中处理,与程序分离,增强程序可读性。
28.异常日志
import java.io.*;class LoggingException extends Exception{ private static Logger logger=Logger.getLogger("LoggingException"); public LoggingException(){ StringWriter trace =new StringWriter(); printStackTrace(new PrintWriter(trace)); logger.severe(trace.toString()); }}public class LoggingExceptions{ public static void main(String[] args){ try{ throw new LoggingException(); }catch(LoggingException e){ System.err.println("Caught"+e); } try{ throw new LoggingException(); }catch(LoggingException e){ System.err.println("Caught"+e); } }}/*Output七月 25, 2016 5:48:06 下午 LoggingException <init>严重: LoggingException at LoggingExceptions.main(LoggingExceptions.java:14)CaughtLoggingException七月 25, 2016 5:48:06 下午 LoggingException <init>严重: LoggingException at LoggingExceptions.main(LoggingExceptions.java:19)CaughtLoggingException*//~
29.处理关闭连接的嵌套异常
在io流和数据库连接中,经常会打开一些连接,而这些连接往往会要求在程序结束时关闭,常见的是放在finally中。可是,如果这个连接创建不成功呢?那又何须关闭?给出了一个思路:如果连接创建失败,就不需要关闭连接,如果连接创建成功,最后再finally中关闭,可以通过异常嵌套来实现。
import java.io.*;class InputFile{ private BufferedReader in; public InputFile(String fname)throws Exception{ try{ in=new BufferedReader(new FileReader(fname)); }catch(FileNotFoundException e){ System.out.println("Could not open "+ fname); throw e; }catch(Exception e){ try{ in.close(); }catch(IOException e2){ System.out.println("in.close() unsuccessful"); } throw e; }finally{ } } public String getLine(){ String s; try{ s=in.readLine(); }catch(IOException e){ throw new RuntimeException("readLine() failed"); } return s; } public void dispose(){ try{ in.close(); System.out.println("dispose() successful"); }catch(IOException e2){ throw new RuntimeException("in.close() failed"); } }}public class Cleanup{ public static void main(String[] args){ try{ InputFile in=new InputFile("Cleanup.java"); try{ String s; int i=1; while((s=in.getLine())!=null); }catch(Exception e){ System.out.println("Caught Exception in main"); e.printStackTrace(System.out); }finally{ in.dispose(); } }catch(Exception e){ System.out.println("InputFile construction failed"); } }}/*Outputdispose() successful*///~
30.使用异常的建议
1).如果对异常没有明确的处理方案,不要轻易去处理异常。
2).尽量抛出异常给高层
3).尽量把不同的异常抛给高层
31.java正则
如果没有经常使用,正则的结构难记。建议在用时查看java的api文档。顺便提一下,java的控制台输出的system.out.format(…)会让我们记起C语言中的printf(…)。看下面防火墙的正则例子:
import java.util.*;public class ThreatAnalyzer{ static String threatData= "58.27.82.161@02/10/2005\n"+ "204.45.234.40@02/11/2005\n"+ "58.27.82.161@02/11/2005\n"+ "[Next log section with different data format]"; public static void main(String[] args){ Scanner scanner=new Scanner(threatData); String pattern="(\\d+[.]\\d+[.]\\d+[.]\\d+)@"+ "(\\d{2}/\\d{2}/\\d{4})"; while(scanner.hasNext(pattern)){ scanner.next(pattern); MatchResult match=scanner.match(); String ip=match.group(1); String date=match.group(2); System.out.format("Threat on %s from %s\n",date,ip); } }}/*OutputThreat on 02/10/2005 from 58.27.82.161Threat on 02/11/2005 from 204.45.234.40Threat on 02/11/2005 from 58.27.82.161*///~
32.类对象
先明白:一个java程序写好之后,在命令行下输入:javac xx.java 即编译,把.java文件里面的类编译为.class文件,当输入:java xx 是在运行程序。这时java虚拟机 JVM会加载用到的类。一开始并不会全部加载,而是等到需要用到该类才会加载(动态加载,也是java一大与c++区别的特性)。
那么平常在程序中又如何通过类对象获取对象呢?(反射机制)
1.class.forName(“xxx”) 会抛出一个ClassNotFoundException异常
2.xxx..class 比class.forName()更安全更高效。xxx.class 这句话分为3个步骤:
1).加载,加载.class文件的字节码
2).连接,为变量开辟地址空间
3). 初始化,为变量赋值
.class 的宗旨是:尽可能的懒。
33.Class类的几个方法
forName()/iddInterface()/getSimpleName()/getName()…
看例子:
interface HasBatteries{}interface Waterproof{}interface Shoots{}class Toy{ Toy(){} Toy(int i){}}class FancyToy extends Toy implements HasBatteries,Waterproof,Shoots{ FancyToy(){ super(1); }}public class ToyTest{ static void printInfo(Class cc){ System.out.println("Class name:"+cc.getName()+"is Interface?["+cc.isInterface()+"]"); System.out.println("Simple name"+cc.getSimpleName()); System.out.println("Canonical name:"+cc.getCanonicalName()); } public static void main(String[] args){ Class c=null; try{ c=Class.forName("FancyToy"); }catch(ClassNotFoundException e){ System.out.println("Can't find FancyToy"); System.exit(1); } printInfo(c); for(Class face:c.getInterfaces()){ printInfo(face); } Class up=c.getSuperclass(); Object obj=null; try{ obj=up.newInstance(); }catch(InstantiationException e){ System.out.println("Cannot instantiate"); System.exit(1); }catch(IllegalAccessException e){ System.out.println("Cannot access"); System.exit(1); } printInfo(obj.getClass()); }}/*OutputClass name:FancyToyis Interface?[false]Simple nameFancyToyCanonical name:FancyToyClass name:HasBatteriesis Interface?[true]Simple nameHasBatteriesCanonical name:HasBatteriesClass name:Waterproofis Interface?[true]Simple nameWaterproofCanonical name:WaterproofClass name:Shootsis Interface?[true]Simple nameShootsCanonical name:ShootsClass name:Toyis Interface?[false]Simple nameToyCanonical name:Toy*///~
34.RTTI(Runtime Type Information)的作用
多态,继承等在java程序运行时,必须告诉java编译器对象的类型。Java7的钻石语法 class也是一种,就是在编译时告诉编译器这是一个类,等到程序运行到需要明确指出类型时,才给出明确的类型(可以通过反射机制获取对象类型)(这些都是增强编译速度的)。到两个重要的类:xxx.newInstance() 和instanceof()
看例子:
1).import java.util.*;class CountedInteger{ private static long counter; private final long id=counter++; public String toString(){ return Long.toString(id); }}public class FilledList<T>{ private Class<T> type; public FilledList(Class<T> type){this.type=type;} public List<T> create(int nElements){ List<T> result=new ArrayList<T>(); try{ for(int i=0;i<nElements;i++){ result.add(type.newInstance());} }catch(Exception e){ throw new RuntimeException(e); } return result; } public static void main(String[] args){ FilledList<CountedInteger> fl=new FilledList<CountedInteger>(CountedInteger.class); System.out.println(fl.create(15)); }}/*Output[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]*///~ try{ obj=up.newInstance(); }catch(InstantiationException e){ System.out.println("Cannot instantiate"); System.exit(1); }catch(IllegalAccessException e){ System.out.println("Cannot access"); System.exit(1); } printInfo(obj.getClass()); }}/*OutputClass name:FancyToyis Interface?[false]Simple nameFancyToyCanonical name:FancyToyClass name:HasBatteriesis Interface?[true]Simple nameHasBatteriesCanonical name:HasBatteriesClass name:Waterproofis Interface?[true]Simple nameWaterproofCanonical name:WaterproofClass name:Shootsis Interface?[true]Simple nameShootsCanonical name:ShootsClass name:Toyis Interface?[false]Simple nameToyCanonical name:Toy*///~
2).instanceof的用法是
if(A instanceof B)返回一个boolean值
35.java的泛型
在《数据结构》中,泛型指的是数据类型不一致,操作方法一致。然而c++的泛型才能称为真正意义上的泛型,java的泛型实际上是假的。java泛型在java编译器编译的时候会有一个erasure(擦除)特性,就是把类型置空,比如 ArrayList,ArrayList在编译的时候都是ArrayList(),两者是相等的,所以,java泛型在使用(运行时)必须明确指定类型。但是,java的擦除特性是为java类库与上层程序开发的相互影响而迁就的办法,解决了版本之间的兼容性和java的可移植性。
java泛型的设计是为拓展代码的复用性。
36.java泛型的语法
下面通过一个简单的java版本的栈例子来看看:
public class LinkedStack<T>{ private static class Node<U>{ U item; Node<U> next; Node(){item=null;next=null;} Node(U item,Node<U> next){ this.item=item; this.next=next; } boolean end(){return item==null&&next==null;} } private Node<T> top=new Node<T>(); public void push(T item){ top=new Node<T>(item,top); } public T pop(){ T result=top.item; if(!top.end()){ top=top.next; } return result; } public static void main(String[] args){ LinkedStack<String> lss=new LinkedStack<String>(); for(String s:"Phasers on stun!".split(" ")) { lss.push(s); } String s; while((s=lss.pop())!=null){ System.out.println(s); } }}/*Outputstun!onPhasers*///~
37.在一些java的QQ群里,有人说:java泛型不就是集合中存取不同类吗?
这是错误的。因为泛型结合集合一起使用的功能强大,因此,java泛型大多以集合形式出现。
java泛型可以用在类,接口,方法。还可以继承。
38.泛型不能使用重载
void f(List v){}
void f(List w){}
由于擦除特性,在编译的时候两个都是:void f(List xx){},编译器也不会让程序编译通过的。
38.泛型的Latent typing特性
举个例子,一个哑巴类,一个狗类,一个表演类(里面有说话,坐下…的方法),只需要把狗/哑巴当成参数传给表演类,再调用表演类的方法,就可以表示狗/哑巴的表演。这就是Latent typing特性。很不幸,java没有latent typing特性,python与c++有。但是,在实际编程中,Latent typing是有用的,java虽然没有,但是可以手动模拟,看下面的例子:
import java.lang.reflect.*;class Mime{ public void walkAgainstTheWind(){} public void sit(){System.out.println("Pretending to sit");} public void puhInvisibleWalls(){} public String toString(){return "Mime";}}class SmartDog{ public void speak(){System.out.println("Woof!");} public void sit(){System.out.println("Sitting");} public void reproduce(){}}class CommunicateReflectively{ public static void perform(Object speaker){ Class<?> spkr=speaker.getClass(); try{ try{ Method speak=spkr.getMethod("speak"); speak.invoke(speaker); }catch(NoSuchMethodException e){ System.out.println(speaker+" cannot speak"); } try{ Method sit=spkr.getMethod("sit"); sit.invoke(speaker); }catch(NoSuchMethodException e){ System.out.println(speaker+" cannot sit"); } }catch(Exception e){ throw new RuntimeException(speaker.toString(),e); } }}public class LatentReflection{ public static void main(String[] args){ CommunicateReflectively.perform(new SmartDog()); CommunicateReflectively.perform(new Mime()); }}/*OutputWoof!SittingMime cannot speakPretending to sit*///~
39.java泛型+策略模式+适配器模式模拟c++的泛型
代码有点多,也有点难理解,了解思路就行:
import java.math.*;import java.util.concurrent.atomic.*;import java.util.*;interface Combiner<T>{T combine(T x,T y);}interface UnaryFunction<R,T>{R function(T x);}interface Collector<T> extends UnaryFunction<T,T>{T result();}interface UnaryPredicate<T>{boolean test(T x);}public class Functional{ public static <T> T reduce(Iterable<T> seq,Combiner<T> combiner){ Iterator<T> it=seq.iterator(); if(it.hasNext()){ T result=it.next(); while(it.hasNext()) result=combiner.combine(result,it.next()); return result; } return null; } public static <T> Collector<T> forEach(Iterable<T> seq,Collector<T> func){ for(T t:seq) func.function(t); return func; } public static <T> List<T> filter(Iterable<T> seq,UnaryPredicate<T> pred){ List<T> result=new ArrayList<T>(); for(T t:seq) if(pred.test(t)) result.add(t); return result; } static class IntegerAdder implements Combiner<Integer>{ public Integer combine(Integer x,Integer y){ return x+y; } } static class IntegerSubstracter implements Combiner<Integer>{ public Integer combine(Integer x,Integer y){ return x-y; } } static class BigDecimalAdder implements Combiner<BigDecimal>{ public BigDecimal combine(BigDecimal x,BigDecimal y){ return x.add(y); } } static class BigIntegerAdder implements Combiner<BigInteger>{ public BigInteger combine(BigInteger x,BigInteger y){ return x.add(y); } } static class AtomicLongAdder implements Combiner<AtomicLong>{ public AtomicLong combine(AtomicLong x,AtomicLong y){ return new AtomicLong(x.addAndGet(y.get())); } } static class BigDecimalUlp implements UnaryFunction<BigDecimal,BigDecimal>{ public BigDecimal function(BigDecimal x){ return x.ulp(); } } static class GreaterThan<T extends Comparable<T>> implements UnaryPredicate<T>{ private T bound; public GreaterThan(T bound){this.bound=bound;} public boolean test(T x){ return x.compareTo(bound)>0; } } static class MultiplyingIntegerCollector implements Collector<Integer>{ private Integer val=1; public Integer function(Integer x){ val*=x; return val; } public Integer result(){return val;} } public static void main(String[] args){ List<Integer> li=Arrays.asList(1,2,3,4,5,6,7); Integer result=reduce(li,new IntegerAdder()); System.out.println(result); result=reduce(li,new IntegerSubstracter()); System.out.println(result); System.out.println(filter(li,new GreaterThan<Integer>(4))); System.out.println(forEach(li,new MultiplyingIntegerCollector()).result()); System.out.println(forEach(filter(li,new GreaterThan<Integer>(4)),new MultiplyingIntegerCollector()).result()); MathContext mc=new MathContext(7); List<BigDecimal> lbd=Arrays.asList(new BigDecimal(1.1,mc),new BigDecimal(2.2,mc), new BigDecimal(3.3,mc),new BigDecimal(4.4,mc)); BigDecimal rbd=reduce(lbd,new BigDecimalAdder()); System.out.println(rbd); System.out.println(filter(lbd,new GreaterThan<BigDecimal>(new BigDecimal(3)))); }}/*Output28-26[5, 6, 7]504021011.000000[3.300000, 4.400000]*///~
40.数组+泛型
java设计者是推崇集合的,尤其是在高版本的java中。但是,对于基本类型,数组还是有用的。下面看看一个数组+泛型的例子:
import java.util.*;public class ArrayOfGenerics{ @SuppressWarnings("unchecked") public static void main(String[] args){ List<String>[] ls; List[] la=new List[10]; ls=(List<String>[])la; ls[0]=new ArrayList<String>(); System.out.println(ls); Object[] objects=ls; objects[1] =new ArrayList<Integer>(); System.out.println(ls); }}/*Output*///~
- Thinking in Java 中闪耀的星星(二)
- Thinking in Java 中闪耀的星星(一)
- Thinking in Java 中闪耀的星星(三)
- Thinking in Java 中闪耀的星星(四)
- Thinking in Java 中闪耀的星星(五)
- Thinking In Java (二)
- Thinking in Java 读书笔记 (二)
- 《thinking in JAVA》读书笔记 (二)
- 我的Thinking in Java学习笔记(二)
- Thinking in java-5 Java中对象存在的意义
- 《Thinking in Java》读书笔记(二)
- 学习《Thinking in java》笔记二
- Thinking In Java学习笔记二
- Thinking In Java 学习笔记(二)
- Thinking In Java琐碎知识点摘要(二)
- Thinking in Java 笔记(二)
- Thinking in Java阅读笔记(二)
- thinking in java学习笔记(二)
- 栈&队列面试题之之两个栈实现一个队列
- JVM之常用JVM配置参数
- C语言基础学习运算符-基本算术运算符
- 找到图中所有生成树的matlab实现
- 360 主页劫持修复
- Thinking in Java 中闪耀的星星(二)
- Flume官方文档翻译之(十)
- 1013 数素数
- Python 3 邮件的接收(IMAP)
- CentOS 6 无法上网 问题解决方案
- 集合(二)Collection的实现List和Set
- IOS 10 适配系列_2_ IOS10 适配汇总:ATS、隐私数据、UserNotifications、UICollectionView汇总
- @SuppressLint("NewApi")和@TargetApi()的区别
- Ubuntu 14.04 LTS 下升级 gcc 到 gcc-4.9、gcc-5 版本