方法的重载(overload)
概念:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数 类型不同即可。与修饰符和返回值类型无关。
参数列表不同是指:
- 个数不同
- 数据类型不同
- 顺序不同。
重载的特点:
- 与返回值类型无关,只看参数列表,且参数列表必须不同。(参数个数或参数类型)。
重载方法调用
- JVM通过方法的参数列表,调用不同的方法。
举例:
/*
* 方法的重载(overload) loading...
*
* 1.定义:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
*
* "两同一不同":同一个类、相同方法名.参数列表不同:参数个数不同,参数类型不同
*
*
* 判断是否是重载:
* 跟方法的权限修饰符、返回值类型、形参变量名、方法体都没有关系!
*
* 在通过对象调用方法时,如何确定某一个指定的方法:
* 方法名 ---> 参数列表
*/
public class OverLoadTest {
public static void main(String[] args) {
OverLoadTest test = new OverLoadTest();
test.getSum(1, 2);
}
//如下的4个方法构成了重载
public void getSum(int i, int j) {
System.out.println("1");
}
public void getSum(double d1, double d2) {
System.out.println("2");
}
public void getSum(String s, int i) {
System.out.println("3");
}
public void getSum(int i, String s) {
System.out.println("4");
}
}
使用重载方法,可以为编程带来方便。 例如,System.out.println()方法就是典型的重载方法。
/*
* 1.编写程序,定义三个重载方法max(),
第一个方法求两个int值中的最大值,
第二个方法求两个double值中的最大值,
第三个方法求三个double值中的最大值,
*/
public class OverloadExer {
//2.如下的三个方法构成重载
public int max(int i, int j) {
return (i > j) ? i : j;
}
public double max(double d1, double d2) {
return (d1 > d2) ? d1 : d2;
}
public double max(double d1, double d2, double d3) {
double max = (d1 > d2) ? d1 : d2;
return (max > d3) ? max : d3;
}
}
可变个数的形参
在JDK1.5之后,如果我们定义一个方法需要接受多个参数,并且多个参数类型一致,我们可以对其简化成如下格式:
JDK1.5以后。出现了简化操作。... 用在参数上,称之为可变参数。同样是代表数组,但是在调用这个带有可变参数的方法时,不用创建数组(这就是简单之处),直接将数组中的元素作为实际参数进行传递,其实编译成的class文件,将这些元素先封装到一个数组中,在进行传递。这些动作都在编译.class文件时,自动完成了。
可变参数的原理:
- 可变参数底层就是一个数组,根据传递参数个数不同,会创建不同长度的数组,来存储这些参数传递的参数个数,可以是0个(不传递),1,2...多个
参数的注意事项
- 声明格式:方法名(参数的类型名 ...参数名)
- 可变参数:方法参数部分指定类型的参数个数是可变多个:0个,1个或多个
- 可变个数形参的方法与同名的方法之间,彼此构成重载
- 可变参数方法的使用与方法参数部分使用数组是一致的
- 方法的参数部分有可变形参,需要放在形参声明的最后
- 在一个方法的形参位置,最多只能声明一个可变个数形参
举例:
package com.atguigu.java1;
/*
* 可变个数形参的方法
*
* 1.jdk 5.0新增的内容
* 2.具体使用:
* 2.1 可变个数形参的格式:数据类型 ... 变量名
* 2.2 当调用可变个数形参的方法时,传入的参数个数可以是:0个,1个,2个,。。。
* 2.3 可变个数形参的方法与本类中方法名相同,形参不同的方法之间构成重载
* 2.4 可变个数形参的方法与本类中方法名相同,形参类型也相同的数组之间不构成重载。换句话说,二者不能共存。
* 2.5 可变个数形参在方法的形参中,必须声明在末尾
* 2.6 可变个数形参在方法的形参中,最多只能声明一个可变形参。
*
*/
public class MethodArgsTest {
public static void main(String[] args) {
MethodArgsTest test = new MethodArgsTest();
//调用方法
test.show("hello");
test.show("hello", "world");
test.show();
test.show(new String[]{"AA", "BB", "CC"});
}
//定义含有可变参数的方法
public void show(String... strs) {
System.out.println("show(String ... strs)");
for (int i = 0; i < strs.length; i++) {
System.out.println(strs[i]);
}
}
/*
不能与上一个方法同时存在
public void show(String[] strs){
}
*/
}
可变参数的又一应用
package demo01;
public class ChangeArgs {
public static void main(String[] args) {
int[] arr = {1, 4, 62, 431, 2};
int sum = getSum(arr);
System.out.println(sum); // 500
// 求 这几个元素和 6 7 2 12 2121
int sum2 = getSum(6, 7, 2, 12, 2121);
System.out.println(sum2);//2148
}
/**
完成数组 所有元素的求和 原始写法
public static int getSum(int[] arr){
int sum = 0;
for(int a : arr){
sum += a;
}
return sum; }
*/
//可变参数写法
public static int getSum(int... arr) {
int sum = 0;
for (int a : arr) {
sum += a;
}
return sum;
}
//可变参数的特殊(终极)写法
public static void method(Object... obj) {
}
方法参数的值传递机制
方法,必须由其所在类或对象调用才有意义。若方法含有参数:
- 形参:方法声明时的参数
- 实参:方法调用时实际传给形参的参数值
变量的赋值:
- 如果变量是基本数据类型,此时赋值的是变量所保存的数据值。
- 如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值。
值传递机制:
- 如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值。
- 如果参数是引用数据类型,此时实参赋给形参的是实参存储数据的地址值。
Java的实参值如何传入方法呢?
Java里方法的参数传递方式只有一种:值传递。 即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。
- 形参是基本数据类型:将实参基本数据类型变量的“数据值”传递给形参
/*
* 方法的形参的传递机制:值传递
* 如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值。
*/
public class ValueTransferTest1 {
public static void main(String[] args) {
int m = 10;
int n = 20;
ValueTransferTest1 test = new ValueTransferTest1();
test.swap(m, n);
System.out.println("m = " + m + ", n = " + n);//m = 10, n = 20
}
public void swap(int m, int n) {
//交换两个变量的值的操作
int temp = m;
m = n;
n = temp;
System.out.println("m = " + m + ", n = " + n);//m = 20, n = 10
}
}
- 形参是引用数据类型:将实参引用数据类型变量的“地址值”传递给形参
public class Person {
int age;
public static void main(String[] args) {
Person obj = new Person();
obj.age = 5;
System.out.println("修改之前age = " + obj.age);// 修改之前age = 5
// obj是实参
change(obj);
System.out.println("修改之后age = " + obj.age);// 修改之后age = 3
}
public static void change(Person obj) {
System.out.println("change:修改之前age = " + obj.age);//change:修改之前age = 5
obj.age = 3;
System.out.println("change:修改之后age = " + obj.age);//change:修改之后age = 3
}
}
需求
- 定义一个Circle类,包含一个double型的radius属性代表圆的半径,一个 findArea()方法返回圆的面积。
- 定义一个类PassObject,在类中定义一个方法printAreas(),该方法的定义 如下:public void printAreas(Circle c, int time) 在printAreas方法中打印输出1到time之间的每个整数半径值,以及对应的面积。 例如,time为5,则输出半径1,2,3,4,5,以及对应的圆面积。 在main方法中调用printAreas()方法,调用完毕后输出当前半径值。
定义Circle类
/*
* 定义一个Circle类,包含一个double型的radius属性代表圆的半径,
* 一个findArea()方法返回圆的面积。
*
*/
class Circle {
double radius;//半径
//求圆的面积
public double findArea(){
return Math.PI * radius * radius;
}
}
定义PassObject类
public class PassObject {
public static void main(String[] args) {
Circle c = new Circle();
printAreas(c, 5);
System.out.println("now radius is " + c.radius);
}
public static void printAreas(Circle c, int time) {
System.out.println("Radius\t\tArea");
int i = 1;
for (; i <= time; i++) {
//设置圆的半径
c.radius = i;
double area = c.findArea();
System.out.println(c.radius + "\t\t" + area);
}
c.radius = i;
}
}
递归
递归概念:指在当前方法内调用自己的这种现象。方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执 行无须循环控制。 递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环。
递归的分类:
- 递归分为两种,直接递归和间接递归。
- 直接递归称为方法自身调用自己。
- 间接递归可以A方法调用B方法,B方法调用C方法,C方法调用A方法。
注意事项:
- 递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出。
- 在递归中虽然有限定条件,但是递归次数不能太多。否则也会发生栈内存溢出。
- 构造方法,禁止递归
举例
package demo02;
public class Demo01Recurison {
public static void main(String[] args) {
//a();
b(1);
}
/*
构造方法,禁止递归
编译报错:构造方法是创建对象使用的,一直递归会导致内存中有无数多个对象,直接编译报错
*/
public Demo01Recurison() {
//Demo01Recurison();
}
/*
在递归中虽然有限定条件,但是递归次数不能太多。否则也会发生栈内存溢出。
Exception in thread "main" java.lang.StackOverflowError
*/
private static void b(int i) {
System.out.println(i);
if(i==20000){
return; //结束方法
}
b(++i);
}
/*
递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出。
Exception in thread "main" java.lang.StackOverflowError
*/
private static void a() {
System.out.println("a方法!");
a();
}
}
需求
计算1 ~ n的和
分析:num的累和 = num + (num-1)的累和,所以可以把累和的操作定义成一个方法,递归调用。
package demo02;
public class DiGuiDemo {
public static void main(String[] args) {
//计算1~num的和,使用递归完成
int num = 5;
// 调用求和的方法
int sum = getSum(num);
// 输出结果
System.out.println(sum);//15
}
/*
通过递归算法实现.
参数列表:int
返回值类型: int
*/
public static int getSum(int num) {
/* num为1时,方法返回1, 相当于是方法的出口,num总有是1的情况 */
if (num == 1) {
return 1;
}
/*
num不为1时,
方法返回 num +(num‐1)的累和
递归调用getSum方法
*/
return num + getSum(num - 1);
}
}
代码执行图解
可。