初看一脸问号,看懂直接跪下! (上)

简介: 初看一脸问号,看懂直接跪下! (上)

你好呀,我是歪歪。

我最近在 stackoverflow 上看到一段代码,怎么说呢。

就是初看一脸懵逼,看懂直接跪下!

image.png

我先带你看看 stackoverflow 上的这个问题是啥,然后引出这段代码:

https://stackoverflow.com/questions/15182496/why-does-this-code-using-random-strings-print-hello-world

问题特别简单,就一句话:

谁能给我解释一下:为什么这段代码使用随机字符串打印出了 hello world?

image.png

代码也很简单,我把它拿出来给你跑一下:

public class MainTest {
    public static void main(String[] args) {
        System.out.println(randomString(-229985452) + " " + randomString(-147909649));
    }
    public static String randomString(int i) {
        Random ran = new Random(i);
        StringBuilder sb = new StringBuilder();
        while (true) {
            int k = ran.nextInt(27);
            if (k == 0)
                break;
            sb.append((char) ('`' + k));
        }
        return sb.toString();
    }
}

上面的代码你也可以直接粘贴到你的运行环境中跑一下,看看是不是也输出的 hello world:

image.png



高赞回答


image.png

高赞回答也特别简单,就这么两句话。

我给你翻译一下,这个哥们说:

当我们调用 Random 的构造方法时,给定了一个“种子”(seed)参数。比如本例子中的:-229985452 或 -147909649。

那么 Random 将从指定的种子值开始生成随机数。

而每个用相同的种子构造的 Random 对象,都会按照产生相同的模式产生数字。

没看的太明白,对不对?

没关系,我给你上一段代码,你就能恍然大悟上面这一段说的是啥事:

public static void main(String[] args) {
    randomString(-229985452);
    System.out.println("------------");
    randomString(-229985452);
}
private static void randomString(int i) {
    Random ran = new Random(i);
    System.out.println(ran.nextInt());
    System.out.println(ran.nextInt());
    System.out.println(ran.nextInt());
    System.out.println(ran.nextInt());
    System.out.println(ran.nextInt());
}

这段代码,在我的机器上运行结果是这样的:


image.png

你拿过去跑,你的运行结果也一定是这样的。

这是为什么呢?

答案就在 Javadoc 上写着的:

image.png

如果用相同的种子创建了两个 Random 的实例,并且对每个实例进行了相同的方法调用序列,那么它们将生成并返回相同的数字序列。

在上面的代码中两个 -229985452 就是相同的种子,而三次 nextInt() 调用,就是相同的调用序列。

所以,他们生成并返回相同的、看起来是随机的数字。

网络异常,图片无法展示
|

image.png

在 new Random() 的时候,不会去指定一个值。

我们都知道 Random 是一个伪随机算法,而构建的时候指定了 seed 参数的就是一个更加伪的伪随机算法了。

因为如果我可以推测出你的 seed 的话,或者你的 seed 泄露了,那么理论上我就可以推测出你随机数生成序列。

这个我已经在前面的代码中演示了。


再看看问题


在前面稍微解释了 “seed” 的关键之处之后,我们再回过头去品一品这个问题,大概就能看出点端倪了。

image.png

主要看这个循环里面的代码。

首先 nextInt(27) 就限定了,当前返回的数 k 一定是在 [0,27) 之间的一个数字。

如果返回 0,那么循环结束,如果不为零。则做一个类型转换。

接下来就是一个 char 类型的强制转换。

看到数字转 char 类型,就应该条件反射的想到 ascii 码:

image.png

image.png

所以,下面这个代码的范围就是 [96+1,96+26]:

'`' + k

也就是 [97,122],即对应 ascii 码的 a-z。

所以,我带你再把上面的演示代码拆解一下。

首先 new Random(-229985452).nextInt(27) 的前五个返回是这样的:

image.png

而 new Random(-147909649).nextInt(27) 的前五个返回是这样的:

image.png

所以,对照着 ascii 码表看,就能看出其对应的字母了:

8 + 96 = 104 --> h

5 + 96 = 101 --> e

12 + 96 = 108 --> l

12 + 96 = 108 --> l

15 + 96 = 111 --> o


23 + 96 = 119 --> w

15 + 96 = 111 --> o

18 + 96 = 114 --> r

12 + 96 = 108 --> l

4 + 96 = 100 --> d

现在,对于这一段谜一样的代码为什么输出了 “hello world” 的原因,心里是不是拨开云雾见青天,心里跟明镜儿似的。

看穿了,也就是一个小把戏而已。

image.png

目录
相关文章
|
C语言
14.C语言:用scanf函数输出数据
14.C语言:用scanf函数输出数据
318 0
|
Web App开发 搜索推荐 机器人
真假搜索引擎蜘蛛IP地址和UA(UserAgent)大全
真假搜索引擎蜘蛛IP地址和UA(UserAgent)大全 这些信息不是一直不变的,这里仅供参考。
2123 0
真假搜索引擎蜘蛛IP地址和UA(UserAgent)大全
|
缓存 安全 Java
全面解读ConcurrentHashMap:Java中的高效并发数据结构
全面解读ConcurrentHashMap:Java中的高效并发数据结构
2531 2
|
存储 开发工具 git
Git日常问题: 什么是LFS?及其错误解决办法
Git LFS(Git Large File Storage)是Git的一个扩展,用于管理大型文件,通过将大文件的实际内容存储在远程服务器上,而Git仓库中只保留一个轻量级的文本指针,从而加速仓库操作的速度并减小仓库大小。当遇到Git LFS相关错误时,通常需要安装Git LFS工具并按照官方文档进行配置。
1184 2
Git日常问题: 什么是LFS?及其错误解决办法
|
安全 网络安全 网络虚拟化
100个网络技术中英文术语,收藏收藏!
【10月更文挑战第22天】
1675 5
100个网络技术中英文术语,收藏收藏!
|
5G 网络架构
怎么区分5G卡片开启的网络类型是NSA(非独立组网)还是SA(独立组网)
要确定5G卡片开启的网络类型是NSA(非独立组网)还是SA(独立组网),你通常需要进行以下操作:
|
Java API 数据安全/隐私保护
【亮剑】如何在Java项目中结合Spring框架实现邮件发送功能
【4月更文挑战第30天】本文介绍了如何在Java项目中结合Spring框架实现邮件发送功能。首先,需在`pom.xml`添加Spring和JavaMail依赖。然后,在`applicationContext.xml`配置邮件发送器,包括SMTP服务器信息。接着,创建一个使用依赖注入的`EmailService`类,通过`JavaMailSender`发送邮件。最后,调用`EmailService`的`sendSimpleEmail`方法即可发送邮件。最佳实践包括:使用配置管理敏感信息,利用`MimeMessage`构造复杂邮件,异常处理和日志记录,以及在大量发送时考虑使用邮件队列。
270 1
|
JavaScript 前端开发 索引
用四种方法实现轮播图
用四种方法实现轮播图
|
SQL Oracle 算法
Mybatis: 兼容Oracle数据库批量插入语句
当前项目需要在不同环境下部署,不同环境下有不同的数据库,有pg、oracle、mysql等,项目中的所有sql均为pg数据库相关的sql,由于oracle数据库比较特殊所以需要兼容相关的sql。批量插入的语句,pg和oracle有着较大的差别,不能同一条语句兼顾两种数据库:,所以需要查找方案来解决。
1321 0
|
运维 监控 负载均衡
HttpClient连接池设置引发的一次雪崩
HttpClient连接池设置引发的一次雪崩