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");
}
}
}/*Output
dispose() 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);
}
}
}/*Output
Threat on 02/10/2005 from 58.27.82.161
Threat on 02/11/2005 from 204.45.234.40
Threat 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());
}
}/*Output
Class name:FancyToyis Interface?[false]
Simple nameFancyToy
Canonical name:FancyToy
Class name:HasBatteriesis Interface?[true]
Simple nameHasBatteries
Canonical name:HasBatteries
Class name:Waterproofis Interface?[true]
Simple nameWaterproof
Canonical name:Waterproof
Class name:Shootsis Interface?[true]
Simple nameShoots
Canonical name:Shoots
Class name:Toyis Interface?[false]
Simple nameToy
Canonical 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());
}
}/*Output
Class name:FancyToyis Interface?[false]
Simple nameFancyToy
Canonical name:FancyToy
Class name:HasBatteriesis Interface?[true]
Simple nameHasBatteries
Canonical name:HasBatteries
Class name:Waterproofis Interface?[true]
Simple nameWaterproof
Canonical name:Waterproof
Class name:Shootsis Interface?[true]
Simple nameShoots
Canonical name:Shoots
Class name:Toyis Interface?[false]
Simple nameToy
Canonical 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);
}
}
}/*Output
stun!
on
Phasers
*///~
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());
}
}/*Output
Woof!
Sitting
Mime cannot speak
Pretending 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))));
}
}/*Output
28
-26
[5, 6, 7]
5040
210
11.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
*///~