------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);
}
}