C语言中自定义函数和Java中的方法,是大同小异的,相比于C语言的自定义函数,Java的方法省略了很多麻烦的事情,因此Java中的方法更好操作些。
目录
一、语法形式
C语言
返回类型 函数名([参数类型 形参] ……)
{
函数体代码;
[return 返回值];
}
Java
修饰符 返回值类型 方法名称([参数类型 形参], ...){
方法体代码;
[return 返回值];
}
程序主入口也是函数或者方法的一种特殊形式。在语法形式上C语言和 Java 的主要区别就是 Java 多了修饰符,修饰符的作用:就是管理方法被调用/访问的权限,除了有常见的 public ,还有 private,protected 和默认的 default(一般不写任何东西来表示默认权限)。
#include <stdio.h>
int add(int x, int y)
{
return (x + y);
}
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
int sum = add(a, b); // 调用add函数
printf("%d\n", sum);
return 0;
}
import java.util.Scanner; // 使用Scanner需要导入包
public class Test{
public static int add(int x, int y){
return x+y;
}
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
int a = scan.nextInt();
int b = scan.nextInt();
int ret = add(a, b);
System.out.println(ret);
}
}
二、形参与实参
无论是函数还是方法,形参和实参的概念是一样的。注意事项也是一样:
1、形参和实参各自有独立的空间
2、形参的修改,不会影响实参
3、形参是实参的一份临时拷贝
4、实参和形参名称可以相同,但不好观察
C语言中调用函数有传址调用和传值调用,使用传址调用才能真正将两个实参的值进行交换;
Java中拿不到栈上局部变量的地址,因此无法像C语言那样通过传址调用交换两个变量的值,若要交换,则需要类和对象的知识。
三、return 返回值
C语言
1、return后边可以是⼀个数值,也可以是⼀个表达式,如果是表达式则先执行表达式,再返回表达式的结果。
2、return后边也可以什么都没有,直接写
return;
这种写法适合函数返回类型是void
的情况。3、return语句执行后,函数就彻底返回,后边的代码不再执行。
4、return返回的值和函数返回类型不⼀致,系统会自动将返回的值隐式转换为函数的返回类型。
5、如果函数中存在 if 等分支的语句,则要保证每种情况下都有 return 返回,否则会出现编译错误。
6、函数的返回类型如果不写,编译器会默认函数的返回类型是int。
7、函数写了返回类型,但是函数中没有使用 return 返回值,那么函数的返回值是未知的。
Java
返回值类型:如果方法有返回值,返回值类型必须要与返回的实体类型一致,如果没有返回值,必须写成 void。
与C语言相比,Java 的方法没有默认返回类型,也不会自动将返回的值隐式转换成定义的返回类型。在将返回类型定义成 void 时,如果写了 return 并且后面什么也没有,方法就结束了。
四、返回类型
一般基本数据类型作为返回类型适用于两种语言,但值得注意的是,对于数组,两种语言有各自的定义方式。
C语言:数组只能作为函数参数
一维数组
#include <stdio.h>
// 形参可以写成数组形式,一维数组大小可省略
void set_arr(int arr[], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
arr[i] = -1;
}
}
// 形参数组也可以写成指针形式
void print(int* arr, int sz)
{
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]); // sz是10数组元素个数
print(arr, sz);
// 写一个函数将arr数组的所有元素全部设置成-1
set_arr(arr, sz);
//写一个函数,打印arr数组的所有元素
print(arr, sz);
return 0;
}
二维数组
#include <stdio.h>
void print(int arr[][5], int r, int c) // 数组中行号可以省略,列号不能省略
{
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main()
{
int arr[3][5] = { {1,2},{3,4,5},{3,4,5,6,7} };
print(arr, 3, 5);
return 0;
}
Java
数组可以直接作为返回类型
将数组的每一个元素放大到两倍并输出:
import java.util.Arrays
public class Test{
public static int[] fun(int[] array){ // 与C语言函数只能返回地址值不同的是,Java可以返回数组
int[] ret = new int[array.length]; // 创建新的数组,不改变原来的数组
for(int i = 0; i < array.length; i++){
ret[i] = array[i] * 2;
}
return ret;
}
public static void main(String[] args){
int[] arr = {1,2,3,4,5};
int[] tmp = fun(arr);
System.out.println(Arrays.toString(arr));
System.out.println(Arrays.toString(tmp));
}
}
直接将数组本身每一个元素放大2倍:
import java.util.Arrays
public static void fun2(int[] array){
for (int i = 0; i < array.length; i++) {
array[i] *= 2;
}
}
public static void main(String[] args){
int[] arr = {1,2,3,4,5};
System.out.println(Arrays.toString(arr));
fun2(arr);
System.out.println(Arrays.toString(arr));
}
五、嵌套使用
C语言:使用函数计算某年某月的天数
#include <stdbool.h>
bool is_leap_year(int y)
{
if ((y % 4 == 0) && (y % 100 != 0) || y % 400 == 0)
return true;
else
return false;
}
int get_days_of_month(int y, int m)
{
int days[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12 数组初始化时前面加多一个0,使其下标与月份对应
int d = days[m];
// 需要一个闰年判断的功能
if (is_leap_year(y) && (2 == m))
{
d += 1;
}
return d;
}
int main()
{
int year = 0;
int month = 0;
scanf("%d %d", &year, &month);
int day = get_days_of_month(year, month);
printf("%d\n", day);
return 0;
}
⚠️ Java中的方法是不能嵌套使用的。
六、函数调用
单个文件中
C语言使用函数时,遵循 “先声明再调用” 的原则。而函数定义放在主函数前面是一种特殊声明。
#include <stdio.h>
// int is_leap_year(int y); //函数声明
int is_leap_year(int); // 函数的声明中形式参数的名字可以省略
int main()
{
int y = 0;
scanf("%d", &y);
int r = is_leap_year(y); // 函数调用
if (r == 1)
printf("闰年\n");
else
printf("非闰年\n");
return 0;
}
// 函数定义
int is_leap_year(int y)
{
if (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))
return 1;
else
return 0;
}
Java对于方法的放置顺序并不在意,即无论是放在程序入口前还是后都不会报错,因为 Java 没有声明方法这一说。但方法必须放在类当中。且方法名不能像C语言一样有下划线,而是采用小驼峰命名法(如testDemo(),第一个单词首字母小写,后面的单词首字母需要大写)。
多个文件中
C语言
add.h 头文件,放置函数声明:
int add(int, int);
add.c 文件,放函数定义:
int add(int x, int y)
{
return x + y;
}
test.c 文件,调用 add() 函数,需要包含头文件
#include "add.h" // !包含自己写的头文件用的是双引号
int main()
{
int a = 0;
int b = 0;
scanf("%d%d", &a, &b);
int c = add(a, b);
printf("%d\n", c);
return 0;
}
如果没有 add.h 头文件,即没有函数声明,可使用 extern 关键字来声明外部符号(可以是函数,也可以是全局变量)
extern int add(int x, int y);
int main()
{
int a = 0;
int b = 0;
scanf("%d%d", &a, &b);
int c = add(a, b);
printf("%d\n", c);
return 0;
}
Java 在多个文件调用方法的内容较为复杂,且涉及类和对象等知识,需要另写一篇博客进行详细说明。
七、方法重载
对于Java语言,有一项C语言没有的知识,即方法重载。意义在于通过一个名字可以调用多种方法,方便。
特点
1、方法名称必须相同
2、参数类型、顺序、数量必须不一样
3、与返回值类型无关
注意返回类型不一样,但方法名、参数类型、顺序和数量一致是不属于方法重载的!
public static int add(int a, int b){
return a+b;
}
public static double add(int a, int b){
return a+b;
}
八、方法签名
在Java中有方法签名的概念,即经过编译器编译修改过之后方法最终的名字。具体组成:方法全路径名+参数列表+返回值类型,构成方法完整的名字。因为参数类型、顺序或者数量的不同,所以各自的签名不一样,也就能使机器识别出有不一样的方法。
在IDEA中查看签名的步骤:
1、打开本文件所在文件夹地址(这里是IDEA2020.1版本)
2、找到当前文件在磁盘中的位置,在终端打开,并输入 javap -v [你的文件名],然后回车
3、翻找方法签名
public static int add(int a, int b){ // 方法真正的名字是下面图片的
return a + b;
}
public static double add(double a, double b){
return a + b;
}
public static void main(String[] args) {
add(1,3);
add(5.4, 7.8);
}
上图中的 test_7_12.add:(II)I 和 test_7_12.add:(DD)D 就是方法签名,其中 I 是指 int 类型,D 是指double 类型。
以上就是C语言函数和Java语言方法在语法形式、形参与实参、return 返回值等形同与相似的地方啦,可能会有混乱的地方,注意区分。此外,
嵌套使用的对象只能是C语言中的函数,Java是不支持嵌套使用的。
C语言在调用函数时,要先声明再调用,多个文件中则要包含头文件;Java没有声明方法这一说,也不关心方法的顺序。
Java有特殊的方法重载和方法签名概念。