java基础第十七篇之网络编程和装饰者模式
阅读原文时间:2021年09月28日阅读:1

1:网络概述
1.1 网络的发展Net
1964年,美国人---> 阿帕网--->以太网Internet
1.2 网络的通信协议
windows电脑,android手机,Mac平板---》联网 ---->网络协议(一个文档:长度,速率,格式)
--->根据文档来写了一段代码(通信协议)
1.3 通信协议的分类
TCP/IP协议: 是一组协议
TCP:传输控制协议
IP :互联网协议

1.4 TCP/IP的分层

应用层:主要负责应用程序的协议,用来产生和显示数据
HTTP:超文本传输协议(http://www.baidu.com)
FTP :文件传输协议(ftp://192.168.10.82)
DNS : 域名解析: www.baidu.com ---> 192.168.10.82
传输层:主要使网络程序进行通信,保证输出的可靠性
TCP:传输控制协议
UDP:用户数据报协议
网络层:网络层是整个TCP/IP协议的核心,找到对方的主机在哪里
IP : 互联网协议
ICMP:网际控制报文协议(ping www.baidu.com)
链路层:链路层是用于定义物理传输通道,网卡和驱动,用于发送和接收数据

OSI模型:7层模型

1.5 IP地址和端口
要想和一台主机建立联系,必须知道对方主机的IP和端口

IP地址:
在一个网络中,IP地址作为一台主机的唯一标识

IP的地址分类:
IPV4:
xxx.xxx.xxx.xxx :点分十进制 ---->二进制(110100101010)
使用4个字节来描述ip: 1.1.1.1 ---> 255.255.255.255 --->21亿
//网络号 主机号
A类:10.xxx.xxx.xxx 国家级
255.0.0.0
B类:10.10.xxx.xxx 企业级(百度)
255.255.0.0
C类:10.10.10.xxx
255.255.255.0
192.168.164.255 --->路由器 ---- 》电信网关 ---->顺义区192.168.103 --->xxx-?
10.10.10.1 : 网关地址
10.10.10.255 :广播地址

IPV6:
16个字节 128个二进制位 2^128 ----》无限大

端口号:
数据库:3306
ftp: 21
标识一台电脑上唯一的一个进程()
端口号是一个16位的数字(1-65535)
< 1024 系统使用的
1024 - 6000 :系统保留
>6000 :自己使用
8888 9999 12306 10086

ip地址和端口号就可以唯一的表示哪台主机哪个进程

3:InetAddress 类
用来描述电脑的ip和其他信息
//通过某种方式获取InetAddress对象
public static InetAddress getByName(String host) //根据主机名或者网址获取Ip
//在一个局域网内部,主机名和IP地址的作用是一样的
public String getHostName() //获取主机名
public String getHostAddress() //获取IP地址

public static InetAddress getLocalHost() //获取本主机的ip和其他信息

例子:
public class Demo01InetAddress {

public static void main(String[] args) throws UnknownHostException {
// //通过某种方式获取InetAddress对象
// public static InetAddress getByName(String host) //根据主机名或者网址获取Ip
// //在一个局域网内部,主机名和IP地址的作用是一样的
// public String getHostName() //获取主机名
// public String getHostAddress() //获取IP地址

//根据主机名获取InetAddress对象 ---->获取IP
// InetAddress address = InetAddress.getByName("LAPTOP-6F2V5QTF");
// //获取IP
// String ip = address.getHostAddress();
// System.out.println(ip);

//根据网址获取InetAddress对象 ---->获取IP
InetAddress address2 = InetAddress.getByName("www.baidu.com");
//获取IP
String ip2 = address2.getHostAddress();
System.out.println(ip2);

//将一个IP字符串转为Inetaddress对象
InetAddress ip3 = InetAddress.getByName("192.168.164.67");

//public static InetAddress getLocalHost() //获取本主机的ip和其他信息
InetAddress ip4 = InetAddress.getLocalHost();
//获取本电脑的主机名
String hostName = ip4.getHostName();
String ip = ip4.getHostAddress();

System.out.println("主机名:" + hostName);
System.out.println("ip:" + ip);

}

}

4:UDP协议
UDP是一种面向无连接的协议
UDP的通信双方在传输数据之前不需要建立连接,发送端只管发,根本不会关心接收端是否接收
优点: 传输速度快,效率高,实时性强
缺点: 数据容易丢失,不安全
应用场景:直播,视频会议,

5:TCP协议
TCP是一种面向连接的协议:
TCP的双方在通信之前,必须先要建立连接,这个连接被称为三次握手
优点:可以保证数据传输的可靠性,数据无丢失,数据可以超时重传
缺点: 传输速度慢,效率低
应用场景: 对数据的传输质量要求高:金融系统,终端支付,密码管理
6: UDP编程

//发送端
public class Demo01Send {
//1.创建DatagramSockt对象,造一个码头
DatagramSocket ds = new DatagramSocket();

//2.准备要发送的数据
byte[] data = "hello".getBytes();

//3.将你要发送的数据方法在包中
/*
参数1:表示要发送的数据
参数2:表示发送数据的长度
参数3:表示接收端的IP
参数4:表示接受的端口

*/
//将IP字符串转换为InetAddress对象
InetAddress address = InetAddress.getByName("192.168.164.67");
DatagramPacket dp = new DatagramPacket(data, data.length,address,9999(port)
//4:发送数据
ds.send(dp);
//5.关闭资源
ds.close();

/*

第5章总结
5.1知识点总结
IP地址:用来唯一表示我们自己的电脑的,是一个网络标示
端口号: 用来区别当前电脑中的应用程序的
UDP: 传送速度快,但是容易丢数据,如视频聊天,语音聊天
TCP: 传送稳定,不会丢失数据,如文件的上传、下载
UDP程序交互的流程
发送端
1,创建DatagramSocket对象
2,创建DatagramPacket对象,并封装数据
3,发送数据
4,释放流资源
接收端
1,创建DatagramSocket对象
2,创建DatagramPacket对象
3,接收数据存储到DatagramPacket对象中
4,获取DatagramPacket对象的内容
5,释放流资源
TCP程序交互的流程
客户端
1,创建客户端的Socket对象
2,获取Socket的输出流对象
3,写数据给服务器
4,获取Socket的输入流对象
5,使用输入流,读反馈信息
6,关闭流资源
服务器端
1,创建服务器端ServerSocket对象,指定服务器端端口号
2,开启服务器,等待着客户端Socket对象的连接,如有客户端连接,返回客户端的Socket对象
3,通过客户端的Socket对象,获取客户端的输入流,为了实现获取客户端发来的数据
4,通过客户端的输入流,获取流中的数据
5,通过客户端的Socket对象,获取客户端的输出流,为了实现给客户端反馈信息
6,通过客户端的输出流,写数据到流中
7,关闭流资源

*/

/*

}
//接收端

public class Demo02Receive {
public static void main(String[] args) throws IOException {
//1:创建DatagramSocke对象,并指定端口号
DatagramPacket dp = new DatagramPacket(8888);

//2.创建DataramPacket对象指定要接收数据的位置和长度
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes,bytes.length);
System.out.println("接收端在运行")
//3.接收数据
//当没有数据发送过来则呈现阻塞.
ds.receive(dp);
//4.获取接收到的数据
byte[] data = dp.getData();
//获取接收数据的长度
int len = dp.getLength();

//获取发送端的IP
String ip = dp.getAddress().getHostAddress();
System.out.println("ip" + ip + "数据:" + new String(data,0,data.length);
//关闭ziyuan
ds.close();

}
}

public class Demo01Send {
public static void main(String[] args) throws IOException {
//1.创建DatagrameSocket对象,造一个码头
DatagramSocket ds = new DatagramSocket();
Scanne sc = new Scanner(System.in);

while(true) {
//2.装备要发送的数据
System.ou.println("请输入你要发送的数据(exit退出)");
Stringstr= sc.nextLine();

byte[] data = str.getBytes();
//3.将你要发送的数据放在包中
/*

参1:表示要发送的数据
参2:表示发送数据长度
参3:表示接收端的IP
参4:表示接收端的端口

*/

//将IP字符串转为InetAddress对象
InetAddress address = InetAddress.getByName("192.168.164.21");
DatagramPacket dp = new DatagramPacket(data, data.length,address,8888);
//4.发送数据
ds.send(dp);
if(str.equals("exit")) {
break;
}
}
//5.关闭资源
ds.close();

}
}

//UDPde 增强版 接收端
public class Demo02Receive {
public static void main(String[] args) throws IOException {
//1.创建DatagramSocket对象,并指定端口号
DatagramSocket ds = new DatagramSocket(8888);

//2.创建DatagramPacket对象,指定要接收的位置和长度
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes,bytes.length)
System.out.println("接收端正在运行");
while(true) {
//3.接收数据//当没有数据发送过来则程序组阻塞
ds.receive(dp);
//4.获取接收到的数据
byte[] data = dp.getData()

//获取接收数据的长度i
int len = dp.getLength();
//获取发送端的IP
String ip= dp.getAddress().getHoostAdress();

String str= new String(data,9,len);

if(str.equals("exit")) {
break;
}
//将获取的数据转为字符串
System.out.println("ip" + ip + "数据:" + str)

}
//5:关闭资源
ds.close();

}
}

运行: 先运行接收端,再运行发送端

7:TCP编程

//客户端
public class ClientDemo {
public static void main(String[] args) throws Exception {
//创建Socket套接子
Socket socket = new Socket("192.168.164.21",9999);

//程序执行到这里,客户端和服务器已经建立好了连接
//2.客户端要给服务器发送数据
//2.1获取输出流
OutputStream os = socket.getOutputStream();

2.2发送数据
os.write("hello".getBytes());
//3.释放资源
os.close();
socket.close();

}
}

//服务器

public class ServerDemo {
public static void main (String[] args) {
//创建ServerSocket对象,并指定端口号

ServerSocket server = new ServerSocket(9999);

//接收客户端的请求
//已经建立好连接
//通过socket可以获取一切信息
System.out.println("服务器正在等待连接…….");
Socket socket = server.accept();
//3.服务器读取数据
//3.1服务器获取输入流
InputStream is = cSocket.getInputStream();
//3.2读取数据
byte[] bytes= new byte[1024];
int len = is.read(bytes);
//3.3将读取的数据转为字符串
System.out.println("读取数据:" + new String(bytes,0,len));

//4.释放资源
is.close();
socket.close();
server.close();

}
}

//客户端读取图片
public class ClientDemo {
public static void main(String[] args) throws Exception{
//1:创建Socket对象
Socket socket = new Socket("192.168.164.67",10086);

//2:获取文件的输入流
BufferedInoutStream bis = new BufferedInputStream(new FileInputStream("下载.jpg");

//4.从文件的输入流中读取数据并写入套接子的输出流
byte[] bytes = new byte[1024];
int len;
while((len = bis.read(bytes) != -1) {
os.write(bytes, 0 ,len);
}

//5.关闭资源
bis.close();
socket.close();

}

//服务器

public class ServerDemo {
public static void main(String[] args) throws IOException {
//1.创建ServerSocket对象
ServerSocket server = new ServerSocket(10086);
//2.接收请求
Socket socket = server.accpet();

//3.获取文件的输出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("liutao.jpg"));

//4.获取套接子的输入流
InputStream is = socket.getInputStream();
//5.将从套接子输入流读取的数据写入文件的输出流
byte[] bytes = new byte[1024];
ine len;
while((len = is.read(bytes)) != -1) {
bos.write(bytes, 0 , len);
//刷新后可以再
bos.flush();
}
//6.关闭资源
bos.close()
server.close();
socke.class();

}
}

//客户端上传图片优化
public class ClientDemo {
public static void main(String[] args) throws Exception {
//1.创建Socket对象
ocket socket = new Socket("192.168.164.21",1008);

//2.获取文件的输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("刘涛.jpg");
//3.获取套接字的输出流
OutputStream os = socket.getOutputStream();
//4.从文件的输入流中读取数据并写入套接子的输出流
byte[] bytes = new byte[1024];
int len;
while((len = bis.read(bytes)) != -1) {
ow.write(bytes,0,len);
}

//客户端需要关闭输出流
socket.showdownOutput();

//接收服务器的反馈信息
//1.获取套接字的输入流
InputStream is = socket.getInputStream;
//2.读取数据
len = is.read(bytes);

System.out.println(new String(bytes,0,len));

//5.关闭资源
bis.close();
socket.close();

}
}

//服务器(加上反馈信息的图片上传)
public class ServerDemo {
public static void main(String[] args) throws Exception {
//1.创建ServerSocket对象
ServerSocket server = new ServerSocket(10086);

System.out.println("accept之前");
//2.接收请求
Socket socket = socket.accept();
System.out.println("accept之后");

//3.获取文件的输出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("liutao.jpg"));
//4.获取文件的输出流
InputStream is = socket.getInputStream();
//5.将套接子输入流读取的数据写入文件的输出流
byte[] bytes = new byte[1024];
int len;
System.out.println("while 之前");
/*
while循环没有结束,说明read并没有读取到-1
现在是从套接子的输入流读取,读取到-1条件是对方把输出流给关闭了
关闭之后,说明客户已经没有数据要给服务器发送了,这就读取到-1

*/
while((len = is.read(bytes)) != -1) {
bos.write(bytes,0,len);
//刷新
bos.flush();
}
System.out.println("while 之后");
//给客户反馈信息
//获取套接子输出流
OutputStream os = socket.getOutputS();
//把信息发送给客户端
os.write("文件上传成功".getBytes);

//6.关闭资源
bos.cloas();
server.cloase();

}

}

//客户端向服务器传送图片
public class ClientDemo {
public static void main(String[] args) throws Exception {
//1.创建Socket对象
Socket socket = new Socket("192.168.164.21",7799);

//获取文件输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("刘涛.jpg"));

//获取文件输出流
OutputStream os = socket.getOutputStream();

byte[] bytes = new byte[1024];
int len;
while((lne = bis.read(bytes)) != -1) {
os.write(bytes,0,len);
//刷新
os.flush()
}
//关闭用户端的输出流
socket.showdownOutput();

//接收服务器反馈的信息
InputStream is = socket.getInputStream();

len = is.read(bytes);

System.out.peintln(new String(bytes,0,len));
bis.close();
socket.close();

}

}

//服务器用多线程执行并接收的图片进行不同名的处理
public class ServerDemo {
public static void main(String[] args) throws Exception {
ServerSokcet server = new ServerSokcet();

while(true) {
Socket socket = server.accept();

new Thread(new MyRunnable(socket)).start();

}

}
}

public class MyRunnable implements Runnable {
Socket socket;

public MyRunnable() {}

public MyRunnable(Socket socket) {
this.socket = socket;
}

public void run () {
//处理意见建立好的连接
//上传文件的代码
BufferedOutputStream bos = null;

try {
//1.获取套接子的输入流
InputStream is = socket.getInputStream();
String fileName = "D:\\Server\\" + "副本" + System.currentTimeMillis() + ".jpg";
//2.获取文件的输出流
bos = new BufferedOutputStream(new FileOutputStream(fileName));

byte[] bytes = new byte[1024];
ine len;
while((len = is.read(bytes)) != -1) {
bos.write(bytes,0,len);
//刷新
bos.flush();

}
//给客户端反馈信息
OutputStream os = socket.getOutputStream();
os.write("文件上传成功".getBytes());

} catch (Exception e) {
e.printStackeTrace();
} finally {
try {
bos.close();
} catch (Exception o1) {
e1.printSackTrace();
}
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

}

//客户端和服务器进行相互聊天(两个人聊天)

//客户端
public class Client {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("192.168.164.21",8888);

//创建读取线程
Thread tRead = new Thread(new ReadThread(socket));
Thread tWrite = new Thread(new WriteThread(socket));

tRead.start();
tWrite.start();
}
}

public class Server {
public static void main(String[] args) throws Exception {
ServerSocket server = new ServerSokcet(8888);

Socket socket = server.accept();

//创建读取线程
Thread tRead = new Thread(new ReadThread(socket));
Thread tWrite = new Thread(new WriteThread(socket));

tRead.start();
tWrite.start();

}
}

public class ReadThread implements Runnable {
Socket socket;

public ReadThread() {
super();
}

public ReadThread(Socket socket) {
super();
this.socket = socket;
}

public void run () {
try {
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
ine len;
while(true) {
len = is.read(bytes);
String ip = socket.getInetAddress().getHostAddress();
System.out.println("读取数据:" + new String(bytes,0,len));

}
}catch (Exception e) {
e.printStackTrace();
}
}

}

public class WriteThread implements Runnable {
Socket socket;
public WriteThread() {
super();
}

public WriteThread(Socket sokcet) {
super();
this.socket = socket;
}

public void run () {
Scanner sc = new Scanner(System.in);
//写数据
try {
OutputStream os = socket.getOutputStream();
while(true) {
System.out.println("请输入要发送的数据:");
String str = sc.nextLine();
os.write(str.getBytes());
}
}catch (Exception e) {
e.printStackTrace();
}

}
}

//类的序列号(客户端)

//学生类
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
public Student() {
super();
}
public Student(String name;int age) {
super();
this.name = name;
this.age = age;

}

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}

}

//客户端
public class Client {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("192.168.164.67",8888);

Student stu = new Student("刘涛",35);
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());

oos.writeObject(stu);
}
}

//服务器

public class Server {
public static void main(String[] args) {
ServerSocket server = new ServerSocket(8888);

Socket socket = server.accept();

ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());

Student stu = (Student)ois.readObject();

System.out.println(stu.getName() + "\t" + stu.getAge());

}
}

//文件上传 服务器端

public class TCPServer {
public static void main(String[] args) {
//1.创建服务器,等待客户端连接
ServerSocket server = new ServerSocket();
//2.实现多个客户端连接服务器的操作
while(true) {
final Socket socket = server.accept();
//启动线程,完成与当前客户端的数据交互过程
new Thread() {
public void run() {
try {
//显示那个客户端Socket连接上了服务器
//得到IP地址对象
InetAddress ipObject = InetAddress.getInetAddress();
//得到ip地址字符串
String ip = ipObject.getHostAddress();
System.out.println("连接的ip是:" + ip);

//7.获取Socket的输入流
InputStream in = socket.getInputStream();
//8.创建目的地的字节输出流(D:\\upload\\192.168.74.58(1).jpg
BufferedOutputStream fileOut = new BufferedOutputStream(new FileOutputStream("D:\\upload\\" + ip + "(" + System.currenTimeMillis() + ").jpg"));
//9.把Socket输入流中的数据,写入目的地的字节输出流中
byte[] buffer = new byte[1024];
int len = -1;
while((len = in.read(buffer)) != -1) {
//写入目的地的字节输出流中
fileOut.write(buffer,0,len);
}
//--反馈信息--
//10.获取Socket的输出流,作用:写反馈信息给客户端
OutputStream out = socket.getOutputStream();
//11.写反馈信息给客户端
out.wirte("图片上传成功".getBytes);

out.close();
fileout.cloas();
in.close();
socket.close();

} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
//server.cloae();
}
}

//上传文件 客户端
public void shutdownOutput() 禁用此Socket的输出流,间接的相当于告知了服务器数据写入完毕

public class TCPClient {
public static void main(String[] args) throws Exception {
//2.创建客户端Socket,连接服务器
Socket socket = new Socket("192.168.164.21",8888);
//3.获取Socket 流中的输出流,功能:用来把数据写到服务器
outputStream out = socket.getOutputStream();
//4.创建字节输入流,功能:用来读取数据源(图片)的字节
BufferedInputStream fileIn = new BufferedInputStream(new FileInputStream("D:\\NoDir\\test.jpg"));

//5.把图片数据写到Socket的输出流中(把数据传到服务器)
byte[] buffer = new byte[1024];
int len = -1;
while((len = fileln.read(buffer)) != -1) {
//把输入写到Socket的输出流中
out.write(buffer,0,len);
}
//6.客户端发送数据完毕,结束Socket输出流的写入操作,告知服务器
socket.shutdownOutput();

//--反馈信息--
//12.获取Socket的输入流 作用:读反馈信息
InputStream in = socket.getInputStream();
//13.读反馈信息
byte[] info = new byte[1024];
//把反馈信息存储到info数组中,并记录字节个数
int length = in.read(info);
//显示反馈结果
System.out.println(new String(info,0,len));
//关闭流
in.close();
fileIn.close();
out.close();
socket.close();

}
}

IP地址:用来唯一表示我们自己的电脑的,是一个网络标示
端口号: 用来区别当前电脑中的应用程序的
UDP: 传送速度快,但是容易丢数据,如视频聊天,语音聊天
TCP: 传送稳定,不会丢失数据,如文件的上传、下载
UDP程序交互的流程
发送端
1,创建DatagramSocket对象
2,创建DatagramPacket对象,并封装数据
3,发送数据
4,释放流资源
接收端
1,创建DatagramSocket对象
2,创建DatagramPacket对象
3,接收数据存储到DatagramPacket对象中
4,获取DatagramPacket对象的内容
5,释放流资源
TCP程序交互的流程
客户端
1,创建客户端的Socket对象
2,获取Socket的输出流对象
3,写数据给服务器
4,获取Socket的输入流对象
5,使用输入流,读反馈信息
6,关闭流资源
服务器端
1,创建服务器端ServerSocket对象,指定服务器端端口号
2,开启服务器,等待着客户端Socket对象的连接,如有客户端连接,返回客户端的Socket对象
3,通过客户端的Socket对象,获取客户端的输入流,为了实现获取客户端发来的数据
4,通过客户端的输入流,获取流中的数据
5,通过客户端的Socket对象,获取客户端的输出流,为了实现给客户端反馈信息
6,通过客户端的输出流,写数据到流中
7,关闭流资源

反射:

1:类的加载
当我们第一次使用一个类,系统会做两件事情:
1:将该类的字节码文件(.class)文件加载到内存
2: 系统还会为该字节码文件创建一个对象:Class对象
a.txt hello.java D://lesson//a.txt ---->FIle类
a.class Hello.class Demo.class ---->Class类

2:一个类什么时候被加载
1. 创建类的实例
2. 类的静态变量,或者为静态变量赋值
3. 类的静态方法
4. 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
5. 初始化某个类的子类
6. 直接使用java.exe命令来运行某个主类

3:反射的作用
1:反射可以让我们在编译的时候使用一个不存在的或者以后才能存在类
2:反射可以访问一个类的私有成员 MD5算法
3: 通过反射,我们写一些通用代码

4:反射的步骤
1:获取类的Class对象 //一个类在内存中只有一个Class对象
2:通过Class对象获取类的成员(构造方法,成员变量,成员方法)
3:访问这些变量和方法

package pack01_reflect;

import java.util.Scanner;

public class Demo01GetClass {

public static void main(String[] args) throws ClassNotFoundException {
//获取一个类的Class对象

//1:通过类名来获取Class对象
Class clazz1 = Student.class;

//2: 通过类的对象获取
Student stu = new Student();
Class clazz2 = stu.getClass();

//一个类在内存中只有一个Class对象
System.out.println(clazz1 == clazz2);

//3:通过类的全名来获取
Class clazz3 = Class.forName("pack01_reflect.Student");
}

}

单词:
Class类
 Constructor 构造
 Method 方法
 Field 字段
 instance 实例
 invoke 执行

5:通过Class获取类的成员
1:获取类的构造方法
a:获取所有的构造
public Constructor[] getConstructors() //只能获取public修饰的构造
public Constructor[] getDeclaredConstructors() //可以获取所有的构造(包括私有)

package pack02_reflect;

import java.lang.reflect.Constructor;

public class Demo01GetConstructor {

public static void main(String[] args) throws ClassNotFoundException {
//1:获取类的Class对象
Class clazz = Class.forName("pack02_reflect.Student");

//2:获取类中所有的构造方法
// public Constructor[] getConstructors() //只能获取public修饰的构造
// public Constructor[] getDeclaredConstructors() //可以获取所有的构造(包括私有)
// Constructor[] constructors = clazz.getConstructors();
// for (Constructor constructor : constructors) {
// System.out.println(constructor);
// }

//构造方法的获取顺序和方法的定义顺序不一定一致
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
for (Constructor constructor : declaredConstructors) {
System.out.println(constructor);
}

}

}

b:获取单个的构造
public Constructor getConstructor(Class… parameterTypes)
public Constructor getDeclaredConstructor(Class… parameterTypes)

package pack02_reflect;

import java.lang.reflect.Constructor;

public class Demo02GetConstructor {

public static void main(String[] args) throws Exception{
//1:获取类的Class对象
Class clazz = Class.forName("pack02_reflect.Student");
//2:获取单个的构造(无参构造)
Constructor constructor = clazz.getConstructor();
//3:通过获取的构造来创建对象
Object obj = constructor.newInstance();

//4:通过对象调用方法
Student stu = (Student)obj;
stu.study();

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

//获取类的有参构造
Constructor constructor2 = clazz.getConstructor(String.class, int.class);

//通过构造创建对象:给方法传实际的参数
Object obj2 = constructor2.newInstance("刘涛", 35);

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

}

}

package pack02_reflect;

import java.lang.reflect.Constructor;

public class Demo03GetConstructor {

public static void main(String[] args) throws Exception{
//通过无参构造创建对象的简化写法
//1:获取类的Class对象
Class clazz = Class.forName("pack02_reflect.Student");
//2:获取单个的构造(无参构造)
// Constructor constructor = clazz.getConstructor();
//3:通过获取的构造来创建对象
// Object obj = constructor.newInstance();

Object obj = clazz.newInstance();
//4:通过对象调用方法
Student stu = (Student)obj;
stu.study();
}

}

2:获取成员方法
a:获取所有的成员方法
public Method[] getMethods()
public Method[] getDeclaredMethods()

import java.lang.reflect.Method;

public class Demo01GetMethod {

public static void main(String[] args) throws ClassNotFoundException {
//1:获取类的Class对象
Class clazz = Class.forName("pack02_reflect.Student");

//2:获取所有的方法
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println(method.getReturnType()+" "+method.getName());
}
}

}

b:获取单个的成员方法
public Method getMethod(String name, Class… parameterTypes)
public Method getDeclaredMethod(String name, Class… parameterTypes)

package pack03_reflect;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Demo03GetMethod {

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
//1:获取类的Class对象
Class clazz = Class.forName("pack03_reflect.Student");

Object obj = clazz.newInstance();
//2: 获取有参数的构造
/*
* 参1: 表示方法的名字
* 参2:方法形参类型的Class对象
*/
Method method = clazz.getMethod("add", int.class,int.class);

//3:调用方法
Object result = method.invoke(obj, 10,20);

int sum = (Integer)result;

System.out.println("sum = " + sum);
}

}

4:获取成员变量
a:获取所有的成员变量
public Field[] getFields()
public Field[] getDeclaredFields()

package pack04_reflect;

import java.lang.reflect.Field;

public class Demo01GetField {

public static void main(String[] args) throws Exception{
//1:创建Class对象
Class clazz = Class.forName("pack04_reflect.Student");

Object obj = clazz.newInstance();
//2:获取成员变量
//参数:变量的名字
Field field1 = clazz.getDeclaredField("name");
Field field2 = clazz.getDeclaredField("age");

//给变量设置暴力访问
field1.setAccessible(true);
field2.setAccessible(true);
//3:给变量赋值
//将obj对象的name变量赋值为柳岩
field1.set(obj, "柳岩");
field2.set(obj, 35);

//获取obj的name变量的值
String name = (String)field1.get(obj);
//获取obj的age变量的值
int age = (Integer)field2.get(obj);

// Student stu = (Student)obj;
// System.out.println(stu.getName() + " "+ stu.getAge());
}

}

b:获取单个成员变量
public Field getField(String name)
public Field getDeclaredField(String name)

//1:获取类的Class对象
Class clazz = Class.forName("pack02_reflect.Student");

//创建对象
Object obj = clazz.newInstance();
//2: 获取单个的成员方法
Method method = clazz.getMethod("study");

//3:调用获取的方法
//参1:表示这个方法由哪个对象来调用
method.invoke(obj);

//暴力访问私有方法
package pack03_reflect;

import java.lang.reflect.Method;

public class Demo04GetMethod {

public static void main(String[] args)
throws Exception {
// 1:获取类的Class对象
Class clazz = Class.forName("pack03_reflect.Student");

Object obj = clazz.newInstance();

//获取私有方法
Method method = clazz.getDeclaredMethod("eat");
//对于私有的成员,必须设置暴力访问
method.setAccessible(true);
method.invoke(obj);

}

}

注意:
例题1:
package pack04_reflect;

import java.lang.reflect.Field;

public class Demo02GetFieldStatic {

public static void main(String[] args) throws Exception{
Class clazz = Class.forName("pack04_reflect.Student");

Field field = clazz.getDeclaredField("classId");
field.setAccessible(true);
//静态的变量反射不需要对象,直接写null
// field.set(null, "黑马66期");

field.set(null, "黑马66期");
System.out.println(Student.getClassId());

}

}

例题2:反射静态方法

package pack04_reflect;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Demo03GetFieldStatic {

public static void main(String[] args) throws Exception{
Class clazz = Class.forName("pack04_reflect.Student");

//反射静态方法
Method method = clazz.getMethod("sleep");
//静态方法调用的时候不需要对象即可
method.invoke(null);

}

}

案例:把文件中的键值,键是方法,值是参数,进行反射调用

package pack05_test;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
import java.util.Set;

public class Demo01Test {

public static void main(String[] args) throws Exception {
// 1:从文件中将键值对读取到Properties集合
// 1.1:创建Properties对象
Properties prop = new Properties();
// 1.2读取数据
prop.load(new FileReader("info.txt"));

// 2:反射
// 2.1 获取类的Class对象
Class clazz = Class.forName("pack05_test.User");
// 2.2 创建对象
Object obj = clazz.newInstance();
// 3:遍历集合
Set set = prop.stringPropertyNames();
for (String key : set) { // uid username password
// 将获取的键拼接成方法的名字 setUid setUsername setPassword
String methodName = "set" + key.substring(0, 1).toUpperCase() + key.substring(1);
// 反射以上获取的方法
Method method = clazz.getMethod(methodName, String.class);
// 获取Properties的值
String value = prop.getProperty(key);
// 调用方法
method.invoke(obj, value);
}

System.out.println(obj);
}

}

//把类全名和方法以键值对的方式放在txt文件中,在进行读取调用方法

package pack05_test;

import java.io.FileReader;
import java.lang.reflect.Method;
import java.util.Properties;

public class Demo02Test {

public static void main(String[] args) throws Exception {
Properties prop = new Properties();

prop.load(new FileReader("config.txt"));

// 从prop集合中获取信息
// 1:获取类的全名
String className = prop.getProperty("className");
// 2:获取类的方法名
String methodName = prop.getProperty("methodName");

// 3:反射
// 3.1 创建类的Class对象
Class clazz = Class.forName(className);
// 3.2 创建对象
Object obj = clazz.newInstance();
// 3.3 获取方法
Method method = clazz.getMethod(methodName);
// 3.4 调用方法
method.invoke(obj);
}

}

案例:
//通用工具
package pack05_test;

import java.lang.reflect.Field;

public class Demo03Test {
//将obj对象的name变量赋值为value 对象 变量名 值
public static void setVariable(Object obj, String name, Object value) throws NoSuchFieldException, SecurityException,
IllegalArgumentException, IllegalAccessException{
Class clazz = obj.getClass();
Field field = clazz.getDeclaredField(name);
//设置暴力访问
field.setAccessible(true);
//将obj对象的name变量设置为value
field.set(obj, value);
}
public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException,
IllegalAccessException {
Student stu = new Student();
setVariable(stu, "name", "刘涛");
setVariable(stu, "age", 35);

System.out.println(stu);

System.out.println("-----------------");
User user = new User();

setVariable(user, "uid", "it001");
setVariable(user, "username", "lft");
setVariable(user, "password", "123");

System.out.println(user);
}

}

反射案例:变参方法

package pack06_kuozhan;

import java.lang.reflect.Method;

public class Demo01Test {
public void func1(String[] array){
System.out.println("数组长度:"+array.length);
}

public void func2(String… array){
System.out.println("数组长度:"+array.length);
}
public static void main(String[] args) throws Exception {

Class clazz = Class.forName("pack06_kuozhan.Demo01Test");
Object obj = clazz.newInstance();
Method method = clazz.getMethod("func2", String[].class);

// method.invoke(obj, new String[]{"hello","world"}); //"hello","world"
// method.invoke(obj, "hello","world");
method.invoke(obj, new Object[]{new String[]{"hello","world"}}); ///new String[]{"hello","world"}

}

装饰设计模式:例题1

package pack06_kuozhan;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

//装饰模式

abstract class Person{
public abstract void eat();
}

class Student extends Person{
String name;

public Student() {
super();
// TODO Auto-generated constructor stub
}

public Student(String name) {
super();
this.name = name;
}

@Override
public void eat() {
System.out.println(name + "学生食堂吃饭");
}

}
class Worker extends Person{

@Override
public void eat() {
System.out.println("工人工地吃饭");
}

}
class BufferedPerson{
Person p;

public BufferedPerson() {
}

public BufferedPerson(Person p) {
this.p = p;
}
public void superEat(){
System.out.println("来一杯");
p.eat();
System.out.println("抽一根");
}
}

public class Demo02Test {

public static void main(String[] args) throws FileNotFoundException {

BufferedPerson bufp = new BufferedPerson(new Student("刘涛"));
bufp.superEat();

// BufferedReader bufr = new BufferedReader(new FileReader("a.txt")); //read
// readLine();
}

}

}

//案例:在给定泛型的集合中添加,任意类型

package pack05_test;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

public class Demo04Test {

public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
ArrayList list = new ArrayList();

list.add(23);
list.add(35);
list.add(29);
// list.add("hello");

//请用所学知识在集合中添加字符
//ArrayList.java ----> ArrayList.class --->Class对象

//绕过编译器直接访问ArrayList的class文件
Class clazz = list.getClass();
//通过反射获取add方法
Method method = clazz.getMethod("add", Object.class);
//调用方法
//此刻实际上是在调用Arraylist的add方法
method.invoke(list, "hello");
method.invoke(list, true);
method.invoke(list, 12.34);

System.out.println(list);

}

}

注意:在现实编程中有的方法或者变量会加密的,不让你进行反射,而让你反射的则不会加密.

例题:在方法里面的可变参数,可以传一个二维数组

package comitheaim_02;

import java.lang.reflect.Method;

public class Test6 {
public void func1 (String[] array) {
System.out.println("数组长度:" + array.length);
}

public void func2 (String…array) {
System.out.println("数组长度:" + array.length);
}

public void func3(String[][]…array) {
System.out.println("数组长度:" + array.length);
}

public static void main(String[] args) throws Exception {
Class clazz = Class.forName("comitheaim_02.Test6");
Object obj = clazz.newInstance();

Method m1 = clazz.getMethod("func1", String[].class);
Method m = clazz.getMethod("func2", String[].class);
Method m2 = clazz.getMethod("func3", String[][][].class);

//m2.invoke(obj, new Object[]{new Object[] {new String[]{"在哪","在的","咋你就好","是的"}},});

//它会把数组分开分别参数里面的数组,但是拆开以后是字符和数组不匹配,所有数组里面在放数组,这样它拆了换是数组,这样就可以赋值了.
m.invoke(obj, new Object[]{new String[]{"hello","world"}});

m1.invoke(obj, new Object[]{new String[]{"hello","world","java"}});

String[] str1 = {"a","b"};
String[] str2 = {"b","c"};

String[][] strs = {str1,str2};
//m2.invoke(obj, strs);

String[] str3 = {"d","j"};
String[] str4 = {"r","g"};
String[][] strss = {str3,str4};

//Object[] ob = {strs,strss};

String[][][] s1 = {strs,strss};

//m2.invoke(obj, new Object[]{strs,strss});
m2.invoke(obj, new Object[]{s1});
//m2.invoke(obj, new Object[]{new String[][]{new String[]{"hello","world"},new String[]{"你好","在吗"}},});

}
}