对于之前常用的一条语句System.out.println()
,有以下说明:
println()是一个方法
System是系统类
out是标准输出对象
该语句就是调用系统类System 中的标准输出对象 out 中的 println()方法。
Java方法是语句的集合,它们在一起执行一个功能。类似于其他语言(比如C++)中的函数。
方法是解决一类问题的步骤的有序组合
方法包含于类或对象中
方法在程序中被创建,在其他地方被引用
方法的本意是功能块,是实现某个功能的语句块的集合。在设计方法的时候最好保持方法的原子性,就是一个方法只完成1个功能。这样设计有利于程序维护,也便于后期扩展。
一般情况下,方法的基本语法结构是:
修饰符 返回值类型 方法名(参数类型 参数名){ ... 方法体 ... return 返回值; }
方法包含一个方法头和方法体:
修饰符:**修饰符,这是可选的**,告诉编译器如何调用该方法。定义了该方法的访问类型。
返回值类型 :方法可能会返回值。returnValueType 是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType 是关键字void。
方法名:是方法的实际名称。方法名和参数表共同构成方法签名。
参数类型:
参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。
参数是可选的,方法可以不包含任何参数
。
形参: 在方法被调用时用于接收外界输入的数据,主要在方法定义时使用,更像是一个占位符。
实参:调用方法时实际传给方法的数据。
方法体:方法体包含具体的语句,定义该方法的功能。
public class Demo01 { //系统main方法,每个程序都有且只有一个main()方法 //应保证main()方法的干净整洁,可读性好。 //对于一些需要执行特定功能的程序,应该在main()方法外面设计为方法,需要使用时在main()方法中调用该方法 //public static都是修饰符;void表示无返回值;main为方法名 //String[] args为main()方法接收的参数类型;{}括起的部分是方法体 public static void main(String[] args) { //调用自定义的add方法 int sum = add(1,2); //调用java内置的println()方法,该方法的功能就是输出。 System.out.println("两数之和为:" + sum); } //自定义一个方法,实现求两数之和的功能 //在main()方法的外面进行方法定义 //public static是修饰符,int为方法返回值类型;add是方法名; //int a,int b为方法的形参,表明方法接收int型数据参数;return关键字表明方法返回值。 //定义之后,可以在main()方法中调用该方法 public static int add (int a, int b) { return a + b; } } ------------------------------------- 运行结果: 两束之和为:3
Java 支持两种调用方法的方式,根据方法是否返回值来选择:
当方法返回一个值的时候,方法调用通常被当做一个值。
当方法没有返回值时(即方法返回值是void),方法调用一定是一条语句。
调用方法:对象名.方法名(实参列表)
//方法调用举例 public class Demo01 { //main方法被JVM调用 public static void main(String[] args) { //在main方法中调用max方法,max方法有返回值 int max = max (30,50); //在main方法中调用println方法,无返回值 //调用方法:(类名).(对象名).方法名(实参列表)` System.out.println(max); } //比大小方法定义 public static int max (int a, int b) { int result = 0; if (a == b) { System.out.println("两数相等"); return 0; }else if (a > b){ result = a; }else { result = b; } return result; } } ------------------------------------------- 运行结果: 50
静态方法与非静态方法的区别
静态方法:
静态方法是在类中使用staitc修饰的方法;
静态方法在类定义的时候已经被装载和分配;
静态方法只能调用静态成员或方法,不能调用非静态方法或者非静态成员。
非静态方法:
方法定义时,没有static
修饰符修饰的方法;
在类定义时没有占用内存,只有在类被实例化成对象时,对象调用该方法才被分配内存,因此非静态方法只能在类实例化对象后,通过对象来调用;
非静态方法既可以调用静态成员或者方法又可以调用其他的非静态成员或者方法。
静态方法与非静态方法的调用
对于静态方法:
调用本类中的静态方法,可直接使用方法名调用;
对于其它类中的静态方法,可通过类名.方法名
调用
对于非静态方法:
只能通过对象名.方法名
的方式调用,因此使用前,必须先将类实例化出一个对象,然后通过对象来调用。
按值传递:
按值传递在方法调用时,传递的参数是按值的拷贝传递。即传递过后,与原值无关。
//按值传递 package com.method; public class Demo01 { public static void main(String[] args) { int a = 3; //初始化a(实参) Demo01.test(a); //调用方法test,将a的值传递给方法形参 System.out.println("======================"); System.out.println("main方法中的a = " + a); //方法调用之后,a的值在方法里有所改动,但不影响main中a的值 } //定义test方法,接收数据的形参是a public static void test (int a){ a += 1; //对a进行操作,但不影响main中a的值; // 这说明test方法接收a的值之后,创建了a的副本,方法内的操作都是对a的副本进行的,不影响a的原值 System.out.println("test方法中的a = " + a); } } ----------------------------------- 运行结果: test方法中的a = 4 ====================== main方法中的a = 3
按引用传递
在C++里,引用是已定义变量的别名,比如b是a的别名,那么对b操作就是对a操作。
按引用传递在方法调用时,传递的参数是按值的内存地址进行传递的,即传递的是值所在的内存地址(相当于C++里的指针)。
因此,传递前后的引用都指向同一块地址,也就是说方法里面的操作是直接对原值进行操作,而不再是值的副本。
package com.method; // 按引用传递 public class Demo02 { public static void main(String[] args) { Age a = new Age(); a.age = 10; test (a); System.out.println("========================"); System.out.println("main方法中的age = " + a.age); } public static class Age { public int age = 0; } public static void test (Age a) { a.age += 20; System.out.println("test方法中的age = " + a.age); } } -------------------------------------- 运行结果: test方法中的age = 30 ======================== main方法中的age = 30
Java中只有值传递,没有引用传递。
上面的程序中,Java实现了修改原值的效果。需要说明的是Java中传递对象参数,由于传递的是地址,因此传递后将会创建一个地址副本,由于传递前后的地址是一样的,都指向原值,因此就产生了可以修改原值的效果。从这个角度来说,Java只有值传递,没有引用传递。
重载就是在一个类中,有相同的函数名称,但形参列表不同的函数。
方法重载的规则
方法名称必须相同;
形参列表必须不同(参数数目不同、参数类型不同、参数排列数序不同等)
方法的返回类型可以相同也可以不同
仅仅返回类型不同不足以构成方法的重载
方法重载的实现:
方法名称相同时,编译器会根据调用方法的参数个数、参数类型去匹配合适的方法。若所有该名称的方法的形参列表均匹配失败,编译器将报错。
方法重载可以让程序更清晰易读。执行密切相关任务的方法应该使用相同的名字。
JDK 1.5 开始,Java支持传递同类型的可变参数给一个方法。
方法的可变参数的声明如下所示:
typeName... parameterName
在方法声明中,在指定参数类型后加一个省略号(…) 。
一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。
递归就是在方法体的内部调用该方法本身。
利用递归可以用一些简单的程序解决一些复杂的问题,递归策略只需用少量的程序就可描述解题过程中所需要的多次重复计算,减少了代码量。
但由于Java是栈机制。因此当用递归计算比较大的数据时,会占用大量内存,造成内存崩溃,慎用递归。
递归结构包含两个部分:
递归头:用于确定什么时候不调用自身方法,即终止递归。没有递归头,将陷入死循环。
递归体:即确定什么时候需要调用自身方法
//递归示例:阶乘 import java.util.Scanner; public class Demo02 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("请输入一个正整数:"); int num = scanner.nextInt(); System.out.println(num + "的阶乘是: " + factor(num)); } //定义方法,实现阶乘n! public static int factor (int n) { //这里的factor(1)是递归的尽头。 if (n == 1) { return 1; } else { //当n!= 1时就执行递归 return n * factor(n - 1); } } } ------------------------------ 运行结果: 请输入一个正整数: 10的阶乘是: 3628800
重要的是学习递归的思想。至于递归在处理较大的数据时,由于自身局限性而寻求其他的算法。
有时候你希望运行一个程序时候再传递给它消息。这要靠传递命令行参数给main()函数实现。
命令行参数是在执行程序时候紧跟在程序名字后面的信息。
package com.method; public class Demo03 { public static void main(String[] args) { for (int i = 0; i < args.length; i++) { System.out.println("args[" + i + "]:" + args[i]); } } }
然后在命令行执行该程序: