方法和包

  • 什么是方法?
  • 基本语法
  • 使用规则
  • 方法的重载
  • 重载的规则
  • 包 (package)
  • 包的作用
  • 基本语法



什么是方法?

方法的本质就是一个代码片段, 类似于 C 语言中的 函数。它存在的意义为:

  1. 是能够模块化的组织代码(当代码规模比较复杂的时候)。
  2. 做到代码被重复使用, 一份代码可以在多个位置使用。
  3. 让代码更好理解更简单。
  4. 直接调用现有方法开发, 不必重复造轮子。

请看问题:

  • 输出 1! + 2! + 3! + 4! + 5! 的值。

传统解法:

int sum = 0;
for (int i = 1; i <= 5; i++) {
    int tmp = 1;
    for (int j = 1; j <= i; j++) {
        tmp *= j;
   }
   sum += tmp;
}
System.out.println("sum = " + sum);

这段代码中使用了双重循环, 还比较容易写错。这个场景我们就可以使用方法来优化这个代码。

基本语法

方法的定义:

public static 方法返回值 方法名称([参数类型 形参 ...]){
	方法体代码;
	[return 返回值];
}

方法的调用:

返回值变量 = 方法名称(实参...);

具体案例就使用上面 阶乘之和 的例题来讲解,代码可以修改为:

class Test {
	//主(main)方法
	public static void main(String[] args) {
		int sum = 0;
		for (int i = 1; i <= 5; i++) {
			sum += factor(i);
		}
		System.out.println("sum = " + sum);
	}
	
	//专门计算阶乘的方法
	public static int factor(int n) {
		System.out.println("计算 n 的阶乘中! n = " + n);
		int result = 1;
		for (int i = 1; i <= n; i++) {
			result *= i;
		}
		return result;
	}
}

// 执行结果
计算 n 的阶乘中! n = 1
计算 n 的阶乘中! n = 2
计算 n 的阶乘中! n = 3
计算 n 的阶乘中! n = 4
计算 n 的阶乘中! n = 5
sum = 153

我们可以看到:使用方法,直观逻辑上避免了使用二重循环,让代码更简单清晰,可读性更高。

使用规则

  • 定义方法的时候,不会执行方法的代码.,只有调用的时候才会执行。
  • 当方法被调用的时候,会将实参赋值给形参
  • 参数传递完毕后, 就会执行到方法体代码。
  • 当方法执行完毕之后(遇到 return 语句),就执行完毕, 回到方法调用位置,按照执行流继续往下执行。
  • 一个方法可以被多次调用。

方法的重载

有些时候我们需要用一个函数同时兼容多种参数的情况, 我们就可以使用到方法重载。

例如以下场景:

class Test {
	public static void main(String[] args) {
		int a = 10;
		int b = 20;
		int ret = add(a, b);	//int类型数据的加法
		System.out.println("ret = " + ret);
		double a2 = 10.5;
		double b2 = 20.5;
		double ret2 = add(a2, b2);	//double类型数据的加法
		System.out.println("ret2 = " + ret2);
	}
	public static int add(int x, int y) {
		return x + y;
	}
}

// 编译出错
Test.java:13: 错误: 不兼容的类型: 从double转换到int可能会有损失
 double ret2 = add(a2, b2);
 				   ^

究其原因是因为参数类型不匹配导致的,所以不能使用现有的 add 方法。

那我们考虑创建两个对应的方法来操作:

public static int addInt(int x, int y) {
	return x + y;
}
public static double addDouble(double x, double y) {
	return x + y;
}

说可行也确实可行,但如果参数类型很多,就要起许多独特的方法名,对用户也并不友好,不如全部都叫做 add ,统一使用。所以就用到方法的重载

class Test {
	public static void main(String[] args) {
		int a = 10;
		int b = 20;
		int ret = add(a, b);
		System.out.println("ret = " + ret);
		
		double a2 = 10.5;
		double b2 = 20.5;
		double ret2 = add(a2, b2);
		System.out.println("ret2 = " + ret2);
		
		double a3 = 10.5;
		double b3 = 10.5;
		double c3 = 20.5;
		double ret3 = add(a3, b3, c3);
		System.out.println("ret3 = " + ret3);
	}  
	@Overload //类内部方法-重载
	public static int add(int x, int y) {
		return x + y;
	}
	@Overload 
	public static double add(double x, double y) {
		return x + y;
	}
	@Overload 
	public static double add(double x, double y, double z) {
		return x + y + z;
	}
}

方法的名字都叫 add,但是有的 add 是计算 int 相加, 有的是 double 相加; 有的计算2个数字相加, 有的是计算3个数字相加。

同一个方法名字, 提供不同版本的实现, 称为方法的重载

@Overload 为重载的标签,不必须,但最好进行标记以便阅读程序。

重载的规则

针对同一个类:

  • 方法名相同
  • 方法的参数不同(参数个数或者参数类型)
  • 方法的返回值类型不影响重载。请看代码:
class Test {
	public static void main(String[] args) {
		int a = 10;
		int b = 20;
		int ret = add(a, b);
		System.out.println("ret = " + ret);
	}
	public static int add(int x, int y) {
		return x + y;
	}
	public static double add(int x, int y) {
		return x + y;
	}
}
// 编译出错
Test.java:13: 错误: 已在类 Test中定义了方法 add(int,int)
	public static double add(int x, int y) {
	^
1 个错误

所以当两个方法的名字相同,参数也相同,但是返回值不同的时候,不构成重载。


包 (package)

为了更好地组织类,Java 提供了包机制,类似于C++中的命名空间(namespace)用于区别类名。

包的作用

  1. 把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用
  2. 如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突
  3. 包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。

Java 使用包(package)这种机制是为了防止命名冲突,访问控制,提供搜索和定位类(class)、接口、枚举(enumerations)和注释(annotation)等,把不同的 java 程序分类保存,更方便的被其他 java 程序调用。
总的来说分为两大功能:提供访问保护命名空间管理

基本语法

包语句的语法格式为:

package pkg1[.pkg2[.pkg3…]];

例如,一个Jiedaibao.java 文件它的内容

package net.java.util;
public class Jiedaibao{
   ...
}

那么它的路径应该是 net/java/util/Jiedaibao.java 这样保存的。

以下是一些 Java 中的包:

  • java.lang:打包基础的类
  • java.io:包含输入输出功能的函数

开发者可以自己把一组类和接口等打包,并定义自己的包。而且在实际开发中这样做是值得提倡的,当你自己完成类的实现之后,将相关的类分组,可以让其他的编程者更容易地确定哪些类、接口、枚举和注释等是相关的。

工程上一般使用com.公司名.项目名.模块名.……的形式作为包名。