------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地址
端口:计算机与外界通信交流的出口
知名端口:0~1024;动态端口:1024~65535
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) // 发送数据包
数据报套接字,接收端和发送端程序的编写步骤
接收端:(明确端口:指定端口或随机端口)
调用DatagramSocket(int port)创建一个数据报套接字,并绑定到指定端口
调用DatagramPacket(byte[] buf,int length),建立一个字节数组以接收UDP包
调用DatagramSocket类的receive()方法,接收UDP包
最后关闭数据报套接字
发送端:(不需指定端口)
调用DatagramSocket()创建一个数据报套接字
调用DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port),建立要发送的UDP包
调用DatagramSocket类的send()方法,发送UDP包
最后关闭数据报套接字
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通信的编写步骤
服务器端的编写流程:
指定本地端口号,创建ServerSocket对象,监听指定端口的 Socket 连接
使用 ss 对象的accept()方法,接收的客户端连接请求,返回Socket 对象
获取Socket对象的输入/输出流
接收数据,处理数据,回传数据
关闭流和 Socket,关闭 ServerSocket
客户端的编写流程
1. 指定要连接的 IP 地址和端口号,创建Socket对象
2. 获取 socket 对象的输入/输出流
3. 读写字节流数据
4. 关闭流,关闭 Socket
客户端与服务端通信模型如下:
1. 服务端创建ServerSocket
2. 通过调用ServerSocket的accept方法监听客户端的连接
3. 客户端创建Socket并指定服务端的地址以及端口来建立与服务端的连接
4. 当服务端accept发现客户端连接后,获取对应该客户端的Socket
5. 双方通过Socket分别获取对应的输入与输出流进行数据通讯
6. 通讯结束后关闭连接。
反射 reflection
Java中类的反射是一种自我管理机制,通过反射可实现:
在运行时判断任意一个对象所属的类;
在运行时构造任意一个类的对象;
在运行时判断任意一个类所具有的成员变量和成员方法;
在运行时调用任意一个对象的方法。
类的加载过程:
加载:将.class文件读入内存,并为之创建一个 Class 对象
连接:
验证内部结构
准备静态成员分配内存默认初始化
解析二进制数据中的符号引用 --> 直接引用
初始化:
类初始化时机:
创建实例,访问静态变量,调用静态方法,反射强行加载,初始化子类,运行主类
三种方式获取Class文件对象
// 使用父类方法 getClass 获取
Classclass1= p.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);
}
}