第三章节 方法 引用传递,值传递,scanner读入char的问题
第三章节 方法 引用传递,值传递,scanner读入char的问题
何为方法
-
Java方法语句的集合,他们在一起执行一个功能
-
方法是解决一类问题的步骤的有序组合
-
方法包含在对象或者类中
-
方法在程序中被创建,在七大地方被引用
-
-
方法的升级原则:方法的本意就是一个功能块,是实现某个功能的语句集合,设计方法的时候最好保持方法的原子性,即一个方法只实现一个功能
方法的定义和调用
定义
修饰符∶修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。
返回值类型∶方法可能会返回值。returnValueType是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType是关键字void。
方法名:是方法的实际名称。方法名和参数表共同构成方法签名。
参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
-
形式参数:在方法被调用时用于接收外界输入的数据。
-
实参:调用方法时实际传给方法的数据。
方法体:方法体包含具体的语句,定义该方法的功能。
调用
- 调用方法:对象名.方法名(实参列表)
- Java支持两种调用方法的方式,根据方法是否返回值来选择。当方法返回一个值的时候,方法调用通常被当做一个值。例如:
int larger = max( 30,40);
- 如果方法返回值是void,方法调用一定是一条语句。
system.out.println("Hello,kuangshen! ");
方法重载
重载就是在一个类中,有相同的函数名称,但形参不同的函数。
方法的重载的规则:
-
方法名称必须相同。
-
参数列表必须不同(个数不同、或类型不同、参数排列顺序不同等)。方法的返回类型可以相同也可以不相同。
-
仅仅返回类型不同不足以成为方法的重载。
配对方法
方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配以选择对应的方法,如果匹配失败,则编译器报错。
public static void main(String[] args) {
}
public static int add(int a,int b){ //例1 基础
return a+b;
}
public static double add(double a,double b){ //例2 参数类型不同
return a+b;
}
public static int add(int a,int b,int c){ //例3 参数个数不同
return a+b+c;
}
public static int add(int a,double b){ //例4
return 1; // 例4和例5是参数顺序不同的案例,他调换的参数必须要类型,不同不能是相同类型的!!
} // 例6为错误的案例
public static int add(double b,int a){ //例5
return 0;
}
//public static int add(int b,int a){ //例6 错误的重载!!!因为这其实与例1是一模一样的,形参的名字不同罢了
// return a+b;
//}
//public static double add(int a,int b){ //例7 错误的重载仅仅改变返回值的类型是无法重载的
// return a+b;
//}
命令行传参
可变参数
-
JDK 1.5开始,Java支持传递同类型的可变参数给一个方法。
-
在方法声明中,在指定参数类型后加一个省略号(.…)。
-
一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。
相当于可变长度的数组
递归
-
A方法调用B方法,我们很容易理解!
-
递归就是:A方法调用A方法!就是自己调用自己
-
利用递归可以用简单的程序来解决一些复杂的问题。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。
-
递归结构包括两个部分
-
递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。
-
递归体:什么时候需要调用自身方法。
public static void main(String[] args) { //阶乘 int n = 5; System.out.println(n+"的阶乘为"+f(n)); } public static int f(int n){ if (n==1){ return 1; }else{ return n*f(n-1); } }
-
今日问题
引用传递和值传递
值传递(pass by value):在调用函数时,将实际参数复制一份传递到函数中,这样在函数中对参数进行修改,就不会影响到原来的实际参数;
引用传递(pass by reference):在调用函数时,将实际参数的地址直接传递到函数中。这样在函数中对参数进行的修改,就会影响到实际参数;
第一个例子:
public class Hello {
public static void main(String[] args) {
Hello hello = new Hello();
// 基本数据类型
int i = 10;
hello.pass(i);
System.out.println("i = " + i);
}
public void pass(int pas) {
pas = 20;
System.out.println("pas = " + pas);
}
}
运行结果:
通过运行结果,可以看出这个例子是比较好理解的一个值传递的例子。
第二个例子:
public class Hello {
public static void main(String[] args) {
Hello hello = new Hello();
// String类
String s = "hello";
hello.pass(s);
System.out.println("s = " + s);
}
public void pass(String str) {
str = "world";
System.out.println("str = "+ str);
}
}
运行结果:
通过运行结果可以看出值也是发生了变化的,但是调用函数对String类赋值的时候【str = "world";】相当于是【str = new String("world");】;我这里理解是变量str重新指向了一个新的对象的地址。
第三个例子:
public class Hello {
public static void main(String[] args) {
Hello hello = new Hello();
// 对象
User user = new User();
user.setName("wang");
hello.pass(user);
System.out.println("main:"+user.getName());
}
public void pass(User user) {
user.setName("java");
System.out.println("The name is :" + user.getName());
}
}
运行结果:
看到这个例子的时候,便是我最大疑问的时候,当时我便觉得在Java中基本数据类型是值传递,对象数据类型是引用传递,而String看做一个特殊的类。在看下一个例子;
第四个例子:
public class Hello {
public static void main(String[] args) {
Hello hello = new Hello();
User user2 = new User();
user2.setName("li");
hello.pass2(user2);
System.out.println("main:"+user2.getName());
}
public void pass2(User user) {
user = new User();
user.setName("java new");
System.out.println("The name is :" + user.getName());
}
}
运行结果:
看到这个例子的时候,你在想想第二个例子,我发现其实他们的输出的结果最后发生了改变,是因为重新new了一个新对象的原因,他们原有的对象并没有发生任何的改变。然后我们再重新看一下值传递和引用传递的定义,重新调整一下思路:
我觉得对于基本数据来说,在进行传递的时候, 将数据的值复制了一份进行的传递,所以我们也比较好理解的这种值传递;而对于对象数据类型,因为该对象本身指向的是它在内存中的地址,所以方法调用的时候,实际上是创建的地址的副本,所以在方法中对其值进行改变的时候,他的地址没有变,值也就跟着改变了;而当你重新创建一个对象的时候,它指向的便是另一个对象的地址了。这样看来跟值传递的定义便不冲突了。
简单的计算器
package method;
import java.util.Scanner;
public class Demo04 {
public static void main(String[] args) {
Scanner sanner =new Scanner(System.in);
int a = sanner.nextInt();
char operator =sanner.next().charAt(0); //scanner读入字符
int b =sanner.nextInt();
calculator(a,operator,b);
}
public static double calculator(int a,char operator,int b){
switch (operator){
case '+':
System.out.println(a+b);
break;
case '-':
System.out.println(a-b);
break;
case '*':
System.out.println(a*b);
break;
case '/':
System.out.println(a/b);
break;
default:
System.out.println("输入错误");
break;
}
return 0;
}
}
canner读入char
在完成简单的计算器的过程中使用sanner类的时候发现一个之前学习的时候没有遇到的问题,就是sanner类没有nextChar()这个类
要想读入一个字符只能采用以下两个方法
- 读入一个字符串,返回字符串的第一个字符的char值
char c = scanner.next().charAt(0); //读入一个字符串,输入字符串(数组)中的第一个字符
public char charAt(int index)
返回指定索引处的 char 值。
错误案例 读入int再强制转换 !!Java中使用scanner类int和char是无法强转的可以编译但是运行结果会错误!!
int T = scanner.nextInt();
char c = (char) T;
========================================================================================================================================
参考https://blog.csdn.net/SummerOfFoam/article/details/109570841