本文是《Java学习指南》原书的网络版,作者邵发,拥有本书的全部权利。相关视频课程在此查看。
目录
第7章 类的方法
7.1 方法
在Java里,方法(Method)和属性是对等的术语。在一个类里,不仅可以添加属性,还可以添加方法。可以大致表示如下:
类
{
属性 : 描述“我有什么”
方法 : 描述“我能做什么”
}
其中,属性可以理解为“我有什么”,而方法可以理解为“我能做什么”。
7.1.1 添加方法
先看一个例子,在Student类里添加一个名字叫show的方法,
public class Student
{
public void show ( )
{
for(int i= 0; i<10; i++)
{
System.out.println("报数: " + (i+1));
}
}
}
其中,public void show () { ... } 这一段就称为方法,而show是方法名,大括号里的代码称为方法体。用图表示如下,
初学者只需要先照抄几遍,记住它的形式就可以。至于各部分的意义和用法,比如public、void是什么意思,这些后面都会详细讲解的。
7.1.2 方法的调用
现在,已经在Student类里添加一个show() 方法,那么,怎么使用这个方法呢?
按照面向对象的一般原则,无论是访问属性、还是方法,都要先创建一个对象。例如,
Student s = new Student();
s.show();
在这段代码里,首先创建一个对象s,然后s.show() 通过点号来调用它的方法。当调用s.show()时,其方法体里的代码被执行。
7.1.3 方法的命名
方法的命名规则和属性一样,都是小写字母开头,形如,
startService ()
check ()
openSafely ()
为了保证代码的可读性,一般属性以名词性短语命名,而方法用动词性短语命名(表示一个动作)。
7.2 方法的参数
先来看一下方法的一般形式,如下,
修饰符 返回值类型 方法名 ( 参数列表 )
{
方法体
}
这节课我们将讨论一下小括里的参数列表的用法。
下面将用具体的例子来说明,相信看完例子大家就明白了。
7.2.1 示例1
要求在Student类里添加一个方法,仍然是实现报数的功能,但最大值 N 由调用者指定。代码如下,
public class Student
{
public void show2 ( int maxNumber )
{
for(int i= 1; i<maxNumber ; i++)
{
System.out.println("报数: " + (i+1));
}
}
}
这个show2方法就带一个参数int maxNumber,可以理解为:此方法用于实现报数的功能,但报数的范围由调用者指定。
下面看一下,如何调用这个show2方法,
Student s = new Student();
s.show2(40); // 传入参数值
也就是说,当方法带有参数时,调用的时候要把参数的值传入。
7.2.2 示例2
进一步修改上面的功能,现在要求在报数的时候,报数的起点和终点都由调用者决定。
在Student类里再添加一个方法show3,代码如下,
public class Student
{
// 指定报数的上限
public void show2 ( int maxNumber )
{
for(int i= 1; i<maxNumber ; i++)
{
System.out.println("报数: " + (i+1));
}
}
// 指定报数的起点和终点
public void show3 ( int from, int to )
{
for(int i= from; i<= to ; i++)
{
System.out.println("报数: " + (i));
}
}
}
在这段代码里,方法show3带了2个参数,以逗号分隔。int from 表示起点,int to 表示终点。
下面再来看一下如何调用 show3 方法,
Student s = new Student();
s.show3( 30, 60); // 从30升级到60
也就是,show3需要传入2个参数。
小结一下:参数列表可以由0..N个参数组成,以逗号分开。每个参数应指定的参数类型和参数名。
7.2.3 理解参数的作用
方法就是描述一个类能够做什么事情,而方法的参数则就是日常生活的“参数”的意思。
比如说,空调表可以用AirConditioner类表来示,空调的致冷功能可以用freeze() 方法来表示。如果freeze() 方法不带参数,则逻辑上就匪夷所思:你买了一台空调,难道连致冷的温度都不能设置吗?
public class AirConditioner
{
public void freeze ( )
{
// 我能致冷,但我该致冷到多少度?
}
}
显然,空调的致冷温度是由用户来设定的,所以freeze()方法需要带一个参数来表示目标温度,示例代码如下,
public class AirConditioner
{
public void freeze ( int degree )
{
// 启动致冷操作、直到达到目标温度degree时
}
}
现在,这个空调就可以正常使用了,代码如下,
AirConditioner ac = new AirConditioner();
ac.freeze ( 18 ) ; // 致冷到18度
相信到此为止,大家已经明白了“参数”的作用。
7.3 方法的返回值(1)
再来回顾一下方法的一般形式,
修饰符 返回值类型 方法名 ( 参数列表 )
{
方法体
}
目前,方法名、方法体、参数列表的意义我们已经明确,这节课再讲一下“返回值类型”的用法。
简单的讲,“方法”就是做一件事情,而“方法的返回值”就是这件事情的结果。
7.3.1 示例1
已知一个整型的数组,要求出里面的最大值。
int[] a1 = { 29, 93, 193 };
这个功能对于大家来说,应该并无太大的难度。代码如下,
public int getMax2 ( int[] data)
{
int result = data[0];
for ( int i= 0; i<data.length; i++)
{
if ( data[i] > result)
{
result = data[i];
}
}
return result;
}
在这一段代码中,我们要注意两个部分,
(1) 将返回值的类型声明为int,表示这个方法将返回一个整数
(2) 计算出结果result,然后用return语句返回
在调用的时候,
int[] a1 = { 29, 93, 193 };
MyMath m = new MyMath();
int max = m.getMax2 ( a1 );
在这段代码中,用变量max来接收m.getMax2()的返回值。通俗的讲,m对象就是小明,max就是小明买回来的东西。
7.3.2 示例2
下面再讲一个例子。现在有两个数组,要求这两个数组中的最大值。
① ② ③ ④ ⑤ ⑥ | MyMath m = new MyMath(); int r1 = m.getMax2( a1 ); int r2 = m.getMax2( a2 ); int max = r1; if( r2 > max ) max = r2; System.out.println("结果为:" + max); |
其中,
第②行,计算数组a1里的最大值r1
第③行,计算数组a2里的最大值r2
第④⑤行,取r1和r2的最大值
提示:如果if语句里只有一行,则可以省略大括号。
if ( r2 > max )
{
max = r2;
}
可以简写为
if (r2 > max )
max = r2;
但是建议初学者,在使用if语句时统一使用大括号。
7.3.3 void 返回值
void的意思是“否、不用”。如果一个方法不需要返回值,则将返回值类型设为void。
打个比方,让小明去看个电影,是不需要返回值的,
pubic void watchMovie( int money)
{
}
但是,如果让小明去买本书,那么就需要把买的书返回来,
public Book buy( int money)
{
}
所以,所谓的返回值就可以理解为这件事情返回的结果。
7.4 方法的返回值(2)
下面,我们来讨论一下return语句的用法。return语句必须放在方法体里,起到两个作用:
v 返回一个值
v 从方法中退出。当return语句运行时,立即从方法体中退出。
7.4.1 示例1
给定一个数组,计算它们的和,是否大于100。假设都是正数。
int[] a1 = { 28, 23, 62, 16, 8 };
首先,创建一个类MyMath并添加一个方法check(),
public class MyMath
{
public boolean check ( int[] arr )
{
...
}
}
方法的参数为一个数组int[ ]。
方法的功能是判断各元素的和是否大于100,所以规定返回值的类型为boolean。如果大于100则返回true,否则返回false。
然后,把功能实现如下,
public boolean check ( int[] arr )
{
boolean result = false;
int sum = 0;
for (int i=0; i<arr.length; i++)
{
sum += arr[i];
if( sum > 100)
{
result = true;
break;
}
}
return result;
}
按照一般思路,先把结果计算出来,记为result,然后使用return语句返回。
但实际上,return语句不是一定要放在最后的。在得到结果的第一时间,就可以调用return语句退出方法的运行。可以把代码优化如下,
public boolean check ( int[] arr )
{
int sum = 0;
for (int i=0; i<arr.length; i++)
{
sum += arr[i];
if( sum > 100)
{
return true; // 结果既出,直接返回
}
}
return false;
}
注意,在return后面不需要再加break语句,因为return的时候直接退出了方法,循环自然就被中断。
7.4.2 示例2
给定一个int值,如果打印一个三角型。形如,
1
2 3
4 5 6
7 8 9 10
先把方法写出来,代码如下,
public void print ( int n )
{
int rows = 0; // 行数
int cols = 0; // 列数
for(int k=1; k<=n; k++)
{
System.out.print( k + " ");
cols ++;
if( cols > rows )
{
System.out.print("\n"); // 换行
rows ++;
cols = 0;
}
}
}
现在我们考虑:当 n <= 0时怎么办?如果n<=0,方法是可以提前退出的,再往走就没有意义。所以可以写成,
public void print ( int n )
{
if(n<=0)
{
System.out.println("给定的数<=0!!");
return; // 退出方法
}
if(n>10)
{
System.out.println("给定的数太大了!");
return; // 退出方法
}
int rows = 0; // 行数
int cols = 0; // 列数
for(int k=1; k<=n; k++)
{
.... 篇幅限制,省略一些代码 .....
}
}
可以发现,当执行return语句后,方法直接退出,方法体里后面的语句不会继承执行。
同时我们也注意到,这个print方法的返回值类型是void,所以return语句里不加返回值。就是单独的一行return; 表示退出方法。截取相关代码如下,
if(n<=0)
{
System.out.println("给定的数<=0!!");
return; // 注意,这里的return不加返回值
}
7.5 方法的返回值(3)
在使用return语句来返回一个值时,可以返回多种类型的值,包含:
- 基本数据类型int, double, String, boolean
- 自定义类型 如 Student, Book
- 数组类型 ,如int[ ] , Student[ ]
也就是说,各种类型都是可以返回的。可以返回一个苹果,也可以返回一个大象,没有禁忌。随着教程的深入,后面会看到返回各种数据类型的例子。
7.5.1 示例1
给定一个数组,求里面的能被8整除的数
int[] arr = { 18, 28, 32, 36, 48 };
自然地,还是添加一个类,然后在类里添加一个方法。代码实现如下,
public class MyMath
{
// 把符合要求的数放在返回值里
public int[] find8(int[] arr)
{
// 创建等大的数组
int[] temp = new int[arr.length];
int count = 0;
for (int i = 0; i < arr.length; i++)
{
if (arr[i] % 8 == 0)
{
temp[count] = arr[i];
count++;
}
}
// 拷贝到结果数组里
int[] result = new int[count];
for (int i = 0; i < count; i++)
{
result[i] = temp[i];
}
return result;
}
}
然后在main()方法里调用这个方法,
public static void main(String[] args)
{
int[] arr = { 18, 28, 32, 36, 48 };
MyMath m = new MyMath();
int[] result = m.find8( arr );
}
提示:数组不能直接用println输出,如果相看数组result里的值,可以用for循环逐个输出,或者用单步调试的方式查看。
7.5.2 示例2
已知学号,姓名,手机号,创建一个学生对象。
由于没有实际项目的上下文,这个例子对于大家来说可能有点生硬。大家只需要了解这个方法的返回值的形式即可。代码如下,
public Student createNew (String id, String name)
{
Student temp = new Student();
temp.id = id;
temp.name = name;
return temp; // 可以返回一个自定义类型的对象
}
再简单看一下如何调用,
int[] arr = { 18, 28, 32, 36, 48 };
MyMath m = new MyMath();
Student stu = m.createNew("2329", "shaofa");
通过这个例子,我们明白了返回的值可以是引用类型。
7.6 方法名的重载
重载,OverLoad,这个术语在Java里表示多个方法取相同的名字。例如,
public class Simple
{
public void test()
{
System.out.println("测试1。。。");
}
public void test(int a, int b)
{
System.out.println("测试2: a="+ a + ",b=" + b);
}
public void test(int a, String b)
{
System.out.println("测试3: a="+ a + ",b=" + b);
}
}
在Simple类中有三个方法,名字都叫test,但参数列表不同。
第一个test方法不带参数。第二个test方法带2个参数(int,int),第三个方法带2个参数(int, String)。
这种方法名称相同、参数不同的现象,称为方法名重载。
在调用的时候,根据传递的参数来匹配相应的方法,例如,
public static void main(String[] args)
{
Simple s = new Simple();
s.test(); // 无参
s.test(10, 12); // 参数: int, int
s.test(10, "shaofa");// 参数:int,String
}
显然,s.test() 时没有传递参数,所以匹配的是无参的test()。
s.test(10,12) 匹配的是test(int, int) ,而s.test(10,"shaofa")匹配的是test(int, String)。
重载是一个重要、常见而又比较简单的语法。大家不用刻意去记忆,见得多了自然就会了。