Java Random 含参与不含参构造函数的区别

##Random 通常用来作为随机数生成器,它有两个构造方法:

        Random random = new Random();
        Random random2 = new Random(50);

1.不含参构造方法:

public Random() {
    setSeed(System.nanoTime() + seedBase);
    ++seedBase;
}

2.含参构造方法:

public Random(long seed) {
    setSeed(seed);
}

都调用的 setSeed 方法:

public synchronized void setSeed(long seed) {
    this.seed = (seed ^ multiplier) & ((1L << 48) - 1);
    haveNextNextGaussian = false;
}

###可以看到,不含参构造方法每次都使用当前时间作为种子,而含参构造方法是以一个固定值作为种子

##什么是种子 seed 呢?

seed 是 Random 生成随机数时使用的参数:

Random 中最重要的就是 next(int) 方法,使用 seed 进行计算:

protected synchronized int next(int bits) {
    seed = (seed * multiplier + 0xbL) & ((1L << 48) - 1);
    return (int) (seed >>> (48 - bits));
}

其他 nextXXX 方法都是调用的 next()。

比如 nextInt(int):

public int nextInt(int n) {
    if (n <= 0) {
        throw new IllegalArgumentException("n <= 0: " + n);
    }
    if ((n & -n) == n) {
		//调用 next()
        return (int) ((n * (long) next(31)) >> 31);
    }
    int bits, val;
    do {
        bits = next(31);
        val = bits % n;
    } while (bits - val + (n - 1) < 0);
    return val;
}

再比如 nextBoolean():

//也是调用的 next()
public boolean nextBoolean() {
    return next(1) != 0;
}

##举个栗子:

@Test
public void testRandomParameter(){
    System.out.println("Random 不含参构造方法:");
    for (int i = 0; i < 5; i++) {
        Random random = new Random();
        for (int j = 0; j < 8; j++) {
            System.out.print(" " + random.nextInt(100) + ", ");
        }

        System.out.println("");
    }

    System.out.println("");

    System.out.println("Random 含参构造方法:");
    for (int i = 0; i < 5; i++) {
        Random random = new Random(50);
        for (int j = 0; j < 8; j++) {
            System.out.print(" " + random.nextInt(100) + ", ");
        }
        System.out.println("");
    }
}

分别用含参构造方法和不含参构造方法创建 5 个随机生成器对象,每个随机生成器再生产 8 个随机数,对比下结果:

再运行一次:

##总结:

通过上述例子可以发现:

随机数是种子经过计算生成的。

  • 不含参的构造函数每次都使用当前时间作为种子,随机性更强
  • 而含参的构造函数其实是伪随机,更有可预见性

原文地址:https://www.cnblogs.com/shizhijie/p/8258668.html

时间: 2024-10-20 14:20:38

Java Random 含参与不含参构造函数的区别的相关文章

No default constructor for entity Java无参构造函数

异常 org.hibernate.InstantiationException: No default constructor for entity 当查询的时候返回的实体类是一个对象实例,是hibernate动态通过反射生成的 反射的Class.forName("className").newInstance();需要对应的类提供一个无参构造函数, 出现这种问题是一般都是实体类有一个有参的构造 ,没有无参构造, 下面说一下有参构造 和无参构造 1,每一个类在默认情况下,都会有一个无参

子类构造函数是否会默认调用父类的无参构造函数

1 package test; 2 3 public class TestB { 4 5 public TestB() { 6 System.out.println("TestB的无参构造函数..."); 7 } 8 9 } 1 package test; 2 3 public class TestA extends TestB { 4 5 public TestA(int i) { 6 System.out.println(i); 7 } 8 9 public static void

C++类到底存不存在缺省无参构造函数

学习C++的时候有个问题老是忘,就是缺省无参构造函数,说的是定义类的时候,如果类本身没有构造函数,则调用一个缺省的无参构造函数,如果有构造函数,则就一定要按照构造函数的方式调用,这意味着如果定义了一个有参数的构造函数,那么在定义类的时候就一定要调用有参的那个构造函数,缺省的无参构造函数就不存在了. 说实话,当时学的时候感觉有点不可思议,但还是稀里糊涂的接受了,很多教材也是这样写的,但是真是这样吗,最近折腾llvm,它的IR对编译器动作表示的比较清晰,特意反汇编了一把看看,代码如下: #inclu

c#之有参和无参构造函数,扩展方法

例如在程序中创建 Parent类和Test类,在Test有三个构造函数,parent类继承Test类,那么我们可以在Test类自身中添加 扩展 方法吗? 答案:是不可以的.因为扩展方法必须是静态的,且静态方法是不存在构造函数的. 先看一段代码: public class Test { public Test() { Console.WriteLine("这是无参的构造函数"); } public Test(string name) { Console.WriteLine(string.

MultiThread(VS2013 MFC多线程-含源码-含个人逐步实现文档)

原文:http://download.csdn.net/download/jobfind/9559162 MultiThread(VS2013 MFC多线程-含源码-含个人逐步实现文档).rar

子类构造函数会默认调用父类无参构造函数

1.调用父类无参构造函数是默认的! 子类的构造方法默认都去访问了父类的无参构造方法:在子类中的构造方法后都有一行默认语句 base() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Fu {   public Fu()     {         Console.WriteLine("fu");     } } class Zi : Fu {     public Zi()         : base()//不管是否显式调用,控制台都会输出fu

java Random类详解

java Random类位于java.util包下,主要用来生成随机数,本文详解介绍了Random类的用法,希望能帮到大家 Random类 (java.util) Random类中实现的随机算法是伪随机,也就是有规则的随机.在进行随机时,随机算法的起源数字称为种子数(seed),在种子数的基础上进行一定的变换,从而产生需要的随机数字. 相同种子数的Random对象,相同次数生成的随机数字是完全相同的.也就是说,两个种子数相同的Random对象,第一次生成的随机数字完全相同,第二次生成的随机数字也

“全栈2019”Java第三十九章:构造函数、构造方法、构造器

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第三十九章:构造函数.构造方法.构造器 下一章 "全栈2019"Java第四十章:this关键字 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorhaf,回复"Java学习小组&q

为什么“含头不含尾”是科学的

什么是美? 在理工科领域,简单就是美.计算机软件领域也是一样.简单意味着易理解,不容易出Bug. 从0开始的数组下标 在计算机编程中数组的下标往往是从0开始,而老百姓熟悉的是从1开始的数字.按道理从1开始更自然更容易接受,也就意味着简单,可为什么多数的编程语言的数组是从零开始的呢?这个可不仅仅是习惯和语言设计者的个人的喜好的问题. 一句话,从0开始能够在许多方面带来运算的简单化.比如一维数组和二维数组的换算.如果我们规定下标,都从1开始,那么一维数组的下标就会是从1到9对应的二维数组的坐标就是(