生成随机数(例子)
import java.util.Scanner;
import java.util.Random;
//import java.util.*; // * 表示调用util中的所有包,就不用上述一样要写两行
public class text1 {
/*
猜数字游戏
*/
public static void main(String[] args) {
Scanner scan = new Scanner (System.in);
//生成随机数
Random random = new Random();
int randNum = random.nextInt(100);//[0-100) 左闭右开
System.out.println(randNum);
}
}
首先我们random类生成随机数,输出结果:
相对于C中的rand函数生成随机数,如果你不多使用时间戳的话,这个rand函数生成的数是一个有有顺序的乱序的数,每一次生成的数的顺序都是一样的,则时候我们需要使用时间戳来实现真正的随机数。
但是在java中不一样,java中的随机数是每一次随机出的数据都不一样,是真正的随机数,不需要像c语言中需要利用时间戳来实现随机数
但是在Java中也是有时间戳的:
Scanner scan = new Scanner (System.in);
//生成随机数
Random random = new Random(20230316);
int randNum = random.nextInt(100);//[0-100) 左闭右开
System.out.println(randNum);
当我们在Random方法中输入上述格式的日期,那么这个随机值就会根据这个时间戳来实现随机数,而且是定值。
输出结果:
关于Random方法使用:
int randNum = random.nextInt(100) + 100;//[100-200) 左闭右开
如果一个包是java.lang ,那么不需要手动导入,可以直接使用里面的方法。
如果看到返回值是如下的:
前面带一个static 的,那么就可以直接这么写:
如果某方法返回值是如下的:
则是这样写:
也就是说,需要一个对于类型的变量来接收这个“值”,然后再对这个变量进行需要的操作。
我们在java中对于 1/i 这种类型的式子需要注意,如果我们计算的时候需要输出小数 可以写成
1.0 / i 这种样子,不然 1/i (此时i = 2) 那么结果是0,不是0.5。
for(int i = 1;i <= 3;i++)
{
System.out.println(1 / i);
System.out.println(1.0 / i);
System.out.println("第" + i + "次");
}
输出结果:
计算某个数的二进制表示里有多少个1:
方法一:
public class textdome {
public static void main(String[] args)
{
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int count = 0;
// 0000 11111
//& 0000 0001
//->0000 0001 count++
for(int i = 0;i < 32;i++)
{
if(((n >> i) & 1) == 1)
{
count++;
}
}
System.out.println(count);
}
}
方法二:
public static void main(String[] args)
{
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int count = 0;
// 0000 0111 ->7
//& 0000 0110 ->6
// 0000 0110 ->6
//& 0000 0101 ->5
// 0000 0100 ->4
//& 0000 0011 ->3
// 0000 0000 ->0
while(n != 0)
{
n = n & (n - 1);
count++;
}
System.out.print(count);
}
关于ider的调试:
方法的基本用法
所谓方法就像相当于是C中的函数, 某一个方法就相当于是一个功能。能够模块化的组织代码,做到代码的重复利用,让代码更加容易理解,其实main就是一个方法,
基本语法
方法的定义
public static 返回值 方法名 (形参列表)
{
方法体;
}
方法命名应该采用小驼峰的形式,也就是说首个单词的首字母不用大写,其余后面的单词的首字母要大写
nextMyNum
如以上形式。
而之所以是public static的是因为我们写的方法需要在main函数中使用,那么在main函数中使用的方法必须是public static静态的。当然,java中也有动态的。
返回值:返回值可有可无,看需求。
例1:
public class textdome {
//求较大数
public static int maxNum(int num1,int num2)
{
return num1 < num2 ? num2 : num1;
}
public static void main(String[] args)
{
Scanner scanner = new Scanner(System.in);
int num1 = scanner.nextInt();
int num2 = scanner.nextInt();
int MaxNumber = maxNum(num1,num2);
System.out.println(MaxNumber);
}
}
方法的调用
方法中不能定义静态的变量
我们发现此时已经报错了,这是因为,我们的方法的调用是依赖于对象,而且静态变量在程序运行过程中,总是先被调用。
而方法中变量是局部变量,在方法调用结束之后会被销毁。
方法中嵌套方法
public class textdome {
//求较大数
public static int maxNum(int num1,int num2)
{
return num1 < num2 ? num2 : num1;
}
public static int maxNum_3(int num1,int num2,int num3)
{
return maxNum(maxNum(num1,num2),num3);
}
public static void main(String[] args)
{
Scanner scanner = new Scanner(System.in);
int num1 = scanner.nextInt();
int num2 = scanner.nextInt();
int num3 = scanner.nextInt();
int MaxNumber = maxNum_3(num1,num2,num3);
System.out.println(MaxNumber);
}
}
java交换变量
我们知道,在C中我们实现一个交换两个变量的值的函数,是不能直接传入数据来进行修改的,因为传入的函数之后,是函数内部的形参来接收数据,我们修改之后的数据也是形参的值,在函数调用结束之后,形参也跟着被销毁,那么我买之前的修改如同虚设。
在C中我们要想在函数里面修改main函数里面的值,就要在函数形参处传入需要修改的变量的地址,也就是对应的指针,这样才能对main函数里面的变量进行修改。
但是在java不能像C一样自由的使用指针,因为java只有按值传递,不能按地址传递,java里的指针都是写在各个方法中的,也可以理解为,java里面的指针是被包装起来的,可以直接使用包装过后的方法。所以在java中我们要在函数中修改其他的变量的值,需要使用java里面类和对象来实现。
public class textdome {
public static void main(String[] args)
{
int [] arr = {10,20};
swap(arr);
System.out.println("a = " + arr[0] + " b = " + arr[1]);
}
public static void swap(int[] arr)
{
int tmp = arr[0];
arr[0] = arr[1];
arr[1] = tmp;
}
}
方法的重载(overload)
首先我们要来理解一下重载和重写有什么区别?
假设我们需要写一个函数来实现计算两个整形int数的和:
public class textdome {
public static void main(String[] args)
{
int a = 10;
int b = 20;
int sum_Int = sumInt(a,b);
System.out.println(sum_Int);
}
public static int sumInt(int a,int b)
{
return a + b;
}
}
这时,我又需要求两个double类型的数的和:
那么此时我们用之前的求int类型两个数的和的函数就不适用了,就会报错:
我们需要重新写一个函数:
public class textdome {
public static void main(String[] args)
{
double a = 19.9;
double b = 18.8;
double sum_Double = sumDouble(a,b);
System.out.println(sum_Int);
}
public static double sumDouble(double a,double b)
{
return a + b;
}
}
而所谓重载是,我们的函数名可以是一样的:
此时我们都调用sum函数,发现int类型和double类型都可以使用。
但是需要注意的是,相同类型的不能使用,会报错:
那么重载也不是所以的同名函数都能构成重载的,构成重载的条件有四个:
- 方法名相同
- 返回值不做要求
- 参数列表必须不同(参数的个数,或者是参数的类型不同)
- 必须在同一个类当中
然后是重写,.重写是指在不同类中,将父类的方法在子类中重新写一遍,子类继承了父类原有的方法,但有时又不想继承父类原有一模一样的方法,所以就在返回类型,方法名,参数列表相同的情况下,对方法体进行修改进行重写,这就是重写。但注意的是 子类的访问修饰符不能比父类的更严格(意思就是父类的访问修饰符要更加 严谨,权限更少,父亲严格)
(转自)
在main函数里调用其他类中的方法:
我们是直接用类名来访问这个类里的静态方法:
class Text2{
public static void hello()
{
System.out.println("hello");
}
}
public class textdome {
public static void main(String[] args)
{
Text2.hello(); //hello
}
}
但是我们对于一个空对象,那么我们也是可以引用这个空对象里类的静态方法:
class Text2{
public static void hello()
{
System.out.println("hello");
}
}
public class textdome {
public static void main(String[] args)
{
Text2 text2 = null; // 创建一个空对象
text2.hello(); // hello
}
}
但是这个方式引用的话,虽然能达到效果,但是编译器会警告,我们一般不建议这样做。
需要注意的是调用静态方法需要使用其对应的类名来调用,而且如果这个方法不是静态的,那么我们这么引用就会报错:
方法的递归
既然在java中方法是相当于是C中的递归,那么方法也是有递归的。
递归的注意事项:
- 要调用方法自己本身
- 要有一个终止的条件
- 推导出递归公式
用递归实现 求n的阶乘:
public class textdome {
public static int fac(int i)
{
if(i == 1)
{
return 1;
}
return fac(i-1) * i;
}
public static void main(String[] args)
{
int num = 4;
int fac_num = fac(num);
System.out.println(fac_num); // 24
}
}
如果我们在使用函数递归的时候,没有函数递归的执行条件,就会报栈空间溢出的错:
这时因为,函数在调用的时候会,在栈上开辟空间,而我们的递归就是简单理解就是要开辟很多层的函数,也就要在栈上开辟很多空间来存储关于函数的先关内容,只有在return的时候,这个一层函数才会结束,所对应栈上的空间才会被销毁。
例二:
顺序输出一个数上的每一位数字:
public class textdome {
public static void sortInputInt(int i)
{
if(i > 9)
{
sortInputInt(i / 10);
}
System.out.println(i % 10);
}
public static void main(String[] args)
{
int num = 1234;
sortInputInt(num);
//1
//2
//3
//4
}
}
例三:
给定一个非负整数,计算这个非负整数的每一位数字之和:
public class textdome {
public static int sum_Int(int i)
{
if(i < 9)
{
return i;
}
return sum_Int(i / 10) + (i % 10);
}
public static void main(String[] args)
{
int num = 1234;
int sum = sum_Int(num);
System.out.println(sum);
}
}
例四:
求斐波那契数列的前N项和:
public class textdome {
public static int function1(int n)
{
if(n == 1 || n == 2)
{
return 1;
}
return function1(n - 1) + function1(n - 2);
}
public static void main(String[] args)
{
Scanner scanner = new Scanner(System.in);
System.out.println("请输入需要的计算的项数:");
int times = scanner.nextInt();
int sum = function1(times);
System.out.println(sum);
}
}
两个函数的递归可以理解为数的左右子树前序遍历。
但是斐波那契不适合用递归去做,只适合用来理解递归,接下来我们用循环来实现这个例子:
public class textdome {
public static int function1(int n)
{
int f1 = 1;
int f2 = 1;
int f3 = 1; //需要注意的是这地方的f3初始值不能是0
for(int i = 1; i <= n ;i++)
{
f3 = f1 + f2;
f1 = f2;
f2 = f3;
}
return f3;
}
public static void main(String[] args)
{
int n = 5; // 项数
int sum = function1(n);
System.out.println(sum);
}
}
或者是:
public static int fibo(int n){
int[] nums = new int[n];
for (int i = 0; i < n; i++) {
if(i==0 || i==1)
nums[i]=1; //第一和第二位填入1
else
nums[i]=nums[i-1]+nums[i-2]; //除第一第二位外其余数据等于前两位之和
}
return nums[n-1];
}
private 私有的 修饰词
关于同一类内,方法外的变量引用:
public class textdome {
private float f = 1.0f;
int m = 12;
static int n = 1;
public static void main(String[] args)
{
textdome t = new textdome();
n = 1; //可以访问
textdome.m; // 不能访问,因为m不是静态的
t.m; // 不能访问,因为m不是静态的
t.f = 1; // 可以访问
t.f = 1.0 //不能访问,因为f是float类型,1.0默认是double类型
}
}
private 修饰的变量只能再定义这个变量的类中使用,不能在其他类使用。
例子:
//java 文件 1
public class textdome {
public class Person
{
private String name = "person";
int age = 0;
}
// java 文件 2
public class Child extends Person
{
public String grade;
public static void main(String[] args)
{
Person p = new Child();
System.out.println(p.name);
}
}
}
其中的name变量就不能再下面这个类中调用。
关于静态变量的调用例子:
public class textdome {
private static int x = 100;
public static void main(String[] args)
{
textdome ttd1 = new textdome();//1
ttd1.x++;
textdome ttd2 = new textdome();//2
ttd2.x++;
ttd1 = new textdome();//3
ttd1.x++;
textdome.x--;//4
System.out.println("x = " + x);
}
}
上述的 代码 1 2 3 都是多余操作,对于静态变量而言 4 操作就能直接调用静态变量。
1 2 3操作是调用不是静态变量的变量。
因为静态是最先被创建和操作的,我们可以先对静态变量进行这样操作:
public class textdome {
static int cut = 6;
static
{
cut += 3;
}
public static void main(String[] args)
{
System.out.println("cut = " + cut); //3
}
static
{
cut /= 3;
}
}
关于 toString 方法的重写:
class Text2{
public String toString()
{
System.out.print("aaa");
return "bbb";
}
}
public class textdome {
public static void main(String[] args)
{
System.out.println(new Test2());
}
}
关于this
例题:
定义一个类,计算没有初始值的num1 和 num2 两个数的加减乘除:
class Calculator{
private int num1;
private int num2;
public int add()
{
// 在同类中使用this来访问同类中的非静态数据
return this.num1 + this.num2;
}
public int sub()
{
return this.num1 - this.num2;
}
public int mul()
{
return this.num1 * this.num2;
}
public int dev()
{
return this.num1 / this.num2;
}
}
但是这个是类,不是方法,那么我们而且这个类里面的变量是 private的,那么我们该如何传入值呢?
首先我们可以使用idea里面的模板来快速实现set和get函数:
首先我们按住 Alt + ins,调出generate界面:
然后点击 Getter and Setter :
然后选择你要创建set和get的变量:
然后就会生成对应变量的get和set函数:
class Calculator{
private int num1;
private int num2;
public int getNum1() {
return num1;
}
public void setNum1(int num1) {
this.num1 = num1;
}
public int getNum2() {
return num2;
}
public void setNum2(int num2) {
this.num2 = num2;
}
public int add()
{
// 在同类中使用this来访问同类中的非静态数据
return this.num1 + this.num2;
}
public int sub()
{
return this.num1 - this.num2;
}
public int mul()
{
return this.num1 * this.num2;
}
public int dev()
{
return this.num1 / this.num2;
}
}
之后我们就可以使用get和set函数来对类中的值赋值了:
public class textdome {
public static void main(String[] args)
{
Calculator calculator = new Calculator();
calculator.setNum1(10);
calculator.setNum2(20);
System.out.println("加法");
int addNum = calculator.add();
System.out.println(addNum);
}
}
例子
实现交换两个变量的值,要求交换实参的值:
class MyValue
{
private int val;
public int getVal() {
return val;
}
public void setVal(int val) {
this.val = val;
}
}
public class textdome {
public static void swap(MyValue myValue1,MyValue myValue2)
{
int tmp = myValue1.getVal();
myValue1.setVal(myValue2.getVal());
myValue2.setVal(tmp);
}
public static void main(String[] args)
{
//创建第一个对象
MyValue myValue1 = new MyValue();
myValue1.setVal(10);
//创建第二个对象
MyValue myValue2 = new MyValue();
myValue2.setVal(20);
System.out.println(myValue1.getVal());
System.out.println(myValue2.getVal());
System.out.println("交换之后");
//交换
swap(myValue1,myValue2);
System.out.println(myValue1.getVal());
System.out.println(myValue2.getVal());
}
}
我们先创建了一个类,这个类中有一个private的变量-val,然后修改这边变量的函数set和get,然后我们在main函数中创建了两个这个类的对象,然后构建swap方法修改这两个对象中的val值。
class MyValue
{
}
,
这个和C中用利用函数和指针修改main函数中的实参的值不太一样,看上去比较麻烦,其实我们还可以这样写:
我们在定义类的时候,把val 变量的修饰词改为public:
class MyValue
{
public int val;
}
然后我们的swap方法实现就可以像C中一样直接进行赋值了,就不再需要set和get函数,同样我们在main函数中给定值也是一样的,可以直接进行赋值,不在需要set和get函数:
class MyValue
{
public int val;
}
public class textdome {
public static void swap(MyValue myValue1,MyValue myValue2)
{
int tmp = myValue1.val;
myValue1.val = myValue2.val;
myValue2.val = tmp;
}
public static void main(String[] args)
{
//创建第一个对象
MyValue myValue1 = new MyValue();
myValue1.val = 10;
//创建第二个对象
MyValue myValue2 = new MyValue();
myValue2.val = 20;
System.out.println(myValue1.val);
System.out.println(myValue2.val);
System.out.println("交换之后");
//交换
swap(myValue1,myValue2);
System.out.println(myValue1.val);
System.out.println(myValue2.val);
}
}
这就是引用,因为java当中只有按值传递,我们这里传的对象,实际上是一个引用。