Java中无返回值的方法
数学函数
Java 在数学上面的能力非常强大,有很多内置的数学函数,函数在 Java 当中也称为方法(method),在Math类中,包含了各种各样的数学函数。在编写不同类别的程序时,可能需要的函数也不同。
要想计算一个数值的平方根,可以使用sqrt方法:
double x = 4;
doublt y = Math.sqrt(x);
System.out.println(y); // result 2.0
在Java中没有幂运算,因此需要借助于Math类中的pow方法,语句:
double y = Math.pow(x,a);
floorMod方法的目的是解决一个长期存在的有关整数余数的问题,考虑表达式n%2
。所有人都知道n为偶数,这个表达式为0;n为基数这个表达式为1。除非n为负数,这个表达式则为-1;
下面考虑这样一个问题:计算一个时钟时针的位置。
这里要做一个时间调整,而且要归一化为一个0~11之间的数。
这很简单:(position + adjustment) % 12。不过,如果这个调整为负会怎么样呢?你可能会得到一个负数。所以要引入一个分支,或者使用((position +adjustment) % 12 + 12) % 12。不管怎样,总之都很麻烦。 floorMod方法就让这个问题变得容易了:floorMod(position + adjustment, 12)总会得到一个0~11之间的数。(遗憾的是,对于负除数,floorMod会得到负数结果,不过这种情况在实际中很少出现。)
我们暂时不需要了解所有的数学函数。但是有一个数学函数是我们应该知道的,而且非常实用。那就是随机数
调用数学方法和之前我们学习的 println 方法类似的,待会我们会继续说到,现在我们回到随机数上来
// 得到一个随机数
double randomOne = Math.random();
System.out.println(randomOne);
// 得到另一个随机数
double randomTwo = Math.random();
System.out.println(randomTwo);
如上代码,Math 是 Java 提供的类用于提供数学计算的,random 就是方法
Math.random() 方法用于返回一个随机数,随机数范围为 0.0 =< Math.random < 1.0。
0.40068331197074114
0.21177156791789276
每次运行都可能看见类似这样长度的随机值,你会发现这个值是一个浮点类型的数据,并且最大<1.0,最小>=0
如果我们想得到 0-9 之间的随机数字可以怎么做呢?借助 random 方法我们是可以得到随机的,但是这个方法执行的结果是一个 double 类型的数据(浮点数)
这个时候我们就需要了解一下浮点数如何转化为整数,理论上数字类型都可以转化,只是会丢失掉精度(自动去掉小数点了)。
Java 当中类型转化的语法如下
int nValue = (int) value;
我们如果想要得到 0-9 之间的随机数,那还需要乘以 10
// (value*10) 用小括号包围是因为先乘10得到结果在转化为整数
// 要不然得不到结果,这个就是数学的优先级
int nValue = (int) (value*10);
如上,这种(类型)
强制类型转换的用法就是 Java 中的类型转化语法.
最后,Java还提供了两个用于表示派和e常量的近似值:
Math.PI
Math.E
自定义方法
println()、random() 这些都是由 Java 提供的方法,当然我们也可以自己添加新的方法。
实际上我们是有过创建方法的,我们在前面一直使用的 main 方法就是我们自己定义的,虽然 main 方法有特殊的含义(它是程序执行的入口,如果要执行代码就必须要有 main 方法),但是它的语法是和其他方法一样的
// 固定的方法格式,main方法用于启动程序
public static void main(String[] args){
}
总结一下方法的语法就是
// public(公共的) static(静态) void(空类型)
public static void 方法名称(方法参数){
代码块
}
这里除了 main 和 Java 的关键字之外,方法名称可以任意的英文单词。
驼峰式命名
Java 世界里命名规范遵守“驼峰式”,骆驼有个非常明显的特点就是它的驼峰,由于它的这种非常明显的特性,编程语言模仿了这个驼峰特性,具体就是把每个单词的首字母变成大写,这样大写的字母就像驼峰一样。
比如说:用户名称如果用英文单词来表示的话就是UserName
,大家注意看一下,这个大写的 U 和 N 是不是像驼峰一样?这样的例子可以很多,比如说我的文档:MyDocument、密码:Password
小驼峰
方法名遵守的是小驼峰,和驼峰的区别就是第一个单词是小写的,所以上面的例子就可以变成如下:
// 密码
public static void password(){
//代码块
}
// 我的文档
public static void myDocument(){
//代码块
}
注意一下,这里我们只是先完成方法的定义,并没有调用方法,所以 password、myDocument 方法并不会被执行
这些都是遵守小驼峰式命名规范的,这点很重要,要不然你的 Java 代码看起来太丑了。
我们先从无参数方法开始了解。
比如说看下面的代码
// newLine 是方法名称,这个是我们自己随便定义的
public static void newLine(){
System.out.println("");
}
这段代码就是我们创建的一个自定义方法,这个方法名称就是 newLine ,紧跟着方法名的空小括号表明此方法不需要参数(注意小括号不能省掉哦,这个是代码规范)
注意一下,这里我们只是先完成方法 newLine 的定义,并没有调用方法哦
自定义方法调用
当方法被创建成功后我们就可以去执行这个方法,一般在编程语言里我们把这个行为称为:方法调用
这个 newLine 方法如何被调用呢,其实也很简单
public class Custom {
public static void main(String[] args){
System.out.println("测试");
// 这里执行一下 newLine 这个自定义方法的调用
newLine();
System.out.println("结束");
}
public static void newLine(){
System.out.println("");
}
}
我们来运行一下看看,注意看一下代码编写的顺序,一定是先定义方法,再调用方法
补充说明一下,自定义的方法都是在 class 类当中的,方法的顺序无所谓,放在 main 方法前面或者后面都可以,但是方法内是不能这样新建方法的,初学者经常会混淆格式,仔细检查 {} 是否正确就可以了
我们刚才的例子里调用了一次自定义的方法,实际上方法可以被任意的调用多次。newLine 方法里也可以调用其他方法,比如:
public class Custom {
public static void main(String[] args){
System.out.println("测试");
newLine();
newLine();
System.out.println("结束");
}
public static void newLine(){
System.out.println("");
// 调用下面的 format 方法
format();
}
//格式化输出内容,这里只是为了测试方法的调用
public static void format(){
System.out.println("------------");
}
}
现在我们来思考一下,为什么需要方法呢?
- 解决代码复用的问题:比如说 newLine 方法不需要重复编写这段逻辑
- 隐藏程序细节,这样程序更为清晰,从而降低复杂度
现在我们来改一下前面代码
public class Custom {
public static void main(String[] args) {
random();
}
/**
*生成6位随机数
*/
public static void random(){
int code = (int) ((Math.random()+1) * 100000);
System.out.println(code);
}
}
这样的代码是不是看的舒服一点,当代码这样解耦合后就可以支持多人协同开发了.
public class Custom {
public static void main(String[] args) {
random();
code();
}
/**
*生成6位随机数
*/
public static void random(){
int code = (int) ((Math.random()+1) * 100000);
System.out.println(code);
}
/**
*生成4位随机数
*/
public static void code(){
int code = (int) ((Math.random()+1) * 1000);
System.out.println(code);
}
}
对于上面两个自定义方法的代码,我们会发现random与code中有大量代码重复了,仅仅存在(int) ((Math.random()+1) * length)的差异。为了解决代码重复这个问题,我们需要引入一个新的概念,那就是方法参数。
我们可以把 100000 和 1000 这个数字定义为一个 int 类型的变量,在抽离出相同部分代码的同时,赋不同的值,通过方法参数传递过去就能解决了。现在看一下代码
public class Custom {
public static void main(String[] args) {
random(100000);
random(1000);
}
/**
*生成随机数
*/
public static void random(int length){
int code = (int) ((Math.random()+1) * length);
System.out.println(code);
}
}
大家看一下,这样代码是不厉害了很多?现在让我们来看一下这个方法参数的语法
public static void random<1>(int length)<2> {
int code = (int) ((Math.random() + 1 ) *length);
System.out.println(code);
}
- <1> 方法名称:遵循小驼峰命名
- <2> 方法参数:参数类型,参数名
实际上方法参数和声明变量并无区别,只是这个变量是要定义在方法参数这个位置里,编程语言里把这个声明的变量叫做 形参
方法调用
看了方法参数后,回头来看方法调用的问题,如果方法有了参数声明后,就必须要传入参数,否则会编译失败。
这个参数可以是变量,也可以是值,只是要特别注意数据类型要匹配,你不能给一个 int 参数 传入 String 字符串类型
编程语言里把这个传递的变量称为 实参
// 直接传值
random(100000);
// 传递变量
int len = 100000;
random(len);
多参数方法
public class MessageCode {
public static void main(String[] args) {
code(1000);
}
public static void code(int len){
int code = (int)((Math.random()+1)*len);
System.out.println("亲爱的用户,你本次的验证码是【"+code+"】");
}
}
在我们实际工作中,其实短信的文字部分(一般称为文案)经常会被调整,运营经常会提出一些文案变更的需要。
我们前面提到过方法的特性之一:隐藏程序细节,所以如果每次都要修改方法内容,那么会导致复用以及维护成本变高。所以在实际运用中,我们会把文案也定义成变量,并且支持变量的值更新。
在我们这个场景里,我们就需要定义多个参数了,让我们来看一下这段代码
public class MessageCode {
public static void main(String[] args) {
String text = "亲爱的用户,你本次的验证码是";
code(text,1000);
}
public static void code(String text,int len){
int code = (int)((Math.random()+1)*len);
System.out.println(text+"【"+code+"】");
}
}
我们在这个例子里新添加了一个参数,你会发现多个形参其实就是使用 ,
分隔一下各个参数。
有返回值方法
返回值
我们在前面了解到返回语句 return;
,大家知道返回语句的目的是中断程序执行,相信大家没有忘记 Math.random()
这个随机数方法,这个方法和我们自己写的方法有个很大的不同,那就是我们执行了Math.random()
这个方法后,是有返回结果的。这也是本节课我们要学习的知识:返回值
我们再来看一下随机数的代码
/**
* 得到验证码
*/
public static void code(int len){
// 得到随机数结果
double val = Math.random();
// 随机数结果*9+1 然后再乘以位数得到验证码
int result = (int)((val*9+1)*len);
}
这段代码大家应该是很熟悉的了,为了强调返回值,这里我们把 Math.random();
赋值给了double val
;
那我们来看一下 random 这个方法 Java 的源代码是如何写的
public static double random() {
return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble();
}
我们可以对比一下区别,其实有两处格式的不同
RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble(); 这个是另外一个 Java 方法,暂时不用管
方法返回值类型的声明
第一处不同就是方法的声明上有不同
// 验证码方法
public static void code(int len)
// 随机数方法
public static double random()
仔细观察一下,你会发现方法的格式做一下改变,把 void
换成了 double
,这个改变就是方法返回值的声明,如果这个位置的代码写的是 void
表示的是无返回值,否则就是有返回值,返回值可以是我们前面介绍的数据类型(当然还可以是其他对象,以后我们还会用到):int、String、double、boolean
所以如果我们想要定义一个有返回值的方法就需要按照这个格式来声明。
我们为什么需要给方法定义返回值类型呢?其实这个问题也很好解答,就像
Math.random()
方法一样,我们不关心方法内部的细节只想获取方法返回值的时候就可以这样做,待会通过案例来理解,现在先有个概念。
方法体返回语句的执行
第二处不同就是方法的返回语句有不同,在方法返回类型声明为 double
之后我们在方法执行的时候就必须执行 return 返回结果;
这个返回结果的类型必须和方法声明的返回值一致
说起来好像有点复杂哈,我们试一下就知道了,现在我们改造一下我们的验证码代码
public class Captcha{
public static void main(String[] args){
//打印出4位随机码
System.out.println("本次的验证码是:"+code(1000));
}
/**
* 得到验证码
*/
public static int code(int len){
// 得到随机数结果
double val = Math.random();
// 随机数结果*9+1 然后再乘以位数得到验证码
int result = (int)((val*9+1)*len);
return result;
}
}
这段代码中,我们调用了 code 方法,并得到了这个方法的结果,我们把这个结果打印出来了。
运行完之后,我们再来优化一下这个代码,很多时候我们虽然要求是 4 位验证码,但是并不知道结果是否正确(比如说如果返回了 5 位数、6 位数那就是错误的),这个时候就需要我们进行值的判断,比如上面的代码就可以是如下的。
public class Captcha{
public static void main(String[] args){
// 得到验证码
int codeValue = code(1000);
// 如果 codeValue 在1000和9999之间,那么就是正确的4位随机数
if(codeValue >= 1000 ){
if(codeValue<=9999){
System.out.println("本次的验证码是:"+codeValue);
}
}
}
/**
* 得到验证码
*/
public static int code(int len){
// 得到随机数结果
double val = Math.random();
// 随机数结果*9+1 然后再乘以位数得到验证码
int result = (int)((val*9+1)*len);
return result;
}
}
我们继续看一下结合 if 语句的返回值。 注意,如果有返回值,返回语句应该是程序的最后执行的行(大多数是最后一行,如果有 if else
语句可能就不是最后一行)
公司到季度末了准备发奖金,如果销售额<100000,奖金按 10%;销售额>=100000,奖金按 9%;销售额>300000,奖金按 7%;没有销售额,没有奖金
public class BonusDemo{
public static void main(String[] args){
int amount = bonus(0);
System.out.println(amount);
amount = bonus(80000);
System.out.println(amount);
amount = bonus(280000);
System.out.println(amount);
amount = bonus(500000);
System.out.println(amount);
}
/**
* 计算奖金
*/
public static int bonus(int amount){
if (amount<100000){
return amount*10/100;
} else if(amount>300000){
return amount*7/100;
} else if(amount>=100000){
return amount*9/100;
} else {
return 0;
}
}
}
布尔&&逻辑运算符
我们在前面了解到,数据运算结果的类型和操作符的类型均相同,比如说`+`
运算符如果传递的是两个 int 整数,那么其结果也是一个整数;或者如果传递的都是 double 类型,那么结果也是 double 类型。
而关系运算符和上面的运算符有很大的不同,它的结果要不然是 true 要么是 false。true 和 false 在 Java 中是非常特殊的值,我们将这个类型称为布尔型,这个我们在前面数据类型里也有介绍过。我们现在深入的学习一下这个 boolean 类型
我们看一下这段代码
if(x>0){
System.out.println("x>0");
}
实际上,上面代码中的条件表达式的结果就是 boolean 类型。所以上面的代码也可以写成
boolean flag = x>0;
if(flag){
System.out.println("x>0");
}
boolean 类型除了作用于这里,也可以作为方法的参数或者返回类型。比如判断是否及格的方法
public static boolean isPass(int score){
return score >= 60;
}
逻辑运算符
我们在前面了解了条件表达式,通过条件表达式可以完成条件的判断,实际上除了数学表达式之外,Java 还支持三种逻辑运算符:and(与)、or(或者)、not(非),对应的符号分别是 &&
、||
、!
使用逻辑运算符有什么用呢?可以用另外一种解释就是组合多个条件,举个例子
if(x>0 && x <10){
// 表示 x 大于0 并且 x小于10时才为真
}
if(x == 60 || x == 80){
// 表示 x 等于60 或者 x 等于80 都为真
}
if(x!=0){
// 表示x不等于0的时候
}
在有些时候,我们还可以对 boolean 数据进行 !
的运用这个表示对 boolean 值进行否定,比如
boolean isPass = false;
if(!isPass){
System.out.println("通过考试");
}
逻辑运算符的运用会非常多,因为很多时候我们的条件都是组合的,除了组合一次外还可以多次组合,比如
if(x == 60 || x == 80 || x == 90){
// 表示 x等于60 或者x等于80 或者x等于90为真
}