Java网络编程

        URL类是网络编程的入口点,所以基于网络的编程首先创建一个URL对象,然后对象调用openConnection方法获得一个URLConnection对象,URLConnection对象可以通过getInputStream方法获得输入流,然后就转向IO编程。其实URL对象可以直接调用openStream方法获得InputStream对象,看到源代码中openStream方法就是调用openConnection().getInputStream而实现的,本质上都是一样的。
        在URL类的构造器URL(String url),url字符串是有严格的格式的,url中的协议必须填上,这不同于浏览器:浏览器可以为我们补上默认的协议和端口。url的格式如:"http://www.baidu.com",不能写成:"www.baidu.com"。
InetAddress类是一个表示IP地址的类,它没有提供public的构造方法,不能通过new的方式生成它的对象,只能通过它提供的静态方法获得InetAddress对象,它提供了3个常用的可以生成其对象的静态方法:getLocalHost()、getByName(String host)、getAllByName(String host),我们一般用第二个用得比较多。InetAddress的toString方法返回字符串格式为:The string returned is of the form: hostname / literal IP address.第一部分是主机名,通过斜线分隔IP地址。例如“www.baidu.com/65.34.25.110”、“Phoenix-PC/192.168.1.2”等。
        TCP通信主要用到ServerSocket、Socket两个类。
        服务器端:1、创建ServerSocket对象sc,2、sc调用accept()方法准备生成Scoket对象;前两步准备建立连接;(3、启动读写线程,while循环,多线程使得服务器可以和多个客服端建立连接)
客户端:1、创建Socket对象sc,;前一步准备建立连接;2、(启动读写线程)
       UDP通信主要用到DatagramSocket、DatagramPacket类。
       服务器端:1、创建DatagramSocket对象ds,2、创建DatagramPacket对象dp1,3、dc调用send方法发送dp1,4、构造一个DatagramPacket对象dp2给receive方法用,5、ds调用receive方法接受到dp2中。
UDP通信完全没有用到IO编程,完全基于packet。因为UDP是无连接的,所以就没有流,所以就没有IO。这完全是因为协议不同而不同。
2011/9/10
JDK5.0新特性
泛型(Generic)
        策略模式就是我们所说的面向接口编程,它最本质的思想是多态来实现的。
       抽象策略类定义为:接口或者抽象类。具体策略类实现抽象策略类。环境类中定义一个抽象策略类的引用。
集合中一定会遇到泛型,所以在使用集合时一定要使用泛型。
增强型for循环
        for(type element : 要遍历数组/集合名字){};type为数组/集合元素的具体类型。
注意二维数组使用增强的for循环,同样要使用两个enhanced for循环。
对于集合遍历就有三种方式:1、旧式for循环,2、Iterator迭代器遍历,3、增强for循环。
对于包装类Integer,它提供了一个缓存,缓存介于-128 - 127之间的整数,所以当使用Integer i1 = 100;Integer i2 = 100;时 i1 == i2为true,因为缓存的机制。但是当i1 = 128;i2 = 128时,i1 == i2为false,因为它超过了缓存的范围。
可变参数(Varargs)
        可变参数本质上是一个数组,所以方法在接受参数时可以用实际参数的形式,也可以用数组的形式。可变参数用三个点“...”来表示。
可变参数只能作为方法参数的最后一个参数,即一个方法不可能具有两个或者两个以上的可变参数。
枚举(Enum)
        可以把枚举理解为类层次上的一个概念。用enum关键字来声明一个枚举类型。switch后面除了byte、short、int、char,还可以接受枚举,这点记住。
         自定义的枚举类型都继承自java.lang.Enum类,枚举中的每个成员默认都是public、static、final的,所以可以通过枚举名.成员名直接直接调用,因为是static的,在外部可以直接使用,因为是public的。因为是final的,所以在case中可以使用。
         枚举中的每个成员就是所定义的枚举类型的一个实例。
        枚举中同样可以定义成员变量、构造方法、普通方法、main方法等。
        EnumSet是一个处理枚举的Set集合。EnumMap中的键必须是一个枚举类型,值没有限制。
        枚举最本质的特点就是实例个数是特定的。在定义枚举时就限制了枚举元素(枚举对象)的个数,在使用枚举时不能new出新的枚举对象。在编译时就已经确定枚举对象的个数,而类在使用可以动态生成不限个数的对象。
静态导入(Static Import)
       旧式导入是导入到类名级别;静态导入则要导入到静态成员变量、静态方法级别。静态导入就好像导入的成员变量、方法定义在当前类中。
       静态导入格式:import static com.lzh.common.People.Age;import static com.lzh.common.People.output;注意output为方法,导入方法时直接写方法名字即可。
反射(Reflection)
        反射是很多Java Web框架的基础。反射是发生在运行时(Runtime)。反射是一种运行时行为。
        Java中一个类对应一个Class对象,一个类无论生成多少个对象都对应同一个Class对象。通过这个Class对象可以获得当前类的概括信息,比如:类名、属性、方法、构造器等。
        获取一个类的Class对象方法:1、Class.forName("带包名的类名字"),2、类.class,每个类都提供了一个“类名.class”方式获得当前类的Class对象,可以理解为class属性。3、该类的对象调用getClass()方法。
对于原生类型也可以是Class类的对象,如byte.class、int.class等。
        Class对象是JVM生成的,我们无法手动Class对象。Class has no public constructor. Instead Class objects are constructed automatically by the Java Virtual Machine as classes are loaded and by calls to the defineClass method in the class loader. //根据API中表述可知,每个类的Class对象是在该类被加载到JVM中时由JVM自动生成的。
         通过反射来生成对象的方式:1、可以通过该类的Class对象调用newInstance()方法,2、通过Class对象获得Constructor对象,然后通过Constructor对象的newInstance()方法获得。对于方法1只能通过默认构造方法或者无参构造方法来生成对象,如果是想通过有参构造方法生成对象只能通过方法2。
2011/9/11   22:41:31
         对于包装类,如Integer.TYPE返回的是int,而Integer.class返回的是Integer类所对应的Class对象。
         通过反射就可以打破private限制类使得在类外也可访问类的private成员和方法。//但是默认下反射时会强制Java语言访问检查,可以通过AccessibleObject类中的setAccessible(true)方法来设置抑制访问检查,只有这样才能真正做到类外访问类中私有属性和私有方法。
        运用反射的流程:1、获得类的Class对象,2、有了类的Class对象后可以生成类的对象、对象生成后可以获得对象的属性和方法。
        Class提供了一个静态getSuperclass方法获得一个类的父类的Class对象。
        设计模式1:单例模式、2:策略模式、设计模式3:代理模式(Proxy Patten)
        静态代理:抽象代理角色(抽象类、接口)、代理角色、真实角色。
        动态代理的思想是在运行时装载一个类,然后生成该类的对象。
        动态代理的类必须实现InvocationHandler接口,该接口中只有一个方法invoke方法,实现该方法即可。
        Proxy类即是动态生成类的类,用它所提供的静态方法来生成运行时类。该类都是在运行时生成,并且实现了真实角色所实现的接口的方法。
注解注释(Annotation)
        JDK5.0开始,才有的注解。注解可以用在任何地方:类、成员、方法上。Override注解表示子类要重写或者实现父类方法。注解都是以“@”符号开始。@Override、@Deprecated注解表示方法是不建议被使用的。@SuppressWarning注解表示抑制警告,该注解一般要加括号,@SuppressWarning("unchecked")。
        注解和类、接口、枚举一样,是同一个层次上的概念。
        自定义注解用“@interface”符号标识。
         当我们使用@interface自定义注解类型时,实际上是自动(extends)继承了java.lang.annotation.Annotation接口由编译器自动完成的,这跟Enum一样,当我们定义一个枚举时,其实是自动继承了java.lang.Enum抽象类。
2011/9/12
         “all annotation types are also interfaces.”也就是说所有的注解都是接口。
         RetentionPolicy为保留策略,是一个枚举类型,有三个枚举值:SOURCE、CLASS、RUNTIME,只有当保留策略为运行时,才可以通过反射读取到方法或者类上定义的注解。
         RUNTIME-“Annotations are to be recorded in the class file by the compiler and retained by the VM at run time, so they may be read reflectively.” SOURCE策略只是在源码中有效,CLASS策略能够在编译后保留在class文件中。
         Retention必须搭配RetentionPolicy,Target必须搭配ElementTarget。这两组枚举有相似用法。Target定义注解只能放在类上、方法上、构造器上、局部变量...
        @Retention、@Target、@Documented(用于在生成DOC文档时将注解一同写入帮助文档中,默认下注解是不会写入帮助文档中的)。
        JUnit单元测试3.8是基于反射,4.x是基于反射和注解实现的。3.8版本中方法命名必须以test开头,因为反射的机制,首先带测试类的Class对象,然后获取Class对象的public所有Method对象数组,再遍历该数组并且调用getName判断是否以test开头。
2011/9/17
内部类(Inner Class)
         Java中的内部类分为4种。1、静态内部类(Static Inner Class),如果要想让static关键字修饰一个类,则这个类一定是内部类。普通类是不能被static关键字修饰的。
         内部类在编译后也会生成一个完全独立的class文件,class文件命名规则为:“外部类$内部类”。2、成员内部类(Member Inner Class),静态内部类去掉static关键字后就是成员内部类。3、局部内部类(Local Inner Class),他不能被public、protected、private、static关键字修饰,这和局部变量相似,同样不能被上述关键字修饰。局部内部类只能在定义该类的方法中使用。在外部内和其它类中是无法局部内部类的。局部内部类只能访问方法中声明的final类型变量,也就是只能访问方法中的常量。
         4、匿名内部类(Anonymous Inner Class),它是一种局部内部类,它是没有名字的内部类,所以也就没有关键字,没有构造器,它会隐式的继承一个父类或者是实现一个接口。它通常是作为方法参数。
         对于匿名内部类在编译后生成的class文件命名规则又不一样了,规则为:“外部类$.n.class”,n=1、2、...。
         设计模式1:单例模式、2:策略模式、设计模式3:代理模式(Proxy Patten)、4:观察者模式(Observer Pattern)。
观察者模式(Observer Pattern)
         抽象主题角色(抽象类、接口)、抽象观察者角色(抽象类、接口)、具体主题角色(实现抽象主题角色中的方法,持有具体观察者角色的引用)、具体观察者角色(实现抽象观察者角色)。
         Swing是基于AWT,也就是继承自AWT。
        JDK对观察者模式内置支持,java.util.Observable类,java.util.Observer接口就是对观察者模式开放的API。
        AWT中事件处理都是利用观察者模式来实现的,在IO中低级流向高级流转变都是利用装饰模式来实现的。
在Observable中changed变量默认下为false,所以在调用notifyObservers方法前一定要注意先调用setChanged方法,该方法为protected,子类可以调用。
        被观察者的状态发生变化时,就可以选择是否通知观察者来调用update方法。
2011/9/17