当前位置: 首页 > news >正文

网络编程 反射【详解】 | Java 学习日志 | 第 15 天

        网络编程

        常见架构BS(Browser Service)和 CS(Client Service)。

        BS浏览器服务端模式需要开发客户端,适合移动互联网应用,可以在任何地方随时访问的系统。

        CS客户端服务模式需要开发客户端,适合定制专业化的办公类软件。

        1.网络编程三要素

        网络编程三要素:IP、端口号、协议。

        IP,设备在网络中的地址,是唯一标识。

        端口号,应用程序在设备中的唯一标识

        协议,计算机网络中,数据在网络中传输的规则被称为网络通信协议,,常见的协议有UDP,TCP,HTTP,HTTPS,FTP

        1.1IP

        IP地址分为两大类
IPv4:是给每个连接在网络上的主机分配一个32bit地址。按照TCP/IP规定,IP地址用二进制来表示,每个IP地址长32bit,也就是4个字节。例如一个采用二进制形式的IP地址是“11000000 10101000 00000001 01000010”,这么长的地址,处理起来也太费劲了。为了方便使用,IP地址经常被写成十进制的形式,中间使用符号“.”分隔不同的字节。于是,上面的IP地址可以表示为“192.168.1.66”。IP地址的这种表示法叫做“点分十进制表示法”,这显然比1和0容易记忆得多
IPv6:由于互联网的蓬勃发展,IP地址的需求量愈来愈大,但是网络地址资源有限,使得IP的分配越发紧张。为了扩大地址空间,通过IPv6重新定义地址空间,采用128位地址长度,每16个字节一组,分成8组十六进制数,这样就解决了网络地址资源数量不够的问题

        目前IPv4已经分配完了,利用局域网IP解决IP不够的问题。

特殊IP地址:
127.0.0.1:是回送地址,可以代表本机地址,一般用来测试使用

        DOS常用命令:
ipconfig:查看本机IP地址
ping IP地址(网址也可以):检查网络是否连通

        InetAddress:此类表示Internet协议(IP)地址

        static InetAddress getByName(String host)  确定主机名称的IP地址。主机名称可以是机器名称,也可以是IP地址
String getHostName()                        获取此IP地址的主机名
String getHostAddress()                     返回文本显示中的IP地址字符串

public static void main(String[] args) throws UnknownHostException {//1.获取InetAddress的对象//IP的对象 一台电脑的对象InetAddress address = InetAddress.getByName("DESKTOP-XXXXX");System.out.println(address);String name = address.getHostName();System.out.println(name);String ip = address.getHostAddress();System.out.println(ip);}

        1.2端口号

        设备上应用程序的唯一标识。

        用两个字节表示的整数,它的取值范围是0~65535。其中,0~1023之间的端口号用于一些知名的网络服务和应用,普通的应用程序需要使用1024以上的端口号。如果端口号被另外一个服务或应用所占用,会导致当前程序启动失败。一个端口号只能被一个应用程序使用。

        2.UDP协议

        UDP协议用户数据报协议(User Datagram Protocol)
UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。
由于使用UDP协议消耗系统资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输
例如视频会议通常采用UDP协议,因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。但是在使用UDP协议传送数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时不建议使用UDP协议

        2.1发送接收数据

        DatagramSocket()  创建数据报套接字并将其绑定到本机地址上的任何可用端口 
DatagramPacket(byte[] buf,int len,InetAddress add,int port) 创建数据包,发送长度为len的数据包到指定主机的指定端口

        void send(DatagramPacket p)    发送数据报包           
void close()                   关闭数据报套接字       

        发送数据。

public static void main(String[] args) throws IOException {//发送数据//1.创建DatagramSocket对象(快递公司)//细节://绑定端口,以后我们就是通过这个端口往外发送//空参:所有可用的端口中随机一个进行使用//有参:指定端口号进行绑定DatagramSocket ds = new DatagramSocket();//2.打包数据String str = "你好";byte[] bytes = str.getBytes();InetAddress address = InetAddress.getByName("127.0.0.1");int port = 10086;DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);//3.发送数据ds.send(dp);//4.释放资源ds.close();}

        void receive(DatagramPacket p)  从此套接字接受数据报包 

        接收数据。ds.receive(dp);会一直等待发送端的数据。

public static void main(String[] args) throws IOException {//1.创建DatagramSocket对象(快递公司)//细节://在接收的时候,一定要绑定端口//而且绑定的端口一定要跟发送的端口保持一致DatagramSocket ds = new DatagramSocket(10086);//2.接收数据包byte[] bytes = new byte[1024];DatagramPacket dp = new DatagramPacket(bytes,bytes.length);//该方法是阻塞的//程序执行到这一步的时候,会在这里死等//等发送端发送消息System.out.println(11111);ds.receive(dp);System.out.println(2222);//3.解析数据包byte[] data = dp.getData();int len = dp.getLength();InetAddress address = dp.getAddress();int port = dp.getPort();System.out.println("接收到数据" + new String(data,0,len));System.out.println("该数据是从" + address + "这台电脑中的" + port + "这个端口发出的");//4.释放资源ds.close();}

        实现聊天室,打开右上方Edit Configurations点击more options点击Allow multiple instances可以同时运行多次放松方中的代码。

        发送方。

public class MyUDP1 {public static void main(String[] args) throws IOException {//发送数据//1.创建DatagramSocket对象(快递公司)//细节://绑定端口,以后我们就是通过这个端口往外发送//空参:所有可用的端口中随机一个进行使用//有参:指定端口号进行绑定DatagramSocket ds = new DatagramSocket();//2.打包数据Scanner sc = new Scanner(System.in);while (true) {String str = sc.nextLine();if (str.equals("b")) {break;}byte[] bytes = str.getBytes();InetAddress address = InetAddress.getByName("127.0.0.1");int port = 10086;DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);//3.发送数据ds.send(dp);}//4.释放资源ds.close();//接收数据}
}

        接收方。

public class MyUDP {public static void main(String[] args) throws IOException {//1.创建DatagramSocket对象(快递公司)//细节://在接收的时候,一定要绑定端口//而且绑定的端口一定要跟发送的端口保持一致DatagramSocket ds = new DatagramSocket(10086);//2.接收数据包byte[] bytes = new byte[1024];DatagramPacket dp = new DatagramPacket(bytes,bytes.length);//该方法是阻塞的//程序执行到这一步的时候,会在这里死等//等发送端发送消息while (true) {ds.receive(dp);//3.解析数据包byte[] data = dp.getData();int len = dp.getLength();InetAddress address = dp.getAddress();int port = dp.getPort();System.out.println("接收到数据" + new String(data,0,len));System.out.println("该数据是从" + address + "这台电脑中的" + port + "这个端口发出的");if(new String(data,0,len).equals("k")) {break;}}//4.释放资源ds.close();}
}

        2.2组播

        UDP的三种通信方式:

        单播,单播用于两个主机之间的端对端通信

        组播,组播用于对一组特定的主机进行通信

        广播,广播用于一个主机对整个局域网上所有主机上的数据通信

        组播地址:224.0.0.0 ~ 29.255.255.255 ,其中224.0.0.0 ~ 224.0.0.255为预留的组播地址。

        广播地址:255.255.255.255

        实现组播,发送法方。

public class MyUDP {public static void main(String[] args) throws IOException {/*组播发送端代码*///创建MulticastSocket对象MulticastSocket ms = new MulticastSocket() ;// 创建DatagramPacket对象String s = "你好,你好!" ;byte[] bytes = s.getBytes();InetAddress address = InetAddress.getByName("224.0.0.1");int port = 10000;DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length, address, port) ;// 调用MulticastSocket发送数据方法发送数据ms.send(datagramPacket);// 释放资源ms.close();}
}

        组内的接收方。

public class MyUDP1 {public static void main(String[] args) throws IOException {/*组播接收端代码*///1. 创建MulticastSocket对象MulticastSocket ms = new MulticastSocket(10000);//2. 将将当前本机,添加到224.0.0.1的这一组当中InetAddress address = InetAddress.getByName("224.0.0.1");ms.joinGroup(address);//3. 创建DatagramPacket数据包对象byte[] bytes = new byte[1024];DatagramPacket dp = new DatagramPacket(bytes, bytes.length);//4. 接收数据ms.receive(dp);//5. 解析数据byte[] data = dp.getData();int len = dp.getLength();String ip = dp.getAddress().getHostAddress();String name = dp.getAddress().getHostName();System.out.println("ip为:" + ip + ",主机名为:" + name + "的人,发送了数据:" + new String(data,0,len));//6. 释放资源ms.close();}
}
public class MyUDP2 {public static void main(String[] args) throws IOException {/*组播接收端代码*///1. 创建MulticastSocket对象MulticastSocket ms = new MulticastSocket(10000);//2. 将将当前本机,添加到224.0.0.1的这一组当中InetAddress address = InetAddress.getByName("224.0.0.1");ms.joinGroup(address);//3. 创建DatagramPacket数据包对象byte[] bytes = new byte[1024];DatagramPacket dp = new DatagramPacket(bytes, bytes.length);//4. 接收数据ms.receive(dp);//5. 解析数据byte[] data = dp.getData();int len = dp.getLength();String ip = dp.getAddress().getHostAddress();String name = dp.getAddress().getHostName();System.out.println("ip为:" + ip + ",主机名为:" + name + "的人,发送了数据:" + new String(data,0,len));//6. 释放资源ms.close();}
}

        3.TCP协议

        传输控制协议 (Transmission Control Protocol)

        TCP协议是面向连接的通信协议,即传输数据之前,在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。

        TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象,通信之前一定哟啊保证连接已建立,通过Socket产生IO流来进行网络通信。

        3.1发送和接收数据

        Java对基于TCP协议的的网络提供了良好的封装,使用Socket对象来代表两端的通信端口,并通过Socket产生IO流来进行网络通信。Java为客户端提供了Socket类,为服务器端提供了ServerSocket类。

        常用方法

        Socket(InetAddress address,int port)  创建流套接字并将其连接到指定IP指定端口号       
Socket(String host, int port)        创建流套接字并将其连接到指定主机上的指定端口号 

        InputStream  getInputStream()  返回此套接字的输入流 
OutputStream getOutputStream()   返回此套接字的输出流 

        这里使用转换流将接收到的字节流数据按字符流读取。

        使用缓冲流读提高效率。

public class MyServer {public static void main(String[] args) throws IOException {//TCP协议,接收数据//1.创建对象ServerSockerServerSocket ss = new ServerSocket(10001);//2.监听客户端的链接Socket socket = ss.accept();//3.从连接通道中获取输入流读取数据InputStream is = socket.getInputStream();//使用转换流转换为字符流InputStreamReader isr = new InputStreamReader(is);//使用缓冲流提高效率BufferedReader br = new BufferedReader(isr);int b;while ((b = br.read()) != -1){System.out.println((char) b);}//4.释放资源socket.close();ss.close();}
public class MyClient {public static void main(String[] args) throws IOException {//TCP协议,发送数据//1.创建Socket对象//细节:在创建对象的同时会连接服务端//      如果连接不上,代码会报错Socket socket = new Socket("127.0.0.1",10001);//2.可以从连接通道中获取输出流OutputStream os = socket.getOutputStream();//写出数据os.write("哈喽".getBytes());//3.释放资源os.close();socket.close();}
}

        3.2三次握手,四次挥手

        在TCP连接中必须要明确客户端与服务器端,由客户端向服务端发出连接请求,每次连接的创建都需要经过“三次握手”。

        三次握手:TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠。

        第一次握手:客户端向服务器端发出连接请求,等待服务器确认。

        第二次握手:服务器端向客户端回送一个响应,通知客户端收到了连接请求。

        第三次握手:客户端再次向服务器端发送确认信息,确认连接。

        完成三次握手,连接建立后,客户端和服务器就可以开始进行数据传输了。由于这种面向连接的特性,TCP协议可以保证传输数据的安全,所以应用十分广泛。例如上传文件、下载文件、浏览网页等。

​        第一次挥手​​:客户端向服务器端发出连接释放请求,等待服务器确认。

        ​​第二次挥手​​:服务器端收到连接释放请求后,向客户端发送响应,表明已经收到释放请求。

        ​​第三次挥手​​:服务器端将所有剩余数据发送完毕后,向客户端发送连接释放请求。

        ​​第四次挥手​​:客户端收到服务器的连接释放请求后,向服务器端发送确认信息,完成连接释放。

        完成四次挥手后,客户端和服务器端的连接完全关闭,终止数据传输。由于TCP协议的这种面向连接的特性,它能够确保数据在传输过程中的完整性和可靠性,因此被广泛应用于各种需要可靠数据传输的场景中。

        反射

        1.概念

        反射允许对成员变量,成员方法和构造方法的信息进行编程访问。

        是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;

        对于任意一个对象,都能够调用它的任意属性和方法;

        这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。

        利用反射创建的对象可以无视修饰符调用类里面的内容。

        可以跟配置文件结合起来使用,把要创建的对象信息和方法写在配置文件中,读取到什么类,就创建什么类的对象,读取到什么方法,就调用什么方法。

        反射都是从class字节码文件中获取的内容。

        需要学习:

        如何获取class字节码文件的对象
利用反射如何获取构造方法(创建对象)
利用反射如何获取成员变量(赋值,获取值)
利用反射如何获取成员方法(运行)

        获取class对象的三种方式:

        Class这个类里面的静态方法forName(“全类名”)(最常用)
通过class属性获取 ,类名.class
通过对象获取字节码文件对象,对象.getClass();

        2.获取构造方法

        Class类中用于获取构造方法的方法
Constructor<?>[] getConstructors()                                返回所有公共构造方法对象的数组
Constructor<?>[] getDeclaredConstructors()                        返回所有构造方法对象的数组
Constructor<T> getConstructor(Class<?>... parameterTypes)         返回单个公共构造方法对象
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回单个构造方法对象
Constructor类中用于创建对象的方法
T newInstance(Object... initargs)                                 根据指定的构造方法创建对象
setAccessible(boolean flag)                                       设置为true,表示取消访问检查

public class Reflect2 {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {//1.获取class 字节码文件对象Class clazz = Class.forName("MyReflect.S.Student");//2.获取构造方法//遍历打印每个构造方法Constructor[] cons1 = clazz.getConstructors();for (Constructor con : cons1) {System.out.println(con);}//遍历包括私有的保护的构造方法System.out.println("declared");Constructor[] cons2 = clazz.getDeclaredConstructors();for (Constructor con : cons2) {System.out.println(con);}//获取单个的空参构造Constructor con1 = clazz.getDeclaredConstructor();System.out.println(con1);Constructor con2 = clazz.getDeclaredConstructor(String.class);System.out.println(con2);Constructor con3 = clazz.getDeclaredConstructor(int.class);System.out.println(con3);Constructor con4 = clazz.getDeclaredConstructor(String.class,int.class);//返回值int表示权限修饰符类型int modifiers = con4.getModifiers();System.out.println(modifiers);//获取方法的参数Parameter[] parameters = con4.getParameters();for (Parameter parameter : parameters) {System.out.println(parameter);}//由于con4是private的 暴力反射:表示临时取消权限校验con4.setAccessible(true);Student stu = (Student) con4.newInstance("张三", 23);System.out.println(stu);}
}
package MyReflect.S;public class Student {private String name;private int age;public String gender;public Student() {}public Student(String name) {this.name = name;}protected Student(int age) {this.age = age;}private Student(String name, int age) {this.name = name;this.age = age;}public Student(String name, int age, String gender) {this.name = name;this.age = age;this.gender = gender;}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 String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", gender='" + gender + '\'' +'}';}
}

        3.获取成员变量

         Class类中用于获取成员变量的方法
Field[] getFields():                返回所有公共成员变量对象的数组
Field[] getDeclaredFields():        返回所有成员变量对象的数组
Field getField(String name):        返回单个公共成员变量对象
Field getDeclaredField(String name):返回单个成员变量对象

        Field类中用于创建对象的方法
void set(Object obj, Object value):赋值
Object get(Object obj)              获取值

public class Reflect1 {public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {//1.获取class字节码文件的对象Class cs = Class.forName("MyReflect.S.Student");//2.获取所有成员变量Field[] fields = cs.getDeclaredFields();for (Field field : fields) {System.out.println(field);}//3.获取单个的成员变量Field gender = cs.getField("gender");System.out.println(gender);//获取私有的要getDeclaredFieldField name = cs.getDeclaredField("name");System.out.println(name);//获取成员变量的名字System.out.println(name.getName());//获取成员变量的类型Class<?> type = name.getType();System.out.println(type);//获取成员变量记录的值Student s = new Student("yiyi", 18, "男");//由于name是私有的要临时获取权限name.setAccessible(true);String value = (String) name.get(s);System.out.println(value);//修改对象里面记录的值name.set(s, "euwo");System.out.println(s);}
}

        4.获取成员方法

        Class类中用于获取成员方法的方法
Method[] getMethods():返回所有公共成员方法对象的数组,包括继承的
Method[] getDeclaredMethods():返回所有成员方法对象的数组,不包括继承的
Method getMethod(String name, Class<?>... parameterTypes) :返回单个公共成员方法对象
Method getDeclaredMethod(String name, Class<?>... parameterTypes):返回单个成员方法对象
Method类中用于创建对象的方法
Object invoke(Object obj, Object... args):运行方法
参数一:用obj对象调用该方法
参数二:调用方法的传递的参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)

        获取方法的修饰符,获取方法的名字,获取方法的形参,获取方法的返回值,获取方法的抛出的异常,运行获取的方法。

public class Reflect3 {public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, ClassNotFoundException {//1. 获取class字节码文件对象Class clazz = Class.forName("MyReflect.S.Student");//2. 获取里面所有的方法对象(包含父类中所有的公共方法)/* Method[] methods = clazz.getMethods();for (Method method : methods) {System.out.println(method);}*/// 获取里面所有的方法对象(不能获取父类的,但是可以获取本类中私有的方法)/*Method[] methods = clazz.getDeclaredMethods();for (Method method : methods) {System.out.println(method);}*/// 获取指定的单一方法Method m = clazz.getDeclaredMethod("eat", String.class);System.out.println(m);// 获取方法的修饰符int modifiers = m.getModifiers();System.out.println(modifiers);// 获取方法的名字String name = m.getName();System.out.println(name);// 获取方法的形参Parameter[] parameters = m.getParameters();for (Parameter parameter : parameters) {System.out.println(parameter);}//获取方法的抛出的异常Class[] exceptionTypes = m.getExceptionTypes();for (Class exceptionType : exceptionTypes) {System.out.println(exceptionType);}//方法运行/*Method类中用于创建对象的方法Object invoke(Object obj, Object... args):运行方法参数一:用obj对象调用该方法参数二:调用方法的传递的参数(如果没有就不写)返回值:方法的返回值(如果没有就不写)*/Student s = new Student();m.setAccessible(true);//参数一s:表示方法的调用者//参数二"汉堡包":表示在调用方法的时候传递的实际参数String result = (String) m.invoke(s, "汉堡包");System.out.println(result);}
}
package MyReflect.S;import java.io.IOException;public class Student {private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}/*** 获取* @return name*/public String getName() {return name;}/*** 设置* @param name*/public void setName(String name) {this.name = name;}/*** 获取* @return age*/public int getAge() {return age;}/*** 设置* @param age*/public void setAge(int age) {this.age = age;}public void sleep(){System.out.println("睡觉");}private String eat(String something) throws IOException,NullPointerException,ClassCastException {System.out.println("在吃" + something);return "年糕";}private void eat(String something,int a) {System.out.println("在吃" + something);}public String toString() {return "Student{name = " + name + ", age = " + age + "}";}
}

        5.反射的作用

        获取一个类的所有信息,获取到之后,再执行其他的业务逻辑。

        结合配置文件,动态的创建对象并调用方法。

        实现:对于一个任意对象,都可以把所有的字段名和值,保存到文件中。

public static void main(String[] args) throws IOException, IllegalAccessException {Student s = new Student("抱竹", 17, '男', 177, "音乐");Teacher t = new Teacher("年糕", 2000);saveObject(s);}public static void saveObject(Object obj) throws IllegalAccessException, IOException {//获取字节码对象Class clazz = obj.getClass();BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));//获取所有的成员变量Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {field.setAccessible(true);String name = field.getName();Object value = field.get(obj);System.out.println();bw.write(name + "=" + value);bw.newLine();}bw.close();}

        反射可以跟配置文件结合的方式,动态的创建对象,并调用方法。

        设置配置文件,设置类的地址和要调用的方法,这里变化那么读取到的类和方法也就变了,实现动态的创建对象,调用方法。

classname=MyReflect.S.Teacher
method=teach
# classname=MyReflect.S.Student
# method=study
public class Teacher {private String name;private double salary;public Teacher() {}public Teacher(String name, double salary) {this.name = name;this.salary = salary;}public void teach(){System.out.println("老师在教书!");}/*** 获取* @return name*/public String getName() {return name;}/*** 设置* @param name*/public void setName(String name) {this.name = name;}/*** 获取* @return salary*/public double getSalary() {return salary;}/*** 设置* @param salary*/public void setSalary(double salary) {this.salary = salary;}public String toString() {return "Teacher{name = " + name + ", salary = " + salary + "}";}
}
public class Student {private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}public void study(){System.out.println("学生在学习!");}/*** 获取* @return name*/public String getName() {return name;}/*** 设置* @param name*/public void setName(String name) {this.name = name;}/*** 获取* @return age*/public int getAge() {return age;}/*** 设置* @param age*/public void setAge(int age) {this.age = age;}public String toString() {return "Student{name = " + name + ", age = " + age + "}";}
}

        通过流读取配置文件信息,然后获取类,创建对象,调用方法。

public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {//读取配置文件的信息Properties prop = new Properties();FileInputStream fis = new FileInputStream("src\\prop.properties");prop.load(fis);fis.close();System.out.println(prop);String classname = (String) prop.get("classname");String methodname = (String) prop.get("method");Class clazz = Class.forName(classname);Constructor con = clazz.getDeclaredConstructor();Object o = con.newInstance();System.out.println(o);Method m = clazz.getDeclaredMethod(methodname);m.setAccessible(true);m.invoke(o);}

        6.动态代理

        代理可以无侵入式地给对象增强其他功能 。

        代理里面就是对象要被代理的方法。

        Java通过接口保证,后面的对象和代理需要实现一个接口,接口中就是被代理的所有方法。

        Proxy类,为对象产生代理对象的方法:

ava.lang.reflect.Proxy类:提供了为对象产生代理对象的方法:

        public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
参数一:用于指定用哪个类加载器,去加载生成的代理类
参数二:指定接口,这些接口用于指定生成的代理长什么,也就是有哪些方法
参数三:用来指定生成的代理对象要干什么事情

        使用反射完成动态代理。

public class ProxyUtil {/*** 方法的作用:*       给一个明星的对象,创建一个代理**  形参:*       被代理的明星对象**  返回值:*       给明星创建的代理**** 需求:*   外面的人想要大明星唱一首歌*   1. 获取代理的对象*      代理对象 = ProxyUtil.createProxy(大明星的对象);*   2. 再调用代理的唱歌方法*      代理对象.唱歌的方法("只因你太美");* */public static Star createProxy(BigStar bigStar) {/* java.lang.reflect.Proxy类:提供了为对象产生代理对象的方法:public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)参数一:用于指定用哪个类加载器,去加载生成的代理类参数二:指定接口,这些接口用于指定生成的代理长什么,也就是有哪些方法参数三:用来指定生成的代理对象要干什么事情*/Star star = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),new Class[]{Star.class},new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {/** 参数一:代理的对象* 参数二:要运行的方法 sing* 参数三:调用sing方法时,传递的实参* */if("sing".equals(method.getName())){System.out.println("准备话筒,收钱");}else if("dance".equals(method.getName())){System.out.println("准备场地,收钱");}//去找大明星开始唱歌或者跳舞//代码的表现形式:调用大明星里面唱歌或者跳舞的方法//反射,使用从Star获取的抽象方法名调用BigStar中重写该抽象方法的方法return method.invoke(bigStar,args);}});return star;}public static void main(String[] args) {/*需求:外面的人想要大明星唱一首歌1. 获取代理的对象代理对象 = ProxyUtil.createProxy(大明星的对象);2. 再调用代理的唱歌方法代理对象.唱歌的方法("只因你太美");*///1. 获取代理的对象BigStar bigStar = new BigStar("鸡哥");Star proxy = ProxyUtil.createProxy(bigStar);//2. 调用唱歌的方法//sing对应方法method,"只因你太美"对应参数argsString result = proxy.sing("只因你太美");System.out.println(result);}
}
public class BigStar implements Star{private String name;public BigStar() {}public BigStar(String name) {this.name = name;}//唱歌@Overridepublic String sing(String name){System.out.println(this.name + "正在唱" + name);return "谢谢";}//跳舞@Overridepublic void dance(){System.out.println(this.name + "正在跳舞");}/*** 获取* @return name*/public String getName() {return name;}/*** 设置* @param name*/public void setName(String name) {this.name = name;}public String toString() {return "BigStar{name = " + name + "}";}
}
public interface Star {//唱歌public abstract String sing(String name);//跳舞public abstract void dance();
}

http://www.xdnf.cn/news/1395811.html

相关文章:

  • 2025牛客暑期多校训练营4 G Ghost in the Parentheses 题解记录
  • Day17 Docker学习
  • uac播放与录制
  • 论文阅读:arixv 2025 WideSearch: Benchmarking Agentic Broad Info-Seeking
  • React Three Fiber
  • LBM——大型行为模型助力波士顿人形Atlas完成多任务灵巧操作:CLIP编码图像与语义,之后DiT去噪扩散生成动作
  • 编程速递:RAD Studio 13 即将到来的功能
  • Linux 线程调度核心要点
  • Shell 脚本基础教程
  • java序列化
  • Android系统框架知识系列(十九):Android安全架构深度剖析 - 从内核到应用的全栈防护
  • python学习打卡day48
  • “白月光”焦点何晟铭现身宁夏中宁,助力非遗与三农发展
  • 拎包入住搭建 Browser Use Agent:基于PPIO Model API +Agent 沙箱的一体化构建
  • 变量声明方式
  • linux学习-数据库
  • 中科米堆CASAIM五金配件三维扫描测量尺寸形位公差
  • 嵌入式Linux驱动开发:i.MX6ULL平台设备驱动
  • 使用 Docker 部署 Squid 为 Kubernetes 中的 Nexus3 提供公网代理访问
  • linux 条件变量与生产消费者模型
  • 玳瑁的嵌入式日记D29-0829(进程间通信)
  • Python OpenCV图像处理与深度学习:Python OpenCV开发环境搭建与入门
  • 基于能量方法的纳维-斯托克斯方程高阶范数有界性理论推导-陈墨仙
  • STM32CubeMX + HAL 库:基于 I²C 通信的 AHT20 高精度温湿度测量实验
  • 【系列03】端侧AI:构建与部署高效的本地化AI模型 第2章:端侧AI硬件入门
  • 134-细粒度多尺度符号熵和鲸鱼优化算法的滚动轴承故障诊断技术MSVM
  • Redis搭建哨兵模式一主两从三哨兵
  • 线程安全及死锁问题
  • 【好题推荐】运算符的构造运用
  • 光伏发多少电才够用?匹配家庭用电需求