Java随机数之System/Random/SecureRandom详解

这篇具有很好参考价值的文章主要介绍了Java随机数之System/Random/SecureRandom详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本系列为:从零开始学Java,为千锋教育资深Java教学老师独家创作

致力于为大家讲解清晰Java学习相关知识点,含有丰富的代码案例及讲解。如果感觉对大家有帮助的话,可以【点个关注】持续追更~

文末有本文重点总结!关于技术类问题,也欢迎大家和我们沟通交流!

前言

我们在解决实际问题时,除了经常需要对数字、日期、时间进行操作之外,有时候还需要对系统进行设置,另外还需要生成一些随机数字。

那么我们又该如何实现这些需求呢?接下来我们会带着大家来学习一下Java中的另几个常用类,包括System、Random、SecureRandom等。


全文大约 【4000】字, 不说废话,只讲可以让你学到技术、明白原理的纯干货!本文带有丰富的案例及配图,让你更好地理解和运用文中的技术概念,并可以给你带来具有足够启迪的思考…

一. System类

1. 简介

System类位于java.lang包中,代表着当前Java程序的运行平台,系统级的很多属性和控制方法都放在该类中。

由于该类的构造方法是private的,所以我们无法直接通过new的方式来创建该类的对象。System类提供了一些静态变量和静态方法,允许我们直接通过System类来调用这些类变量和类方法。在System类中,虽然有挺多的静态变量和方法,但对我们来说,只需记住一些常用的即可。

1.1 常用静态变量

System类中常用的静态变量有如下几个:

● PrintStream out:标准输出流;

● InputStream in:标准输入流;

● PrintStream err:标准错误输出流;

1.2 常用静态方法

System类中常用的静态方法有如下几个:

● currentTimeMillis():返回当前的计算机时间;

● exit():终止当前正在运行的 Java 虚拟机;

● gc():请求系统进行垃圾回收,完成内存中的垃圾清除;

● getProperty():获得系统中属性名为 key 的属性对应的值;

● arraycopy():进行数组复制,即从指定源数组中复制一个数组。

接下来我们就把以上这些静态变量和静态方法的基本使用,给大家简要介绍一下。

2. 静态变量的使用

首先我们来看看System类中几个常用静态变量该如何使用。

2.1 out

out静态变量属于PrintStream类型,是System类中的标准输出流,用于接收要输出的数据。out中的数据内容通常会输出到显示器,或用户指定的某个输出目标。其实对我们来说,out并不陌生,可以说在我们之前的案例中经常使用,尤其是out中的print方法,最近我们一直在使用。但我们要搞清楚,print属于PrintStream流的方法,并不是 System类的方法。

//输出字符串不换行
System.out.print("Hello World");

//输出字符串并换行
System.out.println("Hello World");

2.2 in

in静态变量属于InputStream类型,是System类中的标准输入流,用于接收输入的数据。in通常是对应着键盘的输入,或是用户指定的另一个输入源。我们在之前的案例中,也简单使用过in常量,但它没有out用的那么频繁。
Java随机数之System/Random/SecureRandom详解

上面的这个案例,System.in.read()语句可以读入一个字符,read()方法是InputStream类拥有的方法。变量c必须用 int 类型,而不能用char类型,否则可能会丢失精度而导致编译失败。另外上面的程序,如果输入的是汉字将不能正常输出。如果我们想正常输出汉字,需要把 System.in声明为 InputStreamReader类型的实例。比如

InputStreamReader in=new InputStreamReader(System.in,"GB2312"),此时就可以读入完整的Unicode码,才能显示正常的汉字。

2.3 err

err静态变量属于PrintStream类型,是System类中的标准错误输出流,用于接收要输出的数据。err中的数据内容通常会输出到显示器,或用户指定的某个输出目标。其用法与System.out一样,只是不需要我们提供参数就可以输出错误信息,也可以用来输出用户指定的其他信息,包括一些变量的值。

//err的用法
System.err.println();

//输出指定的内容
System.err.println("错误信息");

以上这几个静态变量都很简单,大家记住其用法即可。

3. 静态方法的使用

接下来再跟大家说说System类中的几个常用静态方法的用法

3.1 currentTimeMillis()方法

currentTimeMillis()方法用于返回当前计算机的时间戳,时间格式是当前计算机的时间与GMT时间(格林尼治时间),自1970年 1月 1日 0时 0分 0秒以来所经历的毫秒数,我们一般用它来测试程序的执行时间。通过调用currentTimeMillis()方法,我们可以获得一个长整型的数字,该数字是以差值表达的当前时间。其实currentTimeMillis()方法我们在之前的文章中已经详细讲解过,这里就不再细说了。

long time = System.currentTimeMillis();

3.2 exit()方法

exit()方法用于终止当前正在运行的Java虚拟机,也就是可以用于退出程序。该方法需要一个整型的status参数,0表示正常退出,非零表示异常退出。我们使用该方法,可以在图形界面编程中实现程序的退出功能。该方法的用法如下:

public class Demo01 {
	public static void main(String[] args) {
		//exit的用法
		try {
            //睡眠5秒
			Thread.sleep(5000);
			//5秒后正常退出程序
			System.exit(0);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

3.3 gc()方法

gc()方法用于请求对系统主动进行垃圾回收,完成内存中的垃圾清除。但系统是否会立刻回收这些垃圾,却取决于系统中垃圾回收算法的具体实现,以及系统执行时的具体情况。一般我们在开发时不会主动调用该方法,有时候调用了也未必有效果。

//主动进行垃圾回收
System.gc();

3.4 getProperty()方法

getProperty()方法可以根据指定的key,获得系统中对应的某些属性值,系统中常见的属性名及其属性如下表所示:

Java随机数之System/Random/SecureRandom详解

public class Demo03 {

	public static void main(String[] args) {
		//getProperty的用法
		
		//获取java版本
		String version = System.getProperty("java.version");
		System.out.println("Java版本:"+version);
		
		//获取java安装目录
		String home = System.getProperty("java.home");
		System.out.println("Java目录:"+home);
		
		//系统名称
        String name = System.getProperty("os.name");
        System.out.println("操作系统名称:"+name);
        
        //用户名称
        String user = System.getProperty("user.name");
        System.out.println("当前用户名称:"+user);
	}

}

3.5 arraycopy()

arraycopy()方法用于数组复制,可以从指定的源数组中复制出一个数组,复制会从指定的位置开始,到目标数组的指定位置结束。arraycopy()方法一般有5个参数,其中,src表示源数组,srcPos表示从源数组中复制的起始位置,dest表示目标数组,destPos表示要复制到的目标数组的起始位置,length表示复制的个数。

public class Demo04 {

	public static void main(String[] args) {
		//arraycopy的用法
		
		//源数组
		char[] srcArray = {'A','B','C','D'};
		//目标数组
        char[] destArray = {'1','2','3','4','5'};
        
        //进行数组复制
        System.arraycopy(srcArray,1,destArray,1,2);
        
        System.out.println("遍历源数组:");
        for(int i = 0;i < srcArray.length;i++) {
            System.out.println("源数组中的每个元素:"+srcArray[i]);
        }
        
        System.out.println("遍历目标数组:");
        for(int j = 0;j < destArray.length;j++) {
            System.out.println("新数组中的每个元素:"+destArray[j]);
        }
	}

}

二. Random随机类

1. 简介

我们在开发时,除了操作一些固定的数字之外,有时候还要操作一些不确定的随机数。Java中给我们提供了两种生成指定范围内随机数的方法:

● 使用Random类:伪随机数类,用来创建伪随机数。所谓伪随机数,就是指我们只要给定一个初始的种子,产生的随机数序列是完全一样的;

● 调用Math类的random()方法:Math.random()内部其实是在调用Random类,它也是伪随机数,但我们无法指定种子。

Random类为我们提供了比较丰富的随机数生成方法,比如nextInt()、nextLong()、nextFloat()、nextDouble()等方法。这些方法可以产生boolean、int、long、float、byte数组以及double类型的随机数,这是它比random()方法更好的地方,random()方法只能产生0~1之间的double类型随机数。

而且Random类提供的所有方法,生成的随机数字都是均匀分布的,也就是说区间内部的数字生成的概率是均等的。Random类位于java.util包中,该类有如下两个常用的构造方法:

● Random():默认利用当前系统的时间戳作为种子数,使用该种子数构造出Random对象。

● Random(long seed):使用单个的long类型参数,创建一个新的随机数生成器。

2. 常用API方法

在Random类中,有如下一些常用的API方法供我们操作随机数:

方法 说明
boolean nextBoolean() 生成一个随机的 boolean 值,生成 true 和 false 的值概率相等
double nextDouble() 生成一个随机的 double 值,数值介于 [0,1.0),含 0 而不包含 1.0
int nextlnt() 生成一个随机的 int 值,该值介于 int 的区间,也就是 -231~231-1。如果需要生成指定区间的 int 值,则需要进行一定的数学变换
int nextlnt(int n) 生成一个随机的 int 值,该值介于 [0,n),包含 0 而不包含 n。如果想生成指定区间的 int 值,也需要进行一定的数学变换
void setSeed(long seed) 重新设置 Random 对象中的种子数。设置完种子数以后的 Random 对象和相同种子数使用 new 关键字创建出的 Random 对象相同
long nextLong() 返回一个随机长整型数字
boolean nextBoolean() 返回一个随机布尔型值
float nextFloat() 返回一个随机浮点型数字
double nextDouble() 返回一个随机双精度值

3. 基本用法

接下来我们通过一个案例,来给大家讲解一下上述方法该如何使用。

import java.util.Random;

public class Demo07 {

	public static void main(String[] args) {
		// 随机类生成随机数
		Random r = new Random();
		
		// 生成[0,1.0]区间的小数
		double d1 = r.nextDouble();
		System.out.println("d1="+d1);
		
		// 生成[0,10.0]区间的小数
		double d2 = r.nextDouble() * 10;
		System.out.println("d2="+d2);
		
		// 生成[0,10]区间的整数
		int i1 = r.nextInt(10);
		System.out.println("i1="+i1);
		
		// 生成[0,25)区间的整数
		int i2 = r.nextInt(30) - 5;
		System.out.println("i2="+i2);
		
		// 生成一个随机长整型值
		long l1 = r.nextLong();
		System.out.println("l1="+l1);
		
		// 生成一个随机布尔型值
		boolean b1 = r.nextBoolean();
		System.out.println("b1="+b1);
		
		// 生成一个随机浮点型值
		float f1 = r.nextFloat();
		System.out.println("f1="+f1);
	}

}

但是我们从上面的案例中,会发现每次生成的随机数可能都是不同的,并没有体现出伪随机数的特性,这是为什么呢?其实这是因为我们创建Random实例时,如果没有给定种子,默认是使用系统的当前时间戳作为种子。因此每次运行时,种子都不同,所以得到的伪随机数序列就不同。如果我们在创建Random实例时指定一个固定的种子,就会得到完全确定的随机数序列。

三. SecureRandom类

1. 简介

之前给大家说过,Random是一种伪随机数类。这时候就有小伙伴问了,那有没有真随机数类呢?

当然是有的!

SecureRandom就是一种真随机数!

从原理来看,SecureRandom内部使用了RNG (Random Number Generator,随机数生成)算法,来生成一个不可预测的安全随机数。但在JDK的底层,实际上SecureRandom也有多种不同的具体实现。有的是使用安全随机种子加上伪随机数算法来生成安全的随机数,有的是使用真正的随机数生成器来生成随机数。实际使用时,我们可以优先获取高强度的安全随机数生成器;如果没有提供,再使用普通等级的安全随机数生成器。但不管哪种情况,我们都无法指定种子。

因为这个种子是通过CPU的热噪声、读写磁盘的字节、网络流量等各种随机事件产生的“熵”,所以这个种子理论上是不可能会重复的。这也就保证了SecureRandom的安全性,所以最终生成的随机数就是安全的真随机数。

尤其是在密码学中,安全的随机数非常重要。如果我们使用不安全的伪随机数,所有加密体系都将被攻破。因此,为了保证系统的安全,我们尽量使用SecureRandom来产生安全的随机数。

2. 基本使用

SecureRandom给我们提供了 nextBoolean()、nextBytes()、nextDouble()、nextFloat()、nextInt()等随机数生成方法,如下图所示:

Java随机数之System/Random/SecureRandom详解

接下来我们就通过一个案例,来看看到底该如何生成一个安全的随机数。

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;

public class Demo05 {

	public static void main(String[] args) {
		//SecureRandom真随机数的用法
		
		SecureRandom sr = null;
        try {
        	//获取高强度安全随机数生成器实例对象
            sr = SecureRandom.getInstanceStrong(); 
        } catch (NoSuchAlgorithmException e) {
        	//处理异常,获取普通的安全随机数生成器
            sr = new SecureRandom(); 
        }
        
        //生成16个随机数
        byte[] buffer = new byte[16];
        //用安全随机数填充buffer
        sr.nextBytes(buffer); 
        System.out.println("随机数="+Arrays.toString(buffer));
        
        //生成100以内的随机整数
        int nextInt = sr.nextInt(100);
        System.out.println("随机数="+nextInt);
	}

}

四. 结语

至此,就把与系统类、伪随机数、真随机数等相关的类给大家介绍完了,这样我们就把开发时的一些常见类介绍完毕了。今天的重点内容是:

● System:代表着当前Java程序的运行平台,系统级的很多属性和控制方法都放在该类中;

● Random:生成伪随机数;

● SecureRandom:生成安全的真随机数。文章来源地址https://www.toymoban.com/news/detail-456953.html

到了这里,关于Java随机数之System/Random/SecureRandom详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JavaSE基础(三)—— 程序流程控制、Random随机数

    目录 一、顺序结构 二、分支结构 1. if 1.1 if分支有三种格式​编辑 2. switch 2.1 if、switch分支各自适合做什么业务场景 3. switch的穿透性 三、循环结构  1. for 循环​编辑 2. while 循环 2.1 什么时候用for循环,什么时候用while循环 3. do-while循环 4. 三种循环的区别 5. 死循环 6

    2024年02月02日
    浏览(42)
  • Python生成随机数的一个标准库-random

    Random库Python中用于生成随机数的一个标准库。计算机没有办法产生真正的随机数,但它可以产生伪随机数。 伪随机数是计算机按照一定的运算规则产生的一些数据,只不过这些数据表现为随机数的形式。计算机中采用梅森旋转算法生成为随机序列,序列中的每一个元素就是伪

    2023年04月26日
    浏览(33)
  • Python random模块(获取随机数)常用方法和使用例子

    嗨喽,大家好呀~这里是爱看美女的茜茜呐 random.random random.random()用于生成一个0到1的随机符点数: 0 = n 1.0 random.uniform random.uniform(a, b),用于生成一个指定范围内的随机符点数,两个参数其中一个是上限,一个是下限。 如果a b,则生成的随机数n: a = n = b。如果 a b, 则 b = n = a

    2024年01月24日
    浏览(52)
  • 【JavaSE API 】生成随机数的2种方法:Random类和Math类的Random方法

    Random类和Math类的random方法都可以用来生成随机数 而Math类的random方法则是 基于系统时间 的伪随机数生成器,= 0.0 , 1.0的随机double值范围[0,1)。例如: double num1 = Math.random() * 5 + 4;//范围[4,9) Random类是 基于种子 的伪随机数生成器,有含参数和不含参数两种构造方式,不含参数的

    2024年02月07日
    浏览(43)
  • C++ 标准库随机数:std::default_random_engine

    库头文件 #include random  

    2024年02月08日
    浏览(38)
  • 【LINUX相关】生成随机数(srand、/dev/random 和 /dev/urandom )

    在一个循环中,生成多组随机值,发现最终的结果都一样,结果是调用的函数如下,在函数中设置了随机种子,且是以秒为单位,那么在一秒类,由于都是用一个种子,srand又是伪随机,所以最终生成的都是同一组随机字符。 2.1 修改种子 (1)将 srand(time(NULL)); 放到循环外面

    2024年02月12日
    浏览(37)
  • R语言【base】——.Random.seed(),RNGkind(),RNGversion(),set.seed():随机数生成器

    Package  base  version 4.2.0 .Random.seed是一个整数向量,包含R中生成随机数的随机数生成器(RNG)状态。它可以保存和恢复,但不应该被用户更改。 RNGkind是一个更友好的接口,用于查询或设置正在使用的RNG类型。 RNGversion在早期的R版本中可以用来设置随机生成器(为了再现性)。 set

    2024年02月22日
    浏览(39)
  • Jmeter-BeanShell脚本中for循环里面使用random随机数函数,每次生成的都一样

    预想的是每次循环生成的随机数不一样,但实际使用Random函数生成的是重复的。 以下是部分原代码: 生成的updateList为: [{“id”:235214718648462,“dataId”:null,“data”:6708,“type”:“number”}, {“id”:318239582208002,“dataId”:333989510397954,“data”:6708,“type”:“number”}, {“id”:33398948

    2024年01月20日
    浏览(45)
  • 【Python】蒙特卡洛模拟 | PRNG 伪随机数发生器 | 马特赛特旋转算法 | LCG 线性同余算法 | Python Random 模块

          猛戳订阅!  👉 《一起玩蛇》🐍 💭 写在前面: 本篇博客将介绍经典的伪随机数生成算法,我们将  重点讲解 LCG(线性同余发生器) 算法与马特赛特旋转算法,在此基础上顺带介绍 Python 的 random 模块。   本篇博客还带有练习,无聊到喷水的练习,咳咳…… 学完前

    2024年02月04日
    浏览(38)
  • 一文详解安全随机数

    本文分享自华为云社区《【安全攻防】深入浅出实战系列专题-安全随机数》,作者: MDKing 。 使用随机数可分类安全场景跟非安全场景。非安全场景需要生成的越快越好。安全场景使用的随机数必须足够安全,保证不能被预测到。 常见的非安全场景: 数据的索引号、标识;

    2024年02月05日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包