首页
关于
Search
1
sql的注入原因和解决办法
146 阅读
2
SpringBoot整合腾讯云存储COS及基本使用,增删改查......
134 阅读
3
深究contains方法
101 阅读
4
多线程概述
76 阅读
5
学习的第一个注解@WebServlet - JavaWeb
74 阅读
默认分类
Java
C/C++
Mysql
JavaWeb
SpringBoot
算法
前端
Linux
Search
标签搜索
Spring
HTTP
Java
JavaWeb
IOC
mybatis
腾讯云
COS
云存储
CDN
redis
分布式
id
全局唯一id
Typecho
累计撰写
26
篇文章
累计收到
2
条评论
首页
栏目
默认分类
Java
C/C++
Mysql
JavaWeb
SpringBoot
算法
前端
Linux
页面
关于
搜索到
11
篇与
默认分类
的结果
2022-10-27
SpringBoot集成腾讯云短信JDK,实现短信发送!!!
腾讯云原文地址,原文更详细,我下面的代码略有修改,只保留了与发送短信相关的代码。https://cloud.tencent.com/document/product/382/43194#.E5.8F.91.E9.80.81.E7.9F.AD.E4.BF.A1腾讯云短信控制台: https://console.cloud.tencent.com/smsv2 短信签名、模板ID、短信应用ID项目pom文件引入腾讯云短信接口的sdk <dependency> <groupId>com.tencentcloudapi</groupId> <artifactId>tencentcloud-sdk-java</artifactId> <!-- go to https://search.maven.org/search?q=tencentcloud-sdk-java and get the latest version. --> <!-- 请到https://search.maven.org/search?q=tencentcloud-sdk-java查询所有版本,最新版本如下 --> <version>3.1.612</version> </dependency>配置tencentCloud.properties文件在resources目录下,用于保存腾讯云的用户API密钥tencent.cloud.secretId=AKc6Si**********BtQmvtiMo5me5S tencent.cloud.secretKey=NYWIuK**********spdIE1fPW tencent.cloud.sdkAppId=短信应用ID tencent.cloud.signName=短信签名内容 tencent.cloud.templateId=模板 ID创建一个实体类,用于读取密钥与短信相关配置@Component @Data @PropertySource(value = "classpath:tencentCloud.properties", encoding = "UTF-8") @ConfigurationProperties(prefix = "tencent.cloud") public class TencentCloudProperties { // 腾讯云账户密钥对 private String secretId; private String secretKey; // 短信应用ID private String sdkAppId ; // 短信签名内容 private String signName ; // 模板 ID private String templateId ; }将发送短信相关代码封装成一个工具类 经过封装后,调用该方法时只需传入手机号码和验证码,事后会返回SDK的一个短信发送结果封装类SendSmsResponse。package com.achong.utils; import com.achong.bean.TencentCloudProperties; import com.tencentcloudapi.common.Credential; import com.tencentcloudapi.common.exception.TencentCloudSDKException; import com.tencentcloudapi.sms.v20210111.SmsClient; // 注意 SendSmsRequest 和 SendSmsResponse 是在同一个包下 import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest; import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class SMSUtils { @Autowired private TencentCloudProperties tencentCloudProperties; /** * 发送短信 post请求 */ public SendSmsResponse sendSMS(String phone, String verCode){ System.out.println("=========================================="); System.out.println(tencentCloudProperties.toString()); System.out.println("=========================================="); // 实例化一个认证对象,入参需要传入腾讯云账户密钥对secretId,secretKey。 Credential cred = new Credential(tencentCloudProperties.getSecretId(), tencentCloudProperties.getSecretKey()); /* 实例化要请求产品的client对象 * 第一个参数是认证对象 * 第二个参数是地域信息,可以直接填写字符串ap-guangzhou,支持的地域列表参考 https://cloud.tencent.com/document/api/382/52071#.E5.9C.B0.E5.9F.9F.E5.88.97.E8.A1.A8 */ SmsClient client = new SmsClient(cred, "ap-guangzhou"); // 实例化一个请求对象,根据调用的接口和实际情况,可以进一步设置请求参数 SendSmsRequest request = new SendSmsRequest(); /** * 以下是填充请求信息 */ /* 短信应用ID: 短信SdkAppId在 [短信控制台] 添加应用后生成的实际SdkAppId,示例如1400006666 */ // 应用 ID 可前往 [短信控制台](https://console.cloud.tencent.com/smsv2/app-manage) 查看 request.setSmsSdkAppId(tencentCloudProperties.getSdkAppId()); /* 短信签名内容: 使用 UTF-8 编码,必须填写已审核通过的签名 */ // 签名信息可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-sign) 或 [国际/港澳台短信](https://console.cloud.tencent.com/smsv2/isms-sign) 的签名管理查看 request.setSignName(tencentCloudProperties.getSignName()); /* 模板 ID: 必须填写已审核通过的模板 ID */ // 模板 ID 可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-template) 或 [国际/港澳台短信](https://console.cloud.tencent.com/smsv2/isms-template) 的正文模板管理查看 request.setTemplateId(tencentCloudProperties.getTemplateId()); /* 模板参数: 模板参数的个数需要与 TemplateId 对应模板的变量个数保持一致,若无模板参数,则设置为空 */ String[] templateParamSet = {verCode}; request.setTemplateParamSet(templateParamSet); /* 下发手机号码,采用 E.164 标准,+[国家或地区码][手机号] * 示例如:+8613711112222, 其中前面有一个+号 ,86为国家码,13711112222为手机号,最多不要超过200个手机号 */ String[] phoneNumberSet = {"86" + phone}; request.setPhoneNumberSet(phoneNumberSet); /* 通过 client 对象调用 SendSms 方法发起请求。注意请求方法名与请求对象是对应的 * 返回的 response 是一个 SendSmsResponse 类的实例,与请求对象对应 */ SendSmsResponse response = null; try { response = client.SendSms(request); } catch (TencentCloudSDKException e) { e.printStackTrace(); } // 输出json格式的字符串回包 System.out.println(SendSmsResponse.toJsonString(response)); //方法将返回 短信发送结果 的对象 return response; } } 创建Controller调用上面封装的工具类发送短信进行测试。package com.achong.controller; import com.achong.utils.SMSUtils; import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class SendSMSController { @Autowired private SMSUtils smsUtils; @RequestMapping("/sendSms") public void sendSms(String phone){ if (phone == null || phone == "" || phone.length() != 11) { System.out.println("手机号错误"); return; } // 本地生成四位数验证码,短信位数可调整 10000 的位数 String code = (int)((Math.random() * 9 + 1) * 10000) + ""; // 调用工具类发送短信,参数分别是 手机号码 和 验证码。 SendSmsResponse response = smsUtils.sendSMS(phone, code); // 格式化打印输出短信发送结果 System.out.println(SendSmsResponse.toJsonString(response)); // 拿到 短信发送结果 里的 Code 字段,该字段表示 短信是否发送成功 String status = response.getSendStatusSet()[0].getCode(); if ("Ok".equals(status)){ System.out.println("发送成功,状态码:"+status); }else { System.out.println("发送失败,状态码:"+status); } } } 浏览器测试访问地址:http://localhost:8080/sendSms?phone=17310101010发送成功后,页面会返回短信发送结果,格式为 JSON字符串,其中Code字段为短信发送结果,成功则该字段为Ok,否则是其他错误信息。该字段可以作为判断短信发送是否成功的依据。 { "SendStatusSet": [{ "SerialNo": "3369:76164835516668596094641947", 发送流水号。 "PhoneNumber": "+8617310101010", 手机号码,E.164标准,+[国家或地区码][手机号] ,示例如:+8613711112222, 其中前面有一个+号 ,86为国家码,13711112222为手机号。 "Fee": 1, 计费条数 "SessionContext": "", 用户 session 内容。 "Code": "Ok", 短信请求错误码 "Message": "send success", 短信请求错误码描述。 "IsoCode": "CN" 国家码或地区码,例如 CN、US 等,对于未识别出国家码或者地区码,默认返回 DEF }], "RequestId": "b9a8468f-12bb-4985-bda7-5592d56f98bd" }
2022年10月27日
66 阅读
0 评论
2 点赞
2022-04-27
Servlet 浏览器响应文件下载功能实现
设置被下载文件先设置文件的下载地址获取文件名设置响应设置响应头设置文件流字节流,更好的传输文件。protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.获取内部文件的下载路径 String realPath = "D:\\study\\JavaWeb\\IDEA code\\test111\\ResponseDownload\\src\\com\\achong\\resources\\哪吒.png"; //2.获取下载的文件名(截取文件路径) String fileName = realPath.substring(realPath.lastIndexOf("\\")+1); //3.设置浏览器能够支持下载,注意处理文件名带中文 //先处理文件中文名问题 fileName = URLEncoder.encode(fileName, "UTF-8"); //告诉浏览器要下载该文件(设置响应头) response.setHeader("Content-Disposition", "attachment; filename="+fileName); //4.获取下载文件的输入流 FileInputStream in = new FileInputStream(realPath); //5.创建缓冲区 int len = 0; byte[] buffer = new byte[1024]; //6.获取OutputStream对象 ServletOutputStream out = response.getOutputStream(); //7.将FileOutputStream流写入buffer缓冲区,使用OutputStream将缓冲区中的数据输出到客户端 while ((len = in.read(buffer))>0){ out.write(buffer,0,len); } //最后,关闭流 in.close(); out.close(); }
2022年04月27日
39 阅读
0 评论
0 点赞
2022-03-23
Mysql常用基础语句
持续更新......选择某表;USE test01;创建表后,添加主键约束;ALTER TABLE `user` ADD CONSTRAINT pk_id PRIMARY KEY(`id`);删除主键约束,不需要指定字段;ALTER TABLE `person1` DROP PRIMARY KEY;添加联合主键;ALTER TABLE `person1` ADD PRIMARY KEY (`uid`,`pid`);创建表后,添加外键约束;alter table 从表 add [constraint] 外键名称 foreign key (从表外键字段名) references 主表(主表的主键);ALTER TABLE `userInfo` ADD CONSTRAINT userInfo_user_fk FOREIGN KEY(`id`) REFERENCES `user`(`id`);删除外键约束,需要指定外键名称;ALTER TABLE `userInfo` DROP FOREIGN KEY userInfo_user_fk;增---------------------------------------------------------------------;创建表;CREATE TABLE person1( `uid` CHAR(12) NOT NULL, `pid` CHAR(12) NOT NULL, `text` CHAR(50) );插入数据;INSERT INTO user1(NO,NAME) VALUE ("125","achong");插入多行数据;INSERT INTO user1(NO,NAME) VALUE ("125","achong1"),("126","achong2"),("127","achong3"); INSERT INTO userInfo(id, address, phone) VALUE ("125","广东省清远市111",10001), ("126","广东省清远市222","10002"), ("127","广东省清远市333","10003");添加字段;ALTER TABLE user1 ADD `phone`CHAR(11);创建数据库create database userdb;删--------------------------------------------------------------------;删除某表;DROP TABLE user22;删除某行;DELETE FROM person1 WHERE `text`= "qwe00";删除表中所有行对比delete,truncate table的执行熟读更快,使用的系统资源和事务日志资源更少,并且删除数据后的标识列会重新开始编号。truncate table t_user;改--------------------------------------------------------------------;修改表名;ALTER TABLE `user1` RENAME `user`;修改字段,连同字段的属性都需要修改;ALTER TABLE user1 CHANGE `phone` `sex`CHAR(1);更新表数据update dept set loc='SH' where deptno=30;查--------------------------------------------------------------------;查询所有数据库;SHOW DATABASES; 查看所有表;SHOW TABLES;查看表结构;DESC `userInfo`;查询表数据;SELECT * FROM `userInfo`; SELECT * FROM `person1`;
2022年03月23日
46 阅读
0 评论
0 点赞
2022-03-17
HTTP请求和响应的分析
get and post准备:index.html, GetHttp.java,PostHttp.javaindex.html<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>GET请求</h1> <form action="/test01/GetHttp" method="get"> userName<input type="text" name="userName"><br> passWord <input type="password" name="passWord"><br> <input type="submit" value="login"> </form> <br><br> <h1>post请求</h1> <form action="/test01/PostHttp" method="post"> userName <input type="text" name="userName"><br> passWord <input type="password" name="passWord"><br> <input type="submit" value="login"> </form> </body> </html>GetHttp@Override public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.print("<!doctype html>"); out.print("<html>"); out.print(" <head>"); out.print(" <title>Form Get Servlet</title>"); out.print(" </head>"); out.print(" <body>"); out.print(" <h1>"); out.print(" from get servlet"); out.print(" </h1>"); out.print(" </body>"); out.print("</html>"); }PostHttp@Override public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.print("<!doctype html>"); out.print("<html>"); out.print(" <head>"); out.print(" <title>Form Get Servlet</title>"); out.print(" </head>"); out.print(" <body>"); out.print(" <h1>"); out.print(" from get servlet"); out.print(" </h1>"); out.print(" </body>"); out.print("</html>"); }分析:响应HTTP具体报文HTTP/1.1 200 ok //状态行 Content-Type: text/html;charset=ISO-8859-1 //响应头 Content-Length: 166 Date: Thu, 17 Mar 2022 04:22:32 GMT Keep-Alive: timeout=20 Connection: keep-alive //空白行 <!doctype html> //响应体 <html> <head> <title>Form Get Servlet</title> </head> <body> <h1> from get servlet </h1> </body> </html状态行三部分组成第一部分:协议版本号(HTTP/1.1)第二部分:状态码(HTTP协议中规定的响应状态号。不i痛的响应结果对应不同的号码)200表示响应成功。404表示资源不存在。要么是没有该资源,要么是路径写错了。405表示前端发生的请求方式和后端的处理方式不一致时发生。比如前段是发送post请求,后端是get方式处理。比如前端是发生post请求,后端是get方式处理。500表示服务器端的程序出现了异常,一般是服务器端导致的错误。小总结:以4开头,一般是浏览器端的错误导致的。以5开头,一般是服务器端的错误导致的。第三部分:状态的描述ok表示正常成功结束not found表示资源找不到响应头:响应的内容类型响应的内容长度响应时间......空白行:用来分隔”响应头“和“响应体”的。响应体:就是响应的正文,响应的正文被浏览器渲染,解释并执行,最终展现出的效果。分析:请求get请求内容Request URL: http://localhost:8080/test01/GetHttp?userName=lisi&passWord=123 //请求行 Request Method: GET //请求头 Status Code: 200 Remote Address: [::1]:8080 Referrer Policy: strict-origin-when-cross-origin HTTP/1.1 200 Content-Type: text/html;charset=ISO-8859-1 Content-Length: 188 Date: Thu, 17 Mar 2022 04:44:40 GMT Keep-Alive: timeout=20 Connection: keep-alive GET /test01/GetHttp?userName=lisi&passWord=123 HTTP/1.1 Host: localhost:8080 Connection: keep-alive sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="99", "Google Chrome";v="99" sec-ch-ua-mobile: ?1 sec-ch-ua-platform: "Android" Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Mobile Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Referer: http://localhost:8080/test01/pages/http/http.html Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7 Cookie: Idea-4bb2b176=f38436c5-5137-4805-8d0a-75f83df8839d //空白行 //请求体post请求内容POST /test01/PostHttp HTTP/1.1 //请求行 Host: localhost:8080 //请求头 Connection: keep-alive Content-Length: 28 Cache-Control: max-age=0 sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="99", "Google Chrome";v="99" sec-ch-ua-mobile: ?1 sec-ch-ua-platform: "Android" Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Mobile Safari/537.36 Origin: http://localhost:8080 Content-Type: application/x-www-form-urlencoded Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Referer: http://localhost:8080/test01/pages/http/http.html Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7 Cookie: Idea-4bb2b176=f38436c5-5137-4805-8d0a-75f83df8839d //空白行 userName: achong //请求体 passWord: 123分析请求行包括三部分第一部分:请求方式,常用的有两个getpost第二部分:URI什么是URI?统一资源标识符。代表网络中某个资源的名字。但是无法通过URI定位资源什么是URL?统一资源定位符。代表网络中某个资源。可以通过URL定位该资源。URI和URL的关系,区别URL包含URI。http://localhost:8080/test01/pages/http/http.html是URL/test01/pages/http/http.html是URI第三部分:HTTP协议版本号。请求体请求的主机主机的端口浏览器信息平台信息Cookie等等空白行分隔”请求体“和”请求体“。请求体向服务器发送的具体数据。get和post的区别怎么向服务器发送GET请求,怎么向服务器发送POST请求?到目前为止,只有一种情况可以发送POST请求:使用form表单,且form标签中的method属性值为“post”。其他情况一律是GET请求。在浏览器上直接输入URL回车,属于get请求。在浏览器直接点击超链接,属于get请求。使用form时,from标签中的method值为get。......GET请求和POST请求的区别get请求发送数据时,数据会挂在URL后面,以” ?“隔开,” ?“后面是数据。这样会导致数据显示在浏览器地址栏上。post请求发送数据的时候,在请求体中发送,不会显示在浏览器地址栏。get请求只能发送普通字符,并且字符串的长度有限制,不同浏览器现在不同,没有明确规范。get无法发送大量数据。post请求可以发送任何类型的数据,包括普通字符,流媒体信息,图片...post可以发送大量数据,理论上没有上限。get请求在W3C中是这样说的,get请求比较适合从服务器段获取数据。post请求在W3C中时这样说的:post请求比较适合向服务器端传送数据。get和post的安全性。get请求是安全的。为什么?从应用场景来说,get请求只是为了从服务器获取数据。不会对服务器造成威胁。post请求时危险的。为什么?因为post时向服务器提交数据,如果这些数据通过后门的方式进入到服务器当中,服务器是很危险的。一般情况下。拦截/监听的请求,大部分是post有些情况,比如get请求会使信息暴露在浏览器地址栏,这是因为使用了错误的请求方式造成的。使用规范请回看上面的7、8。get请求支持缓存。任何一个get请求都会被浏览器缓存起来。https://n.sinaimg.cn/default/590/w240h350/20220316/3a70-d24bfc7f073a3b02bbb1fef5aa17ccd4.jpg在浏览器缓存中,一个资源对应一个路径实际上,在发送get请求的时候,浏览器第一时间是在本地查找资源,找不到了才会去服务器获取。如何不让get走缓存?http:abc.com/img/1.jpg?t=1231234http:abc.com/img/1.jpg?t=1231234http:abc.com/img/1.jpg?t=系统毫秒数只要每次请求的路径不同即可,可以在文件末尾加上时间戳。post请求不支持缓存。因为post请求的一般是动态数据。get和post如何选择?看使用场景。如果想向服务器发送数据,建议get。如果想获取服务器上的资源,建议post。大部分表单提交都是post,因为form表单中需要填写大量数据,一般是要传给服务器来保存或修改的。表单中有敏感数据,建议使用post,因为get会回显数据在浏览器地址栏。做文件上传,一定是要post请求。get和post发送的数据格式时完全相同的,只不过时位置不一样。userName=lisi&passWord=123name是什么?以form表单为例:from表单中的input标签的name。value是什么?以form表单为例:from表单中的input标签的value。
2022年03月17日
36 阅读
0 评论
0 点赞
2022-03-13
解决Tomcat服务其在DOS命令窗口的乱码问题(控制台乱码)
解决前的DOS界面:解决后的DOS界面:解决方法:只需修改小猫的apache-tomcat-8.5.75conflogging.properties这份文件里的43行代码。将原来的编码UTF-8改成GBK即可。因为DOS界面是GBK的编码方式。
2022年03月13日
62 阅读
0 评论
0 点赞
2022-03-06
深究contains方法
contains方法解析在java中,contains方法用于判断集合中是否包含某个元素,包含则返回true,否则返回false。boolean contains(Object o); //先看一个案例:字符串str实际上没添加进集合c里,但是contains返回的结果却是true?也就是说,contains发现str包含在c集合里。public static void main(String[] args) { //创建集合对象 Collection c = new ArrayList(); //添加数据 c.add("abc"); c.add(123); //1.str实际上没添加进集合c里,但是contains返回的结果却是true? String str = "abc"; System.out.println("str是否包含在集合里:"+c.contains(str)); //true 再看第二个案例:new了两个属性相同的学生对象stu1和stu2。跟代码一逻辑一样,把stu1添加进集合里,因为两个学生的名字是相同的,所以用contains方法比较stu2是否包含在集合c里,然而这次返回结果是false,为什么,明明两个学生名字一样啊。public static void main(String[] args) { //创建集合对象 Collection c = new ArrayList(); //添加数据 c.add("abc"); c.add(123); //2.根据上面的逻辑,这次new两个属性相同的学生对象stu1和stu2,把stu1添加进集合里,然后判断stu2是否在集合里,这次结果为false Student stu1 = new Student("小明"); Student stu2 = new Student("小明"); c.add(stu1); System.out.println("学生对象stu是否在集合c里:"+c.contains(stu2)); //false } } //学生类 class Student{ String name; //带参构造方法 public Student(String name) { this.name = name; }原因: 通过查看实现类ArrayList里的contains方法可以发现,从contains()到indexOf(),再到indexOfRange(),在最后的indexOfRange()方法里,调用了equals()方法来进行比较。//contains的底层源码 public boolean contains(Object o) { return indexOf(o) >= 0; } public int indexOf(Object o) { return indexOfRange(o, 0, size); } int indexOfRange(Object o, int start, int end) { Object[] es = elementData; // if (o == null) { for (int i = start; i < end; i++) { if (es[i] == null) { return i; } } } else { for (int i = start; i < end; i++) { if (o.equals(es[i])) { return i; } } } return -1; }结论分析 关于equals方法,我们得知道,所有的子类默认继承Object类,而Object的equels方法只是返回对象内存地址。 由此分析代码一:集合里有一个字符串“abc”,创建一个String变量赋值“abc”,两者本质上都是字符串,且String类型已经重写equals方法。contains在对两个比较的时候调用的是equals方法,由于String类的已经重写了,返回的是属性而不是内存地址,故字符串可以被正确比较。 代码二分析:虽然两个学生的名字属性一样,但是,集合保存的是对象的内存地址,而Student类没有重写equals方法,所以contains方法在调用equals方法判断的时候,判断的是两个对象的地址,两个对象的内存地址肯定不一样,所以返回false。 代码二解决方案:重写Student的equals方法,使其返回对象属性,即可获取正确的判断。//学生类重写的equals方法 class Student{ String name; public Student(String name) { this.name = name; } @Override public boolean equals(Object obj) { if (obj == null || !(obj instanceof Student)) return false; if(obj == this) return true; Student s = (Student) obj; if(this.name == s.name) return true; return false; } }再看以下代码:Integer x = 1000; Integer y = 1000; c.add(x); System.out.println(c.contains(y)); //true虽然new了两个不一样的对象,但是Integer包装类重写了equals方法,所以x和y是一样的。结论:放在集合里的类型,一定要重写equals方法。注意:remove删除方法也是调用的equals方法。
2022年03月06日
101 阅读
0 评论
1 点赞
2022-03-05
Collection集合里的迭代器
Collection集合的迭代器迭代器适合所有集合。常用的两个函数:boolean hasNext(); //判断集合里还有无元素。 next(); //这个方法让迭代器前进一位,并且将指向的元素返回。 void remove(); //删除当前元素一般这两个方法会一起使用,先hasNext()判断集合是否还有元素,然后next()拿到下一个元素。public static void main(String[] args) { //创建一个集合对象 Collection c = new ArrayList(); //添加数据 c.add("你好"); c.add("我叫阿冲"); c.add("很高兴认识你"); c.add("你叫什么名字?"); c.add(123); c.add("abc"); // 创建集合对象 Iterator it = c.iterator(); //循环判断,并取出。 while(it.hasNext()){ Object obj = it.next(); //这里用Object类型接收,因为集合里存储的对象类型可能不一样 System.out.println(obj); } }迭代集合原理该方法拿到一个迭代器,它负责遍历集合中的元素。it.hasNext(); 这个方法返回true,表示集合里还有元素可以迭代,若返回false,则表示没有更多的元素可以迭代了。it.next();表示拿到迭代器当前位置的下一个元素并返回。把集合想象成一个数组,迭代器像一个指向集合里元素的箭头。起初,迭代器指向的位置是在第一个元素的前一位。it.next()每拿一个元素,迭代器就前进一位Iterator it = c.iterator(); while(it.hasNext()){ Object obj = it.next(); //这里用Object接收,因为集合里存储的对象类型可能不一样 System.out.println(obj); }迭代器remove方法先说结论:如果集合的状态发生改变,对应迭代器必须重新获取。若集合的状态改变了,但是迭代器没有更新,此时还用旧的迭代器输出数据,就会发生异常。例如以下代码: 在拿到迭代器后,又往集合里添加一个新数据,此时下面的循环遍历就会报异常 ConcurrentModificationExceptionCollection c = new ArrayList(); c.add(123); c.add(234); c.add(234); Iterator it = c.iterator(); c.add(1122); while (it.hasNext()){ Object o = it.next(); System.out.println(o); }迭代器的原理: 在执行语句Iterator it = c.iterator();的时候,相对于把 c 集合里的数据复制了一份出来保存到 it 里。在使用点带起的时候,系统会时刻检查 c集合 和 it迭代器的内容是否一致 。 所以,往集合添加和删除元素的时候,需要及时更新迭代器;在迭代的过程中需要删除元素,必须使用迭代器的remove方法,而不是集合的remove方法。
2022年03月05日
52 阅读
0 评论
0 点赞
2022-03-05
Collection接口里的常用方法
Collection接口的常用方法Collection是接口,以下使用该接口的实现类来测试该接口里的方法。下面只是列举了一些常用的方法。Collection中能存放什么元素? 没有使用”泛型“之前,Collection可以存储Object的所有子类型。使用”泛型“之后,Collection只能存储某个数据类型。 集合中不能直接存储数据类型,也不能存储java对象,只是 存储java对象的内存地址。 常用方法 //往集合里添加元素。boolean add(Object e); //获取集合中元素个数。 int size(); //清空集合。 void clear(); //判断集合是否包含某元素。 boolean contains(); //删除集合中某个元素 boolean remove(Object o; //判断该集合中元素个数是否为0,即是否为空。 boolean isEmpty(); //把集合转换成数组。Object[] toArray();
2022年03月05日
65 阅读
0 评论
0 点赞
2022-03-05
多线程概述
多线程什么是进程?什么是线程?进程是一个运行中的应用程序。线程时进程中的执行场景/执行单元一个进程可以启动多个线程进程之间的内存独立不共享QQ是一个进程,微信是一个进程,这两个进程时独立的,不共享资源线程之间线程A和线程B,堆方法和方法区内存共享,但是栈内存独立,一个线程一个栈假设启动10个线程,就会有10个栈空间,每个栈和每个栈之间互不干扰,各自执行各自的,这就是多线程并发假设进程是一个火车站,那每一个售票窗口就是一个线程,每个窗口之间的可以同时售票。所以多线程并发可以提高效率。线程的生命周期注意:使用了多线程机制后,main方法结束,程序也不会结束。mian方法结束只是主线程结束了,主栈空了,其他栈可能还在运行(压栈弹栈)
2022年03月05日
76 阅读
0 评论
0 点赞
2022-03-05
集合继承结构图
集合结构Collection- CollectionListList集合存储特点,元素有序可重复,存储的元素有下标。ArrayListArrayList集合底层采用了数组这种数据结构。ArrayList集合是非线程安全的。LinkListLinkList集合底层采用了双向链表数据结构VectorVector集合也是采用双向链表的数据结构,但它是线程安全的。Vector所有的方法都有synchronized关键字修饰,所以线程安全,但是效率较低。选择保证线程安全有别的办法,故Vector使用较少了。SetSet集合存储特点:元素无序不可重复。HashSet实际上HashSet集合在new的时候,底层实际上new了一个HashMap集合。向HashSet中存储元素,实际上是存储在HashMap集合中。HashMap集合是一个哈希表数据结构。TreeSetSet实现了SortedSet接口,TreeSet是一个实现类。TreeSet底层实际上是TreeMap,new TreeSet的时候,实际上是new了一个TreeMap集合。往TreeSet中存储数据的时候,实际上是将数据放到TreeMap集合中了。-TreeMap集合底层采用了二叉树结构。MapMap集合与Collection集合没有关系。Map集合以key和value的这种键对值的方式存储元素。key和value都是存储java对象的内存地址。 -所有Map集合的key特点:无序不可重复的。Map集合的key和Set集合的存储元素特点相同。HashMap:-HashMap集合底层是哈希表数据结构,是非线程安全的。Hashteble-Hashtable集合底层也是哈希表数据结构,是线程安全的,其中所有的方法都带有synchronized关键字,但效率较低,现在使用少了,因为控制线程安全有其他更好的方案。 -Properties -Properties是线程安全的,因为继承Hashtable,另外Properties存储元素的时候也是采用key和value的形式存储,并且key和value支支持String类型,不支持其他类型。 -Properties被称为属性类TreeMap <interface> SortedSetTreeMap集合底层的数据结构是一个二叉树。
2022年03月05日
42 阅读
0 评论
1 点赞
2022-03-05
欢迎使用 Typecho
如果您看到这篇文章,表示您的 blog 已经安装成功.
2022年03月05日
30 阅读
1 评论
0 点赞
粤ICP备18061175号-3