• java基础巩固7


    Date和Calendar

    (1)java.util.Date用于表示一个日期和时间的对象,注意与java.sql.Date区分,后者使用在数据库中。打印本地时区表示的日期和时间时,不同的计算机可能会有不同的结果,如果我们想要针对用户的偏好精确地控制日期和时间的格式,就可以使用SimpleDateFormat对一个Date进行转换。它用预定义的字符串表示格式化:
    yyyy:年
    MM:月
    dd: 日
    HH: 小时
    mm: 分钟
    ss: 秒
    Date对象有几个严重的问题:它不能转换时区,除了toGMTString()可以按GMT+0:00输出外,Date总是以当前计算机系统默认的时区为基础进行输出。此外,我们也很难对日期和时间进行加减,计算两个日期相差多少天,计算某个月第一个星期一的日期等。
    (2)Calendar可以用于获取并设置年、月、日、时分秒,它和Date相比,主要多了一个可以做简单的日期和时间运算的功能。利用Calendar.getTime()可以将一个Calendar对象转换成Date对象,然后就可以用SimpleDateFormat进行格式化了。
    (3)TimeZone
    Calendar和Date相比,它提供了时区转换的功能,时区用TimeZone对象表示,时区的唯一标识是以字符串表示的ID,我们获取指定TimeZone对象也是以这个ID为参数获取,GMT+09:00、Asia/Shanghai都是有效的时区ID。要列出系统支持的所有ID,请使用TimeZone.getAvailableIDs()。
    有了时区,我们就可以对指定时间进行转换。
    利用Calendar进行时区转换的步骤是:
    一、清除所有字段
    二、设定指定时区
    三、设定日期和时间
    四、创建SimpleDateFormat并设定目标时区
    五、格式化获取的Date对象(注意Date对象无时区信息,时区信息存储在SimpleDateFormat中)

    LocalDateTime

    (1)从Java8开始,java.time提供了新的日期API,主要涉及的类型有:
    本地日期和时间:LocalDateTime,LocalDate,LocalTime
    带时区的日期和时间:ZonedDateTime
    时刻:Instant
    时区:ZoneId,ZoneOffset
    时间间隔:Duration
    以及一套新的用于取代SimpleDateFprmat的格式化类型DateTimeFormatter。
    和旧的API相比,新API严格区分了时刻、本地日期、本地时间和带时区的日期时间,并且,对日期和时间运算更加方便。最后,新API的类型几乎全部是不变类型(和String类似),可以放心使用不必担心被修改。

    ZonedDateTime

    (1)LocalDateTime总是表示本地日期和时间,要表示一个带时区的日期和时间,我么那就需要ZonedDateTime。可以简单地把ZonedDateTime理解成LocalDateTime加ZonedId。ZoneId是java.time引入的新的时区类。
    (2)要转换时区,首先我们需要有一个ZonedDateTime对象,然后通过withZoneSameInstant()将关联时区转换到另一个时区,转换后日期和时间都会相应调整。
    下面的代码演示了如何将北京时间转换为纽约时间:
    // 以中国时区获取当前时间:
    ZonedDateTime zbj = ZonedDateTime.now(ZoneId.of(“Asia/Shanghai”));
    // 转换为纽约时间:
    ZonedDateTime zny = zbj.withZoneSameInstant(ZoneId.of(“America/New_York”));

    编写JUnit测试

    (1)单元测试就是针对最小的功能单元编写测试代码。Java程序最小的功能单元是方法,因此,对Java程序进行单元测试就是针对某个Java方法的测试。
    (2)所谓测试驱动开发,是指先编写接口,紧接着编写测试。编写玩测试后,我们才开始编写实现代码。在编写实现代码的过程中,一边写,一边测,什么时候测试全部通过了,那就表示编写的实现完成了。
    (3)JUnit是一个开源的Java芋圆的单元测试框架,专门针对Java设计,使用最广泛。JUnit是事实上的单元测试的标准框架,使用JUnit编写单元测试框架的好处是我们可以非常简单地阻止测试代码,并随时运行,JUnit就会给出成功的测试和失败的测试,还可以生成测试报告。
    (4)单元测试可以确保某个方法按照正确预期运行,如果修改了某个方法的代码,只需确保其对应的单元测试通过,即可认为改动正确。另外,测试代码本身就可以作为实例代码,用来演示如何调用该方法。
    (5)使用JUnit进行单元测试,我们可以使用断言(Assertion)来测试期望结果,可以方便地阻止和运行测试,并方便地查看测试结果,此外,JUnit既可以直接在IDE中运行,也可以方便地集成到Maven这些自动化工具中运行。

    编码算法

    (1)因为ASCII编码最多只能有127个字符,要相对更多地文字进行编码,就需要用Unicode。而中文的中使用Unicode编码就是0x4e2d,使用UTF-8则需要3个字节编码。因此,最简单的编码就是直接给每个字符指定一个若干字节表示的整数,复杂一点的编码就需要根据一个已有的编码推算出来。比如UTF-8编码,它是一种不定长编码,但可以从给定字符Unicode编码推算出来。
    (2)URL编码是浏览器发送数据给服务器时使用的编码,它通常附加在URL的参数部分,子所以要使用URL编码,是因为出于兼容性考虑,很多服务器只识别ASCII字符。URL编码有一套规则:
    如果字符是AZ,az,0~9以及-、、.、*,则保持不变;
    如果是其他字符,先转换为UTF-8编码,然后对每个字节以%XX表示。
    Java标准库提供了一个URLEncoder类对任意字符串进行URL编码。
    和标准的URL编码稍有不同,URLEncoder把空格字符编码成+,而现在的URL编码标准要求空格被编码为%20,不过,服务器都可以处理这两种情况。
    如果服务器收到URL编码的字符串,就可以对其进行解码,还原成原始字符串。
    (3)Base64编码
    URL编码是对字符进行编码,表示成%xx的形式,而Base64编码是对二进制数据进行编码,表示成文本格式。Base64编码可以把任意长度的二进制数据变为纯文本,且只包含AZ、az、0~9、+、/、=这些字符。它的原理是把3字节的二进制数据按6bit一组,用4个int整数表示,然后查表,把int整数用索引对应到字符,得到编码后的字符串。在Java中,二进制数据就是byte[]数组。
    因为标准的Base64编码会出现+、/和=,所以不适合把Base64编码后的字符串放到URL中。一种针对URL的base64编码可以再URL中使用的Base64编码,它仅仅是把+变成-,/变成
    *:
    String b64encoded = Base64.getUrlEncoder().encodeToString(input);
    (4)base64编码的目的就是把二进制数据变成文本格式,这样在很多文本中就可以处理二进制数据。例如,电子邮件协议就是文本协议,如果要在电子邮件中添加一个二进制文件,就可以用base64编码,然后以文本的形式传送。Base64编码的缺点是传输效率会降低,因为它把原始数据的长度增加了三分之一,和URL编码一样,Base64是一种编码算法,不是加密算法。

    哈希算法

    (1)哈希算法(Hash)又称摘要算法(Digest),它的作用是:对任意一组输入数据进行计算,得到一个固定长度输出摘要。哈希算法最重要的特点就是:
    相同的输入一定得到相同的输出;
    不同的输入大概率得到不同的输出。
    哈希算法的目的就是为了验证原始数据是否被篡改。Java字符串的hashCode()就是一个哈希算法,它的输入是任意字符串,输出是固定的4字节int整数。两个相同的字符串永远会计算出相同的hashCode,否则基于hashCode定位的HashMap就无法正常工作。这也是为什么当我们自定义一个class时,覆写equals()方法时我们必须正确覆写hashCode()方法。
    (2)哈希碰撞是指,两个不同的输入得到了相同的输出,碰撞不能避免,因为输出的字节长度是固定的,String的hashCode()输出是4字节整数,最多只有4294967296种输出,但输入的数据长度是不固定的,有无数种输入。所以,哈希算法是把一个无限的输入集合映射到一个有限的输出集合,必然会产生碰撞。
    碰撞不可怕,可怕的是碰撞地概率,因为碰撞概率的高低关系到哈希算法的安全性,一个安全地哈希算法必须满足:
    碰撞概率低
    不能猜测输出:输入的任意一个bit的变化会造成输出完全不同,这样就很难从输出反推输入(只能靠暴力穷举)。安全地哈希算法从输出是看不出任何规律的。
    常见的哈希算法有:
    在这里插入图片描述
    根据碰撞概率,哈希算法的输出长度越长,就越难产生碰撞,也就越安全。

    哈希算法的用途

    (1)如何判断下载到本地的软件是原始的、未经篡改的文件?我们只需要自己计算一下本地文件的哈希值,再与官网公开的哈希值对比,如果相同,说明文件下载正确,否则,说明文件已被篡改。
    (2)哈希算法的另一个重要用途是存储用户口令,如果直接将用户的原始口令存放到数据库中,会产生极大地安全风险:
    数据库管理员能够看到用户明文口令;
    数据库数据一旦泄露,黑客即可获取用户明文口令;
    因此需要存储用户口令的哈希,例如MD5
    在用户输入原始口令后,系统计算用户输入的原始口令的MD5并与数据库存储的MD5对比,如果一致,说明口令正确,否则,口令错误。
    (3)使用哈希口令时,还要注意防止彩虹表攻击,如果有一个预先计算好的常用口令和它们的MD5的对照表:
    在这里插入图片描述
    这个表就是彩虹表,如果用户使用了常用命令,黑客从MD5以下就能反查到原始口令,这就是为什么不要使用常用密码,以及不要使用生日作为密码的原因。即使用户使用了常用口令,我们也可以采取措施来低于彩虹表攻击,方法是对每个口令额外添加随机数,这个方法称为加盐(salt):
    digest = md5(salt+inputPassword)
    加盐的目的在于使黑客的彩虹表失效,即使用户使用常用口令,也无法从MD5反推原始口令。
    (4)SHA-1也是一种哈希算法,它的输出是160 bits,即20字节。SHA-1是由美国国家安全局开发的,SHA算法实际上是一个系列,包括SHA-0(已废弃)、SHA-1、SHA-256、SHA-512等。类似的,计算SHA-256,我们需要传入名称"SHA-256",计算SHA-512,我们需要传入名称"SHA-512"。Java标准库支持的所有哈希算法可以在这里查到。

  • 相关阅读:
    指针强化与提高
    应急响应.windows
    pytho-numpy-数组切片存取元素
    Spring Cloud Alibaba+saas企业架构技术选型+架构全景业务图 + 架构典型部署方案
    338.比特位计数
    Godot 4 教程《勇者传说》依赖注入 学习笔记(0):环境配置
    网安入门17-XSS(打Cookie)
    Python文件操作(05):Excel操作
    2023Linux C/C++全栈开发知识技术合集(基础入门到高级进阶)
    进程关系~
  • 原文地址:https://blog.csdn.net/weixin_49131718/article/details/126251401