IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java学习之成员方法 -> 正文阅读

[Java知识库]Java学习之成员方法

方法的概念

方法也叫函数,是一个独立功能的定义,是一个类中最基本的功能单元。

把一个功能封装为方法的目的是,可以实现代码重用,从而简少代码量。

方法的原则

方法的使用原则:

(1)必须先声明后使用

类,变量,方法等都要先声明后使用

(2)不调用不执行,调用一次执行一次。调用一次,在栈中压入一个方法栈。

成员方法的分类

成员方法分为两类:

  • 实例方法:属于对象的方法,由对象来调用。
  • 静态方法:也叫类方法,属于整个类的,不是属于某个实例,由类名来调用。

定义实例方法的格式

1、语法格式

修饰符 返回值类型 方法名(【参数列表:参数类型1 参数名1,参数类型2 参数名, ......){
        方法体;
        【return 返回值;}
  • 修饰符: public(暂时写着一种,后面会补充)
  • 返回值类型: 表示方法运行的结果的数据类型,方法执行后将结果返回到调用者
    • 基本数据类型
    • 引用数据类型
    • 无返回值类型:void
  • 方法名:给方法起一个名字,见名知意,能准确代表该方法功能的名字
  • 参数列表:方法内部需要用到其他方法中的数据,需要通过参数传递的形式将数据传递过来,可以是基本数据类型、引用数据类型、也可以没有参数,什么都不写
  • 方法体:特定功能代码
  • return:结束方法,并将方法的结果返回去,
    • 如果返回值类型不是void,方法体中必须保证一定有【return 返回值;】语句,并且要求该返回值结果的类型与声明的返回值类型一致或兼容。
    • 如果返回值类型为void时,return 后面不用跟返回值,甚至也可以没有return语句。
    • return语句后面就不能再写其他代码了,否则会报错:Unreachable code

2、方法声明的位置必须在类中方法外(方法中不能声明方法)

正确示例:

{
    方法1(){
        
    }
    方法2(){
        
    }
}

错误示例:

{
    方法1(){
        方法2(){  //错误
        
   		}
    }
}

实例方法调用

  • 方法调用的位置:在另一个方法中调用。

    正确示例:

    {
        方法1(){
            调用其他方法;
        }
    }
    
  • 方法调用的分类:

    • 单独调用,格式如下:

      对象名.方法名(参数)
    • 输出或返回调用,格式如下:

      System.out.println(对象名.方法名(参数));//直接输出方法调用后的返回值return 对象名.方法名(参数);//直接返回方法调用后的返回值作为当前方法的返回值
      
    • 赋值调用,格式如下:

      数据类型 变量名 = 对象名.方法名(参数)

如果实例方法是在本类的另一个实例方法中调用,那么可以省略“对象名.”

class Count {
    /*
    定义计算两个整数和的方法
    返回值类型,计算结果是int
    参数:不确定数据求和,定义int参数.参数又称为形式参数
    */
    public int getSum(int a, int b) {
        return a + b;
    }
    
    /*
    定义计算两个整数差的方法
    返回值类型,计算结果是int
    参数:不确定数据求差,定义int参数.参数又称为形式参数
    */
    public int getSubtract(int a, int b){
        return getSum(a,-b);//直接返回getSum(a,-b)方法调用的结果作为getSubtract(a,b)的结果
    }
}

public class Method_Demo1 {
    public static void main(String[] args) {
        // 创建对象
        Count c = new Count();
        
        // 通过单独调用方式调用方法
        c.getSum(3,4)// 通过输出调用方式调用方法
        System.out.println(c.getSum(3,4));
        
        // 通过赋值调用方式调用方法
        int sum = c.getSum(3,4)System.out.println(sum);
    }
}
  • 形参:在定义方法时方法名后面括号中的变量名称称为形式参数(简称形参),即形参出现在方法定义中。
  • 实参:调用者方法中调用另一个方法时,方法名后面括号中的参数称为实际参数(简称实参),即实参出现在调用者方法中。

总结:

(1)调用时,需要通过方法名来识别调用哪个方法

(2)调用时,需要传“实参”,实参的个数、类型、顺序顺序要与形参列表一一对应

? 如果方法没有形参,就不需要也不能传实参。

(3)调用时,如果方法有返回值,可以接受或处理返回值结果。

? 如果方法的返回值类型是void,不需要也不能接收和处理返回值结果。

定义和调用实例方法举例

声明客户和账户类、银行类

  • 声明账户类Account
    • 包含:账户和余额两个实例变量
    • 包含save存款方法
    • 包含withdraw取款方法
  • 声明客户类Customer
    • 包含:姓名和手机、身份证号、拥有的一个账户,四个实例变量
  • 声明银行类BankClerk
    • 包含open方法,给某个客户对象开户,关联Customer和Account两个对象的信息
class Account{
	String id;
	double balance;
	public void save(double money){
		if(money > 0){
			balance += money;
		}else{
			System.out.println("参数有误");
		}
	}
	public void withdraw(double money){
		if(money <0){
			System.out.println("参数有误");
		}else if(money > balance){
			System.out.println("余额不足");
		}else{
			balance -= money;
		}
	}
}
class Customer{
	String name;
	String tel;
	String cid;
	Account account;
}
class BankClerk{
	public void open(Customer c, Account a){
		c.account = a;
	}
}
public class Method_Exer6 {
	public static void main(String[] args) {
		//创建客户对象
		Customer c = new Customer();
		c.name = "柴林燕";
		c.tel = "10086";
		c.cid = "111111111111111111";
		
		//创建银行卡账号对象
		Account a = new Account();
		a.id = "12345678910";
		a.balance = 0;
		
		//银行对象
		BankClerk b = new BankClerk();
		b.open(c, a);
		System.out.println("姓名:" + c.name + ",电话:" + c.tel + ",身份证号:" + c.cid + ",账号:" + c.account.id + ",余额:" + c.account.balance);
		
		//存款
		c.account.save(1000);
		System.out.println("姓名:" + c.name + ",电话:" + c.tel + ",身份证号:" + c.cid + ",账号:" + c.account.id + ",余额:" + c.account.balance);
		
		//取款
		c.account.withdraw(2000);
		//显示信息
		System.out.println("姓名:" + c.name + ",电话:" + c.tel + ",身份证号:" + c.cid + ",账号:" + c.account.id + ",余额:" + c.account.balance);
	}
}

方法调用内存分析

方法不调用不执行,调用一次执行一次,每次调用会在栈中有一个入栈动作,即给当前方法开辟一块独立的内存区域,用于存储当前方法的局部变量的值,当方法执行结束后,会释放该内存,称为出栈,如果方法有返回值,就会把结果返回调用处,如果没有返回值,就直接结束,回到调用处继续执行下一条指令。

栈结构:先进后出,后进先出。

class Test18_Invoke_Memory{
	public static void main(String[] args){
		Count c = new Count();
		
		int x = 1;
		int y = 2;
		
		int sum = c.getSum(x,y);
		System.out.println(x + " + " + y + " = " + sum);
	}
}
class Count{
	public int getSum(int a, int b){
		return a + b;
	}
}

在这里插入图片描述

可变参数

JDK1.5之后,如果我们定义一个方法时,此时某个形参的类型可以确定,但是形参的个数不确定,那么我们可以使用可变参数。

格式:

修饰符 返回值类型 方法名(【非可变参数部分的形参列表,】参数类型... 形参名){ 
	方法体;
 }

要求:

(1)一个方法只能有一个可变参数

(2)可变参数必须是形参列表的最后一个

(3)其实这个书写“等价于”

修饰符 返回值类型 方法名(【非可变参数部分的形参列表,】参数类型[] 形参名){ 
	方法体;
 }

只是后面这种定义,在调用时必须传递数组,而前者更灵活,既可以传递数组,又可以直接传递数组的元素,其实编译成的class文件,将这些元素先封装到一个数组中,在进行传递。这些动作都在编译.class文件时,自动完成了。

好处:

同样是代表数组,但是在调用这个带有可变参数的方法时,不用创建数组(这就是简单之处),直接将数组中的元素作为实际参数进行传递,其实编译成的class文件,将这些元素先封装到一个数组中,在进行传递。这些动作都在编译.class文件时,自动完成了。

代码演示:

public class ChangeArgs {
	public static void main(String[] args) {
		// 创建对象
		Count c = new Count();

		int[] arr = { 1, 4, 62, 431, 2 };
		int sum1 = c.getSum1(arr);
		System.out.println(sum1);

		int sum2 = c.getSum2(arr);
		System.out.println(sum2);
		int sum3 = c.getSum2(1, 4, 62, 431, 2);
		System.out.println(sum3);
	}

}

class Count {

	// 完成数组 所有元素的求和
	// 原始写法
	public int getSum1(int[] arr) {
		int sum = 0;
		for (int i = 0; i < arr.length; i++) {
			sum += arr[i];
		}

		return sum;
	}

	// 可变参数写法
	public int getSum2(int... arr) {
		int sum = 0;
		for (int i = 0; i < arr.length; i++) {
			sum += arr[i];
		}
		return sum;
	}
}

举例1:找最大值

定义求1-n个整数中的最大值

public class ChangeArgs_Exer1 {
	public static void main(String[] args) {
		Count c = new Count();
		System.out.println(c.max(1));
		System.out.println(c.max(5,3,2,6));
	}
}
class Count{
	public int max(int num, int... others){
		int max = num;
		for (int i = 0; i < others.length; i++) {
			if(max < others[i]){
				max = num;
			}
		}
		return max;
	}
}

举例2:字符串拼接

定义将n个字符串进行拼接,如果没有传入字符串,那么返回空字符串

public class ChangeArgs_Exer2 {
	public static void main(String[] args) {
		StringUtil su = new StringUtil();
		System.out.println(su.concat());
		System.out.println(su.concat("hello","world"));
	}
}
class StringUtil{
	public String concat(String... args){
		String str = "";
		for (int i = 0; i < args.length; i++) {
			str += args[i];
		}
		return str;
	}
}

方法重载

  • 方法重载:指在同一个类中,允许存在一个以上的同名方法,只要它们的参数列表不同即可,与修饰符和返回值类型无关。
  • 参数列表:数据类型个数不同,数据类型不同,数据类型顺序不同。
  • 重载方法调用:JVM通过方法的参数列表,调用不同的方法。

方法重载示例:比较两个数据是否相等

比较两个数据是否相等。参数类型分别为两个byte类型,两个short类型,两个int类型,两个long类型,并在main方法中进行测试。

public class Method_Demo6 {
    public static void main(String[] args) {
        //创建
        Count c = new Count();
        
        //定义不同数据类型的变量
        byte a = 10;
        byte b = 20;
        short c = 10;
        short d = 20;
        int e = 10;
        int f = 10;
        long g = 10;
        long h = 20;
        // 调用
        System.out.println(c.compare(a, b));
        System.out.println(c.compare(c, d));
        System.out.println(c.compare(e, f));
        System.out.println(c.compare(g, h));
    }
}

class Count {
        // 两个byte类型的
    public boolean compare(byte a, byte b) {
        System.out.println("byte");
        return a == b;
    }

    // 两个short类型的
    public boolean compare(short a, short b) {
        System.out.println("short");
        return a == b;
    }

    // 两个int类型的
    public boolean compare(int a, int b) {
        System.out.println("int");
        return a == b;
    }

    // 两个long类型的
    public boolean compare(long a, long b) {
        System.out.println("long");
        return a == b;
    }
}

方法的参数传递机制

  • 形参:在定义方法时方法名后面括号中的变量名称称为形式参数(简称形参),即形参出现在方法定义中。
  • 实参:调用者方法中调用另一个方法时,方法名后面括号中的参数称为实际参数(简称实参),即实参出现在调用者方法中。
  • 方法的参数传递机制:实参给形参赋值
    • 方法的形参是基本数据类型时,形参值的改变不会影响实参;
    • 方法的形参是引用数据类型时,形参地址值的改变不会影响实参,但是形参地址值里面的数据的改变会影响实参,例如,修改数组元素的值,或修改对象的属性值。
      • 注意:String、Integer等特殊类型除外

示例代码1:

class Test{
    public static void swap(int a, int b){
        int temp = a;
        a = b;
        b = temp;
	}

	public static void main(String[] args){
        int x = 1;
        int y = 2;
        swap(x,y);//调用完之后,x与y的值不变
    }
}

陷阱实例1:

/*
陷阱1:在方法中,形参 = 新new对象,那么就和实参无关了
*/
class Test{
    public static void change(MyData my){
        my = new MyData();//形参指向了新对象
        my.num *= 2;
    }
    
    public static void main(String[] args){
        MyData m = new MyData();
        m.num = 1;
        
        change(m);//调用完之后,m对象的num属性值仍然为1
    }
}

class MyData{
    int num;
}

陷阱实例2:

public class Test {
	public static void main(String[] args) {
		StringUtil util = new StringUtil();
		String str = "尚硅谷";
		util.change(str);
		System.out.println(str);
	}
}
class StringUtil{
	public void change(String str){
		str += "你好";//String对象不可变,一旦修改就会产生新对象
	}
}

命令行参数

通过命令行给main方法的形参传递的实参称为命令行参数

在这里插入图片描述

public class TestCommandParam{
	//形参:String[] args
	public static void main(String[] args){
		System.out.println(args);
		System.out.println(args.length);
		
		for(int i=0; i<args.length; i++){
			System.out.println("第" + (i+1) + "个参数的值是:" + args[i]);
		}
	}
}

运行命令:

java TestCommandParam
java TestCommandParam 1 2 3
java TestCommandParam hello atguigu

递归方法(recursion)

  • 递归:指在当前方法内调用自己的这种现象。
  • 递归的分类:
    • 递归分为两种,直接递归和间接递归。
    • 直接递归称为方法自身调用自己。
    • 间接递归可以A方法调用B方法,B方法调用C方法,C方法调用A方法。
  • 注意事项
    • 递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出。
    • 在递归中虽然有限定条件,但是递归次数不能太多。否则也会发生栈内存溢出。

举例1:计算1-100之间所有自然数的和

public class RecursionMethod1{
	public static void main(String[] args) {
		Count c = new Count();
		
		int sum = c.sum(100);
		System.out.println("1-100的和:" + sum);
	}
}
class Count{
	public int sum(int n){
		if(n == 1){
			return 1;
		}else{
			return n + sum(n-1);
		}
	}
}

在这里插入图片描述

举例2:计算斐波那契数列(Fibonacci)的第n个值

规律:一个数等于前两个数之和,

? f(0) =1,

? f(1) = 1,

? f(2) = f(0) + f(1) =2,

? f(3) = f(1) + f(2) = 3,

? f(4) = f(2) + f(3) = 5

? …

? f(n) = f(n-2) + f(n-1);

public class RecursionMethod3{
	public static void main(String[] args) {
		Count c = new Count();
		
		System.out.println("f(10):" + c.f(10));
		System.out.println("f方法被调用的总次数:" + c.total);
	}
}
class Count{
	int total = 0;
	public int f(int n){
		total++;
		if(n <= 1){
			return 1;
		}else{
			return f(n-2) + f(n-1);
		}
	}
}

在这里插入图片描述

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-11-30 15:28:34  更:2021-11-30 15:31:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:39:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码