java中no1_【Java】-- 网络编程のNo.1

在现有的网络中,网络通讯的方式主要有两种:

TCP(传输控制协议)方式

UDP(用户数据报协议)方式

在网络通讯中,TCP方式就类似于拨打电话,使用该种方式进行网络通讯时,需要建立专门的虚拟连接,然后进行可靠的数据传输,如果数据发送失败,则客户端会自动重发该数据。

而UDP方式就类似于发送短信,使用这种方式进行网络通讯时,不需要建立专门的虚拟连接,传输也不是很可靠,如果发送失败则客户端无法获得。

这两种传输方式都是实际的网络编程中进行使用,重要的数据一般使用TCP方式进行数据传输,而大量的非核心数据则都通过UDP方式进行传递,在一些程序中甚至结合使用这两种方式进行数据的传递。

由于TCP需要建立专用的虚拟连接以及确认传输是否正确,所以使用TCP方式的速度稍微慢一些,而且传输时产生的数据量要比UDP稍微大一些。

无论使用TCP方式还是UDP方式进行网络通讯,网络编程都是由客户端和服务器端组成当然,B/S结构的编程中只需要实现服务器端即可。所以,下面介绍网络编程的步骤时,均以C/S结构为基础进行介绍。

网络编程技术

1、客户端网络编程步骤

客户端(Client)是指网络编程中首先发起连接的程序,客户端一般实现程序界面和基本逻辑实现,在进行实际的客户端编程时,无论客户端复杂还是简单,以及客户端实现的方式,客户端的编程主要由三个步骤实现:

建立网络连接

客户端网络编程的第一步都是建立网络连接。在建立网络连接时需要指定连接到的服务器的IP地址和端口号,建立完成以后,会形成一条虚拟的连接,后续的操作就可以通过该连接实现数据交换了。

交换数据

连接建立以后,就可以通过这个连接交换数据了。交换数据严格按照请求响应模型进行,由客户端发送一个请求数据到服务器,服务器反馈一个响应数据给客户端,如果客户端不发送请求则服务器端就不响应。根据逻辑需要,可以多次交换数据,但是还是必须遵循请求响应模型。

关闭网络连接

在数据交换完成以后,关闭网络连接,释放程序占用的端口、内存等系统资源,结束网络编程。

在实际实现时,步骤2会出现重复,在进行代码组织时,由于网络编程是比较耗时的操作,所以一般开启专门的现场进行网络通讯。

2、服务器端网络编程步骤

服务器端(Server)是指在网络编程中被动等待连接的程序,服务器端一般实现程序的核心逻辑以及数据存储等核心功能。服务器端的编程步骤和客户端不同,是由四个步骤实现,依次是:

监听端口

服务器端属于被动等待连接,所以服务器端启动以后,不需要发起连接,而只需要监听本地计算机的某个固定端口即可。

这个端口就是服务器端开放给客户端的端口,服务器端程序运行的本地计算机的IP地址就是服务器端程序的IP地址。

获得连接

当客户端连接到服务器端时,服务器端就可以获得一个连接,这个连接包含客户端的信息,例如客户端IP地址等等,服务器端和客户端也通过该连接进行数据交换。

一般在服务器端编程中,当获得连接时,需要开启专门的线程处理该连接,每个连接都由独立的线程实现。

交换数据

服务器端通过获得的连接进行数据交换。服务器端的数据交换步骤是首先接收客户端发送过来的数据,然后进行逻辑处理,再把处理以后的结果数据发送给客户端。简单来说,就是先接收再发送,这个和客户端的数据交换数序不同。

其实,服务器端获得的连接和客户端连接是一样的,只是数据交换的步骤不同。

当然,服务器端的数据交换也是可以多次进行的。

在数据交换完成以后,关闭和客户端的连接。

关闭连接

当服务器程序关闭时,需要关闭服务器端,通过关闭服务器端使得服务器监听的端口以及占用的内存可以释放出来,实现了连接的关闭。

TCP方式是需要建立连接的,对于服务器端的压力比较大,而UDP是不需要建立连接的,对于服务器端的压力比较小罢了。

Java网络编程技术

和网络编程有关的基本API位于java.net包中,该包中包含了基本的网络编程实现,该包是网络编程的基础。该包中既包含基础的网络编程类,也包含封装后的专门处理WEB相关的处理类。

InetAddress类

该类的功能是代表一个IP地址,并且将IP地址和域名相关的操作方法包含在该类的内部。

先来个Demo

publicstaticvoidmain(String[] args)throwsIOException {

try{

//使用域名创建对象

InetAddress address=InetAddress.getByName("www.163.com");

System.out.println(address);

//使用ip创建对象

InetAddress address2=InetAddress.getByName("222.184.115.167");

System.out.println(address2);

//获得本机地址对象

InetAddress address3 = InetAddress.getLocalHost();

System.out.println(address3);

//获得对象中存储的域名

System.out.println("域名:"+address3.getHostName());

//获得对象中存储的ip地址

System.out.println("IP地址:"+address3.getHostAddress());

} catch(Exception e) {

// TODO: handle exception

}

}

由于该代码中包含一个互联网的网址,所以运行该程序时需要联网,否则将产生异常。

在后续的使用中,经常包含需要使用InetAddress对象代表IP地址的构造方法,当然,该类的使用不是必须的,也可以使用字符串来代表IP地址进行实现。

TCP编程

在Java语言中,对于TCP方式的网络编程提供了良好的支持,在实际实现时,以java.net.Socket类代表客户端连接,以java.net.ServerSocket类代表服务器端连接。在进行网络编程时,底层网络通讯的细节已经实现了比较高的封装,所以在程序员实际编程时,只需要指定IP地址和端口号码就可以建立连接了。正是由于这种高度的封装,一方面简化了Java语言网络编程的难度,另外也使得使用Java语言进行网络编程时无法深入到网络的底层,所以使用Java语言进行网络底层系统编程很困难,具体点说,Java语言无法实现底层的网络嗅探以及获得IP包结构等信息。但是由于Java语言的网络编程比较简单,所以还是获得了广泛的使用。

在使用TCP方式进行网络编程时,需要按照前面介绍的网络编程的步骤进行,下面分别介绍一下在Java语言中客户端和服务器端的实现步骤。

在客户端网络编程中,首先需要建立连接,在Java API中以java.net.Socket类的对象代表网络连接,所以建立客户端网络连接,也就是创建Socket类型的对象,该对象代表网络连接

// socket1实现的是连接到IP地址是192.168.1.103的计算机的10000号端口

Socket socket1 = newSocket("192.168.1.103",10000);

// socket2实现的是连接到域名是www.sohu.com的计算机的80号端口

Socket socket2 = newSocket("www.sohu.com",80);

底层网络如何实现建立连接,对于程序员来说是完全透明的。如果建立连接时,本机网络不通,或服务器端程序未开启,则会抛出异常。

连接一旦建立,则完成了客户端编程的第一步,紧接着的步骤就是按照“请求-响应”模型进行网络数据交换,在Java语言中,数据传输功能由Java IO实现,也就是说只需要从连接中获得输入流和输出流即可,然后将需要发送的数据写入连接对象的输出流中,在发送完成以后从输入流中读取数据即可。

//获得输出流

OutputStream outputStream = socket1.getOutputStream();

//获得输入流

InputStream inputStream=socket1.getInputStream();

这里获得的只是最基本的输出流和输入流对象,还可以根据前面学习到的IO知识,使用流的嵌套将这些获得到的基本流对象转换成需要的装饰流对象,从而方便数据的操作。

最后当数据交换完成以后,关闭网络连接,释放网络连接占用的系统端口和内存等资源,完成网络操作,示例代码如下:

socket1.close();

以上就是最基本的网络编程功能介绍。

接下来写个客户端的Demo,程序在客户端发送字符串到服务器,并将服务器端的反馈显示到控制台,数据交换只进行一次,当数据交换进行完成以后关闭网络连接,程序结束。

先来客户端的代码

importjava.io.InputStream;

importjava.io.OutputStream;

importjava.net.Socket;

publicclassClient {

publicstaticvoidmain(String[] args) {

Socket socket = null;

InputStream is = null;

OutputStream os = null;

try{

String msg = "Hello";

String ip = "localhost";

intport =9898;

// 建立连接

socket = newSocket(ip, port);

// 发送数据

os = socket.getOutputStream();

os.write(msg.getBytes());

// 接收数据

is = socket.getInputStream();

byteb[]=newbyte[1024];

intn =is.read(b);

System.out.println(newString(b,0,n));

} catch(Exception e) {

// TODO: handle exception

e.printStackTrace();

} finally{

try{

//关闭连接和流

is.close();

os.close();

socket.close();

} catch(Exception e2) {

// TODO: handle exception

e2.printStackTrace();

}

}

}

}

代码中建服务器端的代码:

publicclassServer {

publicstaticvoidmain(String[] args) {

ServerSocket serverSocket=null;

Socket socket=null;

InputStream is =null;

OutputStream os =null;

try{

serverSocket = newServerSocket(9898);

socket = serverSocket.accept();

is = socket.getInputStream();

byteb[] =newbyte[1024];

intn = is.read(b);

System.out.println("客户端发送了:"+newString(b,0,n));

os = socket.getOutputStream();

os.write("接收成功!".getBytes());

} catch(Exception e) {

// TODO: handle exception

e.printStackTrace();

}finally{

try{

is.close();

os.close();

socket.close();

serverSocket.close();

} catch(Exception e2) {

// TODO: handle exception

}

}

}

}

先运行服务器端,然后运行客户端,服务器接收到数据将数据打印出来之后再返回数据到客户端,客户端打印出来

在该示例代码中建立了一个监听当前计算机9898号端口的服务器端Socket连接,然后获得客户端发送过来的连接,如果有连接到达时,读取连接中发送过来的内容,并将发送的内容在控制台进行输出,输出完成以后将客户端发送的内容再反馈给客户端。最后关闭流和连接对象,结束程序。

在服务器端程序编程中,由于服务器端实现的是被动等待连接,所以服务器端编程的第一个步骤是监听端口,也就是监听是否有客户端连接到达。实现服务器端监听的代码为:

// 该代码实现的功能是监听当前计算机的9898号端口,如果在执行该代码时,

// 10000号端口已经被别的程序占用,那么将抛出异常。否则将实现监听。

serverSocket = newServerSocket(9898);

服务器端编程的第二个步骤是获得连接。该步骤的作用是当有客户端连接到达时,建立一个和客户端连接对应的Socket连 接对象,从而释放客户端连接对于服务器端端口的占用。通过获得连接,使得客户端的连接在服务器端获得了保持,另外使得服务器端的端口释放出来,可以继续等待其它的客户端连接。 实现获得连接的代码是:

socket = serverSocket.accept();

该代码实现的功能是获得当前连接到服务器端的客户端连接。需要说明的是accept和前面IO部分介绍的read方法一样,都是一个阻塞方法,也就是当无连接时,该方法将阻塞程序的执行,直到连接到达时才执行该行代码。另外获得的连接会在服务器端的该端口注册,这样以后就可以通过在服务器端的注册信息直接通信,而注册以后服务器端的端口就被释放出来,又可以继续接受其它的连接了。

连接获得以后,后续的编程就和客户端的网络编程类似了,这里获得的Socket类型的连接就和客户端的网络连接一样了,只是服务器端需要首先读取发送过来的数据,然后进行逻辑处理以后再发送给客户端,也就是交换数据的顺序和客户端交换数据的步骤刚好相反。这部分的内容和客户端很类似。

--------------------------

上面这个示例只是演示了网络编程的基本步骤以及各个功能方法的基本使用,只是为网络编程打下了一个基础,下面将就几个问题来深入介绍网络编程深层次的一些知识。

1.如何复用Socket连接?

拨通一次电话以后多次对话,这就是复用客户端连接。

建立连接以后,将数据交换的逻辑写到一个循环中,只要循环不结束则连接就不会被关闭,按照这种思路,可以改造一下上面的代码,让该程序可以在建立连接一次以后,发送三次数据,当然这里的次数也可以是多次

现在看下新的服务器代码和客户端代码:

importjava.io.InputStream;

importjava.io.OutputStream;

importjava.net.ServerSocket;

importjava.net.Socket;

/**

* 服务器代码

* */

publicclassServer {

publicstaticvoidmain(String[] args) {

ServerSocket serverSocket = null;

Socket socket = null;

InputStream is = null;

OutputStream os = null;

try{

serverSocket = newServerSocket(9898);

socket = serverSocket.accept();

is = socket.getInputStream();

os = socket.getOutputStream();

byteb[] =newbyte[1024];

for(inti =0; i <3; i++) {

intn = is.read(b);

os.write(("客户端发送的内容:"+newString(b,0, n)).getBytes());

}

} catch(Exception e) {

// TODO: handle exception

e.printStackTrace();

} finally{

try{

is.close();

os.close();

socket.close();

serverSocket.close();

} catch(Exception e2) {

// TODO: handle exception

}

}

}

}

再看下新的客户端代码:

importjava.io.InputStream;

importjava.io.OutputStream;

importjava.net.Socket;

/**

* 客户端代码

* */

publicclassClient {

publicstaticvoidmain(String[] args) {

Socket socket = null;

InputStream is = null;

OutputStream os = null;

try{

String msg[] = { "one","two","three"};

String ip = "localhost";

intport =9898;

// 建立连接

socket = newSocket(ip, port);

// 发送数据

os = socket.getOutputStream();

// 接收数据

is = socket.getInputStream();

byteb[] =newbyte[1024];

for(inti =0; i 

os.write(msg[i].getBytes());

intn = is.read(b);

System.out.println(newString(b,0, n));

}

} catch(Exception e) {

// TODO: handle exception

e.printStackTrace();

} finally{

try{

// 关闭连接和流

is.close();

os.close();

socket.close();

} catch(Exception e2) {

// TODO: handle exception

e2.printStackTrace();

}

}

}

}

上面的代码虽然比较简单,但是通用性比较差。

在该程序中,比较明显的体现出了“请求-响应”模型,也就是在客户端发起连接以后,首先发送字符串“First”给服务器端,服务器端输出客户端发送的内容“First”,然后将客户端发送的内容再反馈给客户端,这样客户端也输出服务器反馈“First”,这样就完成了客户端和服务器端的一次对话

三次会话的过程一样,在这个过程中,每次都是客户端程序首先发送数据给服务器端,服务器接收数据以后,将结果反馈给客户端,客户端接收到服务器端的反馈,从而完成一次通讯过程。

2、如何使服务器端支持多个客户端同时工作?

一个服务器端一般都需要同时为多个客户端提供通讯,如果需要同时支持多个客户端,则必须使用前面介绍的线程的概念。简单来说,也就是当服务器端接收到一个连接时,启动一个专门的线程处理和该客户端的通讯。

改造之后的服务器代码,可以接收多个客户端的数据。

在该示例代码中,实现了一个while形式的死循环,由于accept方法是阻塞方法,所以当客户端连接未到达时,将阻塞该程序的执行,当客户端到达时接收该连接,并启动一个新的LogicThread线程处理该连接,然后按照循环的执行流程,继续等待下一个客户端连接。这样当任何一个客户端连接到达时,都开启一个专门的线程处理,通过多个线程支持多个客户端同时处理。

/**

* 支持多客户端的服务器代码

* */

publicclassServer {

publicstaticvoidmain(String[] args) {

ServerSocket serverSocket = null;

Socket socket = null;

try{

serverSocket = newServerSocket(9898);

while(true) {

socket = serverSocket.accept();

// 启动线程

// 实现接收客户端连接,然后开启专门的逻辑线程处理该连接,

// LogicThread类实现对于一个客户端连接的逻辑处理,将处理的逻辑放置在该类的run方法中。

newLogicThread(socket);

}

} catch(Exception e) {

// TODO: handle exception

e.printStackTrace();

} finally{

try{

socket.close();

serverSocket.close();

} catch(Exception e2) {

// TODO: handle exception

}

}

}

staticclassLogicThreadextendsThread {

Socket socket = null;

publicLogicThread(Socket socket) {

this.socket = socket;

start();

}

@Override

publicvoidrun() {

byteb[] =newbyte[1024];

InputStream is = null;

OutputStream os = null;

try{

is = socket.getInputStream();

os = socket.getOutputStream();

intn = is.read(b);

os.write(("客户端发送的内容:"+newString(b,0, n)).getBytes());

} catch(Exception e) {

// TODO: handle exception

e.printStackTrace();

} finally{

try{

is.close();

os.close();

socket.close();

} catch(Exception e2) {

// TODO: handle exception

}

}

}

}

}

这里的示例还只是基础的服务器端实现,在实际的服务器端实现中,由于硬件和端口数的限制,所以不能无限制的创建线程对象,而且频繁的创建线程对象效率也比较低,所以程序中都实现了线程池来提高程序的执行效率。

这里简单介绍一下线程池的概念,线程池(Thread pool)是池技术的一种,就是在程序启动时首先把需要个数的线程对象创建好,例如创建5000个线程对象,然后当客户端连接到达时从池中取出一个已经创建完成的线程对象使用即可。当客户端连接关闭以后,将该线程对象重新放入到线程池中供其它的客户端重复使用,这样可以提高程序的执行速度,优化程序对于内存的占用等。

关于基础的TCP方式的网络编程就介绍这么多,下面一章介绍UDP方式的网络编程在Java语言中的实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/573719.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

优启通怎么重装系统win10_重装系统失败?小编教你安全给神舟战神GX9 Pro重装win10系统方法...

神舟战神GX9 Pro 上市于2016年1月&#xff0c;虽然现在已经停产&#xff0c;但是还是有不少用户依旧十分喜爱这款笔记本。这款笔记本的性能完全对得起它的售价&#xff0c;很多用户都反馈其比外星人电脑要好。对于爱玩游戏的用户而言&#xff0c;对它17.3英寸的显示屏简直欲罢不…

.NET小细节

1、equals()和运算符的区别 C#中有两种不同的相等&#xff1a;引用相等和值相等。值相等是两个对象包含相同的值&#xff1b;引用相等是两个对象引用的是同一个对象。 “”操作符比较的是两个变量的值是否相等&#xff0c;或两个引用是不是指向同一个内存地址&#xff08;类似比…

java exception用法_Java基础回顾_Exception异常使用详解

package 内部类异常包装器;public class 异常 {/*** 1.异常:* 有Error和Exception两个基本子类* 2.Error:* Error表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。* 3.Exception:* 表示一种设计或实现问题。也就是说&…

获得代理ippython_Python搭建代理IP池实现获取IP的方法

使用爬虫时&#xff0c;大部分网站都有一定的反爬措施&#xff0c;有些网站会限制每个 IP 的访问速度或访问次数&#xff0c;超出了它的限制你的 IP 就会被封掉。对于访问速度的处理比较简单&#xff0c;只要间隔一段时间爬取一次就行了&#xff0c;避免频繁访问&#xff1b;而…

20135202闫佳歆--week 8 实验:理解进程调度时机跟踪分析进程调度与进程切换的过程--实验及总结...

week 8 实验&#xff1a;理解进程调度时机跟踪分析进程调度与进程切换的过程 1.环境搭建&#xff1a; rm menu -rf git clone https://github.com/megnning/menu.git cd menu ls make rootfs qemu -kernel ../linux-3.18.6/arch/x86/boot/bzImage -initrd ../rootfs.img -s -S …

java jni技术_JNI技术简介

JNI(Java Native Interface)提供一种Java字节码调用C/C的解决方案&#xff0c;JNI描述的是一种技术。NDK(Native Development Kit)Android NDK 是一组允许您将 C 或 C(“原生代码”)嵌入到 Android 应用中的工具&#xff0c;NDK描述的是工具集。 能够在 Android 应用中使用原生…

python 读取mysql大量数据处理_python使用多线程快速把大量mysql数据导入elasticsearch...

使用python多线程&#xff0c;运行时自定义线程数&#xff0c;自动计算每个线程处理的数据量&#xff0c;连接mysql读取数据&#xff0c;处理成需要的字段入到elasticsearch。运行效果图&#xff1a;10个线程 运行会在这里实时刷新&#xff0c;方便查看每个线程处理到的id数&am…

java web redis_java web redis使用(二)

上篇中已经安装好redis&#xff0c;然后下面就说怎么在java web中用客户端来使用regis使用jedis java客户端一&#xff1a;一个简单的示例代码:public static void main(String[] args) {Jedis jedis new Jedis( "147.151.240.234" , 6379 );jedis.set("foo&…

mysql 主从_搭建mysql主从并编写监控主从状态脚本

要求&#xff1a;两台centos7虚拟机分为主和从安装mysqlyum -y install mysql mysql-server关闭防火墙service iptables stopsetenforce 0上面的主从都做。修改主的配置文件vi /etc/my.cnf#添加server-id1log-binmysqlbinrelay-logrelays之后保存退出重启mysql服务service …

Ubuntu Sublime Text 3 搜狗拼音

已知前置条件 本经验目前在Ubuntu14.04环境下&#xff0c;已有搜狗输入法 for Linux和Sublime Text 3的情况下安装成功。 解决方法步骤 保存下面的代码到文件sublime_imfix.c(位于~目录) #include <gtk/gtkimcontext.h> void gtk_im_context_set_client_window (GtkIMCon…

Java核心技术点之动态代理

本篇博文会从代理的概念出发&#xff0c;介绍Java中动态代理技术的使用&#xff0c;并进一步探索它的实现原理。由于个人水平有限&#xff0c;叙述中难免出现不清晰或是不准确的地方&#xff0c;希望大家可以指正&#xff0c;谢谢大家&#xff1a;&#xff09; 一、概述 1. 什么…

pythonwebview自动化测试_GitHub - githubwzg/python-appium: 基于PageObject UI自动化测试框架,支持Android/iOS...

0910 UPDATE新增控件集参数化&#xff0c;相同测试步骤的Android/iOS可共用一份测试用例不同测试步骤的用例还需要单独写0904 UPDATE优化Android log及crsahinfo相关输出路径新增iOS crashreport解析新增内容&#xff1a;适配iOS提取android crash信息优化report(增加自动填充包…

linux中使用lftp上传下载文件

lftp是linux中一款ftp服务器相比windows中的ftp显得要复杂不少了&#xff0c;下面我来总结一下lftp文件上传&#xff0c;文件下载&#xff0c;及文件查找等等相关命令吧。 lftp连接的几种方法&#xff0c;最常用的是lftp namesite&#xff0c;这样可以不用明文输入密码。 1、lf…

java 数据库 事务 只读_不使用事务和使用只读事务的区别

转转转&#xff0c;&#xff0c;还需要具体验证(决定把readonly类型的事务完全去掉&#xff0c;以提高性能&#xff0c;这里有讨论&#xff1a;http://stackoverflow.com/questions/2562865/spring-transaction-readonly)。。。如果只提交一个查询&#xff0c;有必要用事务吗&a…

python搭建webapi_怎么搭建Web Api

1.通常我们有个web 让后可以有个web api 提供接口2.通常我们分别建两个项目 web api 依赖web的来进行访问(说到底是依赖是IIS)3.我们先建个SmallCode.Test.Web 再建一个SmallCode.Test.Api4.直接在SmallCode.Test.Web 引用 SamllCode.Test.Api 运行通过地址 /api/Order 无法访问…

shell入门之expr的使用

在expr中加减乘除的使用&#xff0c;脚本例如以下&#xff1a; #!/bin/sh #a test about expr v1expr 5 6 echo "$v1" echo expr 3 5 echo expr 6 / 2 echo expr 9 \* 5 echo expr 9 - 6 执行效果 转载于:https://www.cnblogs.com/bhlsheji/p/5401458.html

java中子线程与主线程通信_Android笔记(三十二) Android中线程之间的通信(四)主线程给子线程发送消息...

之前的例子都是我们在子线程(WorkerThread)当中处理并发送消息&#xff0c;然后在主线程(UI线程)中获取消息并修改UI&#xff0c;那么可以不可以在由主线程发送消息&#xff0c;子线程接收呢&#xff1f;我们按照之前的思路写一下代码&#xff1a;packagecn.lixyz.handlertest;…

java开源笔记软件下载_开发常用软件笔记 - ZhaoQian's Blog - OSCHINA - 中文开源技术交流社区...

notepad使用快捷键CtrlH打开“替换对话框”&#xff0c;在每行的开头添加内容。 勾选左下角的“正则表达式”选项 在“查找目标”里输入上尖号“^”&#xff0c;上尖号代表每行的开头 在“替换为”里输入“private String”。然后点"全部替换"按钮&#xff0c;这样每…

python示例apk_Python获取apk文件URL地址实例

工作中经常需要提取apk文件的特定URL地址&#xff0c;如是想到用Python脚本进行自动处理。需要用到的Python基础知识如下:os.walk()函数声明&#xff1a;os.walk(top,topdownTrue,οnerrοrNone)(1)参数top表示需要遍历的顶级目录的路径。(2)参数topdown的默认值是“True”表示…

使用静态工厂方法而不是构造器

注意&#xff1a;静态工厂方法不是设计模式中的工厂方法。 一个类向客户端提供静态工厂方法有如下好处&#xff1a; 有名称&#xff0c;不用根据参数类型和顺序区分重载方法&#xff0c;让代码更易读 是否每次调用都需要新对象是可控制的&#xff0c;对于不可修改的对象可以采取…