一、反射
通过一个实例化对象映射到类,在程序运行期间就可以获取类的信息,进行相关操作。
1.1 Class类
Class类是反射的基础
用一个对象来表示某个类的信息,通过Class类来创建
Class是专门用来描述其他类的类,每一个Class对象都是对某个类的具体描述
- 调用forName方法
- 通过目标类的类字面量获取
- 通过目标类的实例化对象获取
java
public class Test7 {
public static void main(String[] args) throws Exception{
/**
* 反射的三种方法
*/
//forName()
Class clazz1 = Class.forName("User");
System.out.println(clazz1);
//类字面量
Class clazz2 = User.class;
System.out.println(clazz2);
//实例化对象
User user = new User(1,"dyz");
Class clazz3 = user.getClass();
System.out.println(clazz3);
System.out.println(clazz1 == clazz2);
System.out.println(clazz2 == clazz3);
}
}

上述3种方式获取的Class对象都是同一个,因为每个类在内存中只有一份,对应的对象(描述内部结构的对象)也只有一份。(类就只有一个)
1.2 反射的常见方法
|----------------------------------------------------------|------------------------------------|
| 方法 | 描述 |
| public boolean isInterface() | 判断类是否为接口 |
| public boolean isArray() | 判断类是否为数组 |
| public boolean isAnnotation() | 判断类是否为注解 |
| public String getName() | 获取类名 |
| public ClassLoader getClassLoader() | 获取类加载器 |
| public Class getSuperclass() | 获取类的父类 |
| pubic Package getPackage() | 获取类所在的包 |
| public String getPackageName() | 获取类所在的包名 |
| public Class\[\] getInterfaces() | 获取类的接口 |
| public int getModifiers() | 获取类的访问权限修饰符 |
| public Field\[\] getFileds() | 获取类的全部公有成员变量,包括继承父类和自定义的 |
| public Field\[\] getDeclareFields() | 获取类的自定义成员变量 |
| public Field\[\] getField(String name) | 通过名称获取类的公有成员变量(public),包括继承父类和自定义的 |
| public Field\[\] getDeclareField(String name) | 通过名称获取类的自定义成员变量(自己定义的) |
| public Method\[\] getMethods() | 获取类的全部公有方法(public),包括继承父类和自定义的 |
| public Method\[\] getDeclaredMethods() | 获取类的自定义方法(自己定义的方法) |
| public Method getMethod(String name,Class...pars) | 通过名称和参数信息获取类的公有方法,包括继承父类和自定义的 |
| public Method getDeclareMethod(String name,Class.. pars) | 通过名称和参数信息获取类的自定义方法 |
| public Constructor\[\] getConstructors() | 获取类的全部公有构造器 |
| public Constructor\[\] getDeclareConstructors() | 获取类的全部构造器 |
| public Constructor getConstructor(Class... pars) | 通过参数信息获取类的公有构造器 |
| public Constructor getDeclareConstructor(Class... pars) | 通过参数信息获取类的构造器 |
了解:
java
package com.xlh;
import java.io.*;
public class Test {
public static void main(String[] args) throws Exception{
Class clazz1 = Class.forName("com.xlh.User");
System.out.println(clazz1); //class com.xlh.User
System.out.println(clazz1.isInterface()); //判断是否为接口 false
System.out.println(clazz1.isArray()); //判断是否为数组 false
System.out.println(clazz1.isAnnotation()); //判断是否为注解 false
System.out.println(clazz1.getName());//获取类名 com.xlh.User
System.out.println(clazz1.getClassLoader());//获取类加载器 jdk.internal.loader.ClassLoaders$AppClassLoader@1f89ab83
System.out.println(clazz1.getSuperclass());//获取父类 Object
System.out.println(clazz1.getPackage());//获取类所在的包 package com.xlh
System.out.println(clazz1.getPackageName());//获取类所在的包名 com.xlh
Class[] interfaces = clazz1.getInterfaces(); //获取类的接口
for (Class aclazz : interfaces){
System.out.println(aclazz); //interface java.io.Serializable
}
int modifiers = clazz1.getModifiers();
System.out.println(modifiers); //获取类的访问权限修饰符 返回1,因为只有public
}
}
实际开发中常用:
java
Class clazz = Class.forName("com.xlh.User");
Field[] fields = clazz.getFields();
for (Field field: fields){
System.out.println(field); //类的所有公有成员变量,包括父类和自定义的 public int com.xlh.People.id public java.lang.String com.xlh.People.name
}
Field[] declaredFields = clazz.getDeclaredFields();
for (Field declareField : declaredFields){
System.out.println(declareField); //获取自己的所有属性 不管公有还是私有 private int com.xlh.User.id private java.lang.String com.xlh.User.name
}
System.out.println(clazz.getField("id"));//拿到的是People中的id,User中的id和name是private 拿不到
System.out.println(clazz.getDeclaredField("id"));//拿去自己的属性 不管公有还是私有 获取的是User中的id
二、反射的应用
java
package test;
public class Student {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("学生信息");
System.out.println("ID:" + this.id);
System.out.println("姓名:" + this.name);
}
public int test(int num,int num1){
return num+num1;
}
}
2.1 反射调用方法
java
package test;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws Exception{
Student student = new Student();
student.setId(1);
student.setName("dyz");
//常规调用
student.show();
//反射调用:操作方法
Class clazz = Student.class;
Method show = clazz.getMethod("show", null);
show.invoke(student,null);
Method method = clazz.getMethod("test", int.class,int.class);
Object invoke = method.invoke(student, 1, 2);
System.out.println(invoke);
}
}

2.2 反射访问成员变量
java
package test;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws Exception {
Class clazz = Student.class;
Field[] declaredFields = clazz.getDeclaredFields();
for (Field declaredField : declaredFields){
int modifiers = declaredField.getModifiers();
Class<?> type = declaredField.getType();
String name = declaredField.getName();
System.out.println("成员变量" + name + "的数据类型是:" + type + "访问权限是:" + getModifiers(modifiers));
}
}
public static String getModifiers(int modifiers){
String result = null;
switch (modifiers){
case 0:
result="";
break;
case 1:
result ="public";
break;
case 2:
result= "private";
break;
case 3:
result= "protected";
break;
}
return result;
}
}

2.3 反射调用构造器
私有方法不能访问,通过访问公有方法反射私有属性。
java
package test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws Exception {
Class clazz = Student.class;
Constructor<Student> constructor = clazz.getConstructor(); //获取无参构造器,不传参数
Student student = constructor.newInstance(); //创建实例
Method setId = clazz.getMethod("setId", int.class);
setId.invoke(student,1);
Method getId = clazz.getMethod("getId", null);
System.out.println(getId.invoke(student));
}
}

三、网络编程
如何使用Java开发基于web的应用
3.1 IP和端口
IP:互联网中每台终端设备都有一个唯一标识,网络中的请求可以根据这个标识找到具体的终端,这个唯一标识就是IP。
端口:8080、3306
3.2 TCP协议
TCP协议面向连接的运输层协议,比较复杂,安全但效率低,使用TCP协议前必须先建立连接,才能传输数据,数据传输完毕后释放连接。
3.2.1 ServerScoket
|---------------------------------------------------------------|------------------------|
| 方法 | 解释 |
| public ServerSocket(int port) | 根据端口创建ServerSocket对象 |
| public ServerSocket(int port,int backlog,InetAddress address) | 根据端口、backlog 、IP地址创建对象 |
| public Socket accpept() | 等待客户端请求,返回Socket对象 |
| public void close() | 关闭ServerSocket |
3.2.2 Socket
|------------------------------------------|-----------------------|
| 方法 | 解释 |
| public Socket(String host,int port) | 根据主机、端口创建要连接的Socket对象 |
| public Socket(InetAddress host,int port) | 根据IP、端口创建要连接的Socket对象 |
| public InputStream getInputStream() | 获取Socket输入流 |
| public synchronized void close() | 关闭Socket |
java
package test;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws Exception{
ServerSocket serverSocket = null;
Socket socket = null;
InputStream inputStream = null;
OutputStream outputStream = null;
DataInputStream dataInputStream = null;
DataOutputStream dataOutputStream = null;
serverSocket = new ServerSocket(8080);
System.out.println("服务器端已启动,等待接收");
Socket accept = serverSocket.accept();
// System.out.println(accept);
inputStream = accept.getInputStream();
dataInputStream = new DataInputStream(inputStream);
String request = dataInputStream.readUTF();
System.out.println("接收到了客户端请求" + request);
String response = "Hello Word";
outputStream = accept.getOutputStream();
dataOutputStream = new DataOutputStream(outputStream);
dataOutputStream.writeUTF(response);
System.out.println("给客户端做出回应" + response);
//关闭
accept.close();
serverSocket.close();
inputStream.close();;
outputStream.close();
dataOutputStream.close();
dataInputStream.close();
}
}
java
package test;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws Exception{
Socket socket = null;
InputStream inputStream = null;
OutputStream outputStream = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
socket = new Socket("127.0.0.1",8080);
System.out.println("客户端接收");
System.out.println(socket);
//给服务器发消息
String msg = "你好呀!";
System.out.println("客户端说:" + msg);
outputStream = socket.getOutputStream();
dataOutputStream = new DataOutputStream(outputStream);
dataOutputStream.writeUTF(msg);
//接收服务器发来的消息
inputStream = socket.getInputStream();
dataInputStream = new DataInputStream(inputStream);
String s = dataInputStream.readUTF();
System.out.println("服务器响应" + s);
//关闭
socket.close();
inputStream.close();
outputStream.close();
dataOutputStream.close();
dataInputStream.close();
}
}


3.3 UDP协议
TCP优点是稳定安全,缺点是效率低,UDP恰好相反,优点是效率高,缺点是不安全。
3.3.1 DatagramSocket
|-----------------------------------------------|------------------------|
| 方法 | 描述 |
| public DatagramSocket(int port) | 根据端口创建DatagramSocket对象 |
| public void send(DatagramPacket p) | 发送数据包 |
| public synchronized receive(DatagramPacket p) | 接收数据包 |
3.3.2 DatagramPacket
|-----------------------------------------------------------------------------|----------------------------------------|
| 方法 | 描述 |
| public DatagramPacket(byte buf\[\],int length,InetAddress address,int port) | 根据发送的数据、数据长度、IP地址、端口创建DatagramPacket对象 |
| public synchronized byte\[\] getData() | 获取接收的数据 |
| public synchronized int getLength() | 获取数据长度 |
| public synchronized int getPort() | 获取发送数据的Socket端口 |
java
package test;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketAddress;
public class TerminalA {
public static void main(String[] args) throws Exception{
byte[] buff = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(buff, buff.length);
DatagramSocket datagramSocket = new DatagramSocket(8081);
datagramSocket.receive(datagramPacket);
String message = new String(datagramPacket.getData(),0,datagramPacket.getLength());
System.out.println("我是TerminalA终端,接收到了" + datagramSocket + "端口" + "传来的数据:" + message);
//回应B
String reply = "我是TerminalA,已经接收到了你传来的数据";
SocketAddress socketAddress = datagramPacket.getSocketAddress();
DatagramPacket datagramPacket1 = new DatagramPacket(reply.getBytes(),reply.getBytes().length,socketAddress);
datagramSocket.send(datagramPacket1);
}
}
java
package test;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
public class TerminalB {
public static void main(String[] args) throws Exception{
String message = "你好,我是TerminalB。";
InetAddress inetAddress = InetAddress.getByName("localhost");
DatagramPacket datagramPacket = new DatagramPacket(message.getBytes(),message.getBytes().length,inetAddress,8081);
DatagramSocket datagramSocket = new DatagramSocket(8080);
datagramSocket.send(datagramPacket);
//接受到A的回应
byte[] bytes = new byte[1024];
DatagramPacket datagramPacket1 = new DatagramPacket(bytes, bytes.length);
datagramSocket.receive(datagramPacket1);
String reply = new String(datagramPacket1.getData(),0,datagramPacket1.getLength());
System.out.println("我是TerminalB,接收到了" + datagramPacket1.getPort() + "发送来的数据" + reply);
}
}


3.4 多线程的网络编程
java
package test;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerThread {
public static void main(String[] args) throws Exception{
ServerSocket serverSocket = new ServerSocket(8080);
System.out.println("服务器启动..");
while(true){
Socket socket = serverSocket.accept();
new Thread(new ServerRunnable(socket)).start();
}
}
}
java
package test;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
public class ServerRunnable implements Runnable{
private Socket socket;
public ServerRunnable(Socket socket) {
this.socket = socket;
}
//input 读入
@Override
public void run() {
InputStream inputStream = null;
DataInputStream dataInputStream = null;
try {
inputStream = this.socket.getInputStream();
dataInputStream = new DataInputStream(inputStream);
String message = dataInputStream.readUTF();
System.out.println(message);
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
dataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
java
package test;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
public class ClientRunnable implements Runnable{
private int num;
public ClientRunnable(int num){
this.num = num;
}
@Override
public void run() {
Socket socket = null;
OutputStream outputStream = null;
DataOutputStream dataOutputStream = null;
try {
socket = new Socket("localhost",8080);
String message = "我是客户端" +this.num;
outputStream = socket.getOutputStream();
dataOutputStream = new DataOutputStream(outputStream);
dataOutputStream.writeUTF(message);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
dataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
java
package test;
public class ClientThread {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(new ClientRunnable(i)).start();
}
}
}

