黑马程序员--Java基础学习笔记【单例设计模式、网络编程、反射】

 

 ------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------    

设计模式分类:

    创建模式:是对类的实例化过程的抽象化,又分为类创建模式和对象创建模式

        类创建模式:工厂方法模式

        对象:简单工厂(静态工厂方法)模式、抽象工厂模式、单例模式、建造模式

    结构模式:描述如何将类或者对象结合在一起形成更大的结构

        适配器模式、缺省模式、合成模式、装饰模式(包装模式)、门面模式

    行为模式:对不同的对象之间划分责任和算法的抽象化

       不变模式、策略模式、迭代子模式、命令模式、访问者模式

 

  • 单例设计模式(Singleton,一种对象创建模式)

    单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

    如何保证类在内存中只有一个对象?

    1.私有化类的构造方法

    2. 本类的成员位置创建自己的本类对象

    3. 提供公共方法,让外界获取这个本类对象

-------------------------------饿汉式--------------------------------

/*

 * 饿汉式,适合开发

 * 在类初始化时,已经自行实例化

 */

class SingletonHungry {

    // 已经自行实例化

    privatestatic SingletonHungry s = new SingletonHungry();

 

    // 私有的默认构造器

    private SingletonHungry() {

    }

 

    // 静态工厂方法

    publicstatic SingletonHungrygetInstance() {

       returns;

    }

}

---------------------------懒汉式(延迟加载)---------------------------

/*

 * 懒汉式,适合面试

 * 在第一次调用的时候实例化

 */

class SingletonLazy {

    // 没有final修饰

    privatestatic SingletonLazy s = null;

 

    // 私有的默认构造器

    private SingletonLazy() {

    }

 

    // // 未考虑线程安全问题

    // public static SingletonLazy getInstance() {

    // if (s == null) {

    // s = new SingletonLazy();

    // }

    // return s;

    // }

 

    // // 静态方法加锁实现线程安全

    // public static synchronized SingletonLazy getInstance(){

    // if (s == null) {

    // s = new SingletonLazy();

    // }

    // return s;

    // }

 

    // 静态工厂方法

    // 同步代码块实现线程安全,双重检查实现高效

    /*

     * 静态方法锁的对象是类对象,每个类都有唯一的一个类对象

     * 获取类对象的方式:类名.class

     */

    /*

     * 静态方法与非静态方法同时声明了 synchronized ,他们之间是非互斥关系的。

     * 原因在于,静态方法锁的是类对象,而非静态方法锁的是当前方法所属对象。

     */

    publicstatic SingletonLazygetInstance() {

       if (s == null) { // 高效

           synchronized (SingletonLazy.class) { // 安全

              if (s == null) {

                  s = new SingletonLazy();

              }

           }

       }

       returns;

    }

}

 

==============================网络编程===============================

InetAddress

    getByName 获取任意主机的 IP 地址

    getHostName 返回字符串形式的主机名

    getHostAddress 得到主机字符串形式IP地址

端口:计算机与外界通信交流的出口

    知名端口:01024;动态端口:102465535

TCP UDP协议

TCP:面向连接的保护可靠传输的协议,不定长度的数据

UDP:无连接的协议,每个数据包中包含完整的源、目的信息,传输大小有限制 64KB

 

  • UDP 通信

DatagramPacket 用于发送和接收数据的不同构造方法

// 接收数据

DatagramPacket(byte[] ibuft, intlength)

DatagramPacket(byte[] ibuft, intoffset, int length)

// 发送数据(指定对方IP地址和端口)

DatagramPacket(byte[] ibuf, intilength, InetAddress iaddr, int port)

DatagramPacket(byte[] ibuf, intoffset, int ilength, InetAddress iaddr, int port)

 

DatagramPacket 对象的常用方法

InetAddress getAddress() // 返回远程主机的IP地址

byte[] getData() // 返回字节数组类型的数据

int getLength() // 返回数据的字节数

int getPort() // 返回远程主机的端口号

SocketAddress getSocketAddress() // 返回远程主机的SocketAddress

int getOffset() // 返回数据的偏移量

 

DatagramSocket 对象的创建及常用方法

    DatagramSocket()

    DatagramSocket(int port)

    DatagramSocket(int port,InetAddress iaddr)

    InetAddress getLocalAddress() // 获取套接字绑定本机IP地址

    int getLocalPort() // 返回套接字绑定本机端口号

    SocketAddressgetLocalSocketAddress() // 返回包含IP地址和端口号的sa

    void receive(DatagramPacket dp)// 接收数据包

    void send(DatagramPacket dp) // 发送数据包

 

  • 数据报套接字,接收端和发送端程序的编写步骤

接收端:(明确端口:指定端口或随机端口)

  1. 调用DatagramSocket(int port)创建一个数据报套接字,并绑定到指定端口

  2. 调用DatagramPacket(byte[] buf,int     length),建立一个字节数组以接收UDP

  3. 调用DatagramSocket类的receive()方法,接收UDP

  4. 最后关闭数据报套接字

发送端:(不需指定端口)

  1. 调用DatagramSocket()创建一个数据报套接字

  2. 调用DatagramPacket(byte[] buf, int     offset, int length, InetAddress address, int port),建立要发送的UDP

  3. 调用DatagramSocket类的send()方法,发送UDP

  4. 最后关闭数据报套接字

 

  • TCP 通信

Socket 的构造方法及常用方法

Socket(String host, int port)

Socket(InetAddress host, int port)

InputStream getInputStream()

OutputStream getOutputStream()

InetAddress getInetAddress() // 返回套接字连接的地址

int getPort() // 返回套接字连接到的远程端口

close()

 

ServerSocket 的构造方法及常用方法

ServerSocket(int port)

ServerSocket(int port, int queuelength)

// 指定本地端口号,连接请求队列的长度(最大连接数目),本地网络地址

ServerSocket(int port, int queuelength, InetAddressbindaddress)

accept() // 侦听并接受套接字的连接

close()

 

  • C/S通信的编写步骤

服务器端的编写流程:

  1. 指定本地端口号,创建ServerSocket对象,监听指定端口的 Socket 连接

  2. 使用 ss 对象的accept()方法,接收的客户端连接请求,返回Socket 对象

  3. 获取Socket对象的输入/输出流

  4. 接收数据,处理数据,回传数据

  5. 关闭流和 Socket,关闭 ServerSocket

客户端的编写流程

  1. 1.  指定要连接的 IP 地址和端口号,创建Socket对象

  2. 2.  获取 socket 对象的输入/输出流

  3. 3.  读写字节流数据

  4. 4.  关闭流,关闭 Socket

 

  • 客户端与服务端通信模型如下:

说明: http://pdf7.tarena.com.cn/source/doc/JSD1503Y/6090/index.files/image001.png

1.     服务端创建ServerSocket

2.     通过调用ServerSocket的accept方法监听客户端的连接

3.     客户端创建Socket并指定服务端的地址以及端口来建立与服务端的连接

4.     当服务端accept发现客户端连接后,获取对应该客户端的Socket

5.     双方通过Socket分别获取对应的输入与输出流进行数据通讯

6.     通讯结束后关闭连接。

 

 

  • 反射 reflection

    Java中类的反射是一种自我管理机制,通过反射可实现:

在运行时判断任意一个对象所属的类;

在运行时构造任意一个类的对象;

在运行时判断任意一个类所具有的成员变量和成员方法;

在运行时调用任意一个对象的方法。

 

    类的加载过程:

加载:将.class文件读入内存,并为之创建一个 Class 对象

连接:

验证内部结构

准备静态成员分配内存默认初始化

解析二进制数据中的符号引用 --> 直接引用

初始化:

类初始化时机:

创建实例,访问静态变量,调用静态方法,反射强行加载,初始化子类,运行主类

 

  • 三种方式获取Class文件对象

       // 使用父类方法 getClass 获取

       Classclass1p.getClass();

       System.out.println(class1);

      

       // 使用类的静态属性 class

       Classclass2= Person.class;

       System.out.println(class2);

      

       // 使用Class类的静态方法 forName

       // 全类名

       Classclass3= Class.forName("cn.itcast.Person");

       System.out.println(class3);

 

  • 通过反射获取构造方法并使用

       // 获取class文件中的公有的构造方法

       Constructor<?>[]constructors= class3.getConstructors();

       for (Constructor<?> constructor : constructors) {

           System.out.println(constructor);

       }

      

       // 获取指定构造方法,空参数

       Constructor<?>constructor= class3.getConstructor();

      

       // 运行获取到的构造方法

       Objectobject= constructor.newInstance();

       System.out.println(object);

      

       System.out.println("--------------------------");

       // 获取带参数构造方法

       // 传递参数列表,要传递这个数据类型的class对象

       Constructorconstructor2= class3.getConstructor(String.class, int.class);

      

       Objectobject2= constructor2.newInstance("zs", 20);

       System.out.println(object2);

      

       System.out.println("--------------------------");

       // 获取所有的构造方法

       Constructor<?>[]constructors2= class3.getDeclaredConstructors();

       for (Constructor<?> constructor3 : constructors2) {

           System.out.println(constructor3);

       }

      

       // 获取私有构造方法并运行

       Constructorconstructor3= class3.getDeclaredConstructor(String.class);

      

//     //调用Constructor父类方法 setAccessible(true)

//     constructor3.setAccessible(true);// 暴力访问,不建议使用

      

//     constructor3.newInstance("ls");// java.lang.IllegalAccessException

//     System.out.println(constructor3);

      

       System.out.println("==========================");

      

       // 保证空参数的构造方法存在,并且具有可访问权限

       Classclazz= Class.forName("cn.itcast.Person");

       // 不获取构造方法,直接调用具有可访问权限的空参数的构造方法

       Objectobject3= clazz.newInstance();

       System.out.println(object3);

 

  • 通过反射获取成员变量并使用

       // 获取所有公共成员变量

       Field[]fields= clazz.getFields();

       for (Field field : fields) {

           System.out.println(field);

       }

      

       // 获取指定成员变量

//     Fieldfields2 = clazz.getField("age");

//     System.out.println(fields2);

      

       // 修改获取到的成员变量值,必须有这个类的支持

//     Objectobj = clazz.newInstance();

//     fields2.set(obj,22);

      

       // 获取所有成员变量

       clazz.getDeclaredFields();

       // 获取指定的成员变量

       clazz.getDeclaredField("age");

 

  • 通过反射获取成员方法并使用

       // 获取所有公共成员方法和继承的

       Method[]methods= clazz.getMethods();

       for (Method method : methods) {

           System.out.println(method);

       }

      

       // 获取指定的成员方法 (字符串方法名,Class类型的参数列表)

       Methodmethod= clazz.getMethod("toString");

       System.out.println(method);

       // 运行获取到的方法,传递对象和实际参数

       Objectobj= clazz.newInstance();

       method.invoke(obj);

      

       Methodmethod2= clazz.getMethod("setName",String.class);

       System.out.println(method2);

       method2.invoke(obj, "ww");

      

       // 获取所有成员方法,不包括继承的

       clazz.getDeclaredMethods();

       // 获取指定的成员方法

//     clazz.getDeclaredMethod(name,parameterTypes);

 

 

  • 已知ArrayList<Integer>的一个对象,如何实现往集合中添加一个字符串数据?

package cn.itcast;

 

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

import java.util.ArrayList;

 

/*

 * 考查对反射原理的理解

 * 反射将泛型进行擦除

 * 反射绕过编译器检查,将不同的数据类型存储到带泛型的集合

 */

publicclassReflectTest {

 

    publicstaticvoid main(String[] args) throws NoSuchMethodException,SecurityException, IllegalAccessException,

           IllegalArgumentException,InvocationTargetException {

       ArrayList<Integer>list= newArrayList<>();

       list.add(0);

       list.add(1);

       list.add(2);

       list.add(3);

 

       // 反射获取ArrayList.class 文件中的add() 方法

       Classclazz= list.getClass();

       Methodmethod= clazz.getMethod("add", Object.class);

       method.invoke(list, "itcast");

 

       System.out.println(list);

    }

 

}

 


你可能感兴趣的:(反射,单例设计模式,网络编程)