在java学习过程中,我们不难发现有很多重复使用的功能代码块,每次使用如果都要重新写一遍,岂不是很麻烦,就算是“ cv ”大法,感觉也不是很方便,那么, 有什么办法可以解决这个问题呢?
方法!
java中,一段可重用的,用于执行特定功能的代码块叫做方法 ,它可以接收参数、返回结果,并且可以被多次使用。
[修饰符] 返回值类型 方法名([参数列表]) [throws 异常类型] {
// 方法体
}
[throws 异常类型]在IO、网络、数据库等底层操作中很常见,但是业务层出现频率不高,更倾向于try-catch捕获并处理,而不是抛出,作为初学者我们暂时可以不做研究,可以不写,后续需要用的时候在做详细学习
我们现在主要研究一下它的其他组成部分:
public:公用方法,可以被任何类访问
protected:受保护的方法,可以在包内和子类中访问
private:私有方法,只能在定义它的类中访问
默认(不写):包访问权限,仅在同一个包内可以访问
权限宽松到严格:public -> protected -> 默认(不写) -> private
方法必须声明返回值类型,就算没有也要使用void
遵循小驼峰命名,eg:arrAvg(...){...}
可以有多个参数,但是参数类型必须明确
实现功能逻辑的代码块
接下来我们看一下方法中最重要的兄弟俩:重载和重写
在同一个类中定义的多个方法,它们方法名相同,而形参列表不同(数据类型不同、数量不同、顺序不同),这样就构成了方法的重载,与返回值类型无关
eg:
//数据类型不同
public int add(int a, int b){
return a + b;
}
public double add(double a, double b){
return a + b;
}
//形参数量不同
public int add(int a, int b){
return a + b;
}
public int add(int a, int b, int c){
return a + b + c;
}
//形参顺序不同
public void print(int a, double b){
System.out.println("int double");
}
public void print(double a, int b){
System.out.println("double int");
}
但是不推荐只是参数顺序不同构成的重载,避免引起调用歧义和差劲的代码可读性
当子类继承父类的时候,可以重写父类的方法,从而提供不同的实现
eg:
class Animal {
public void makeSound() {
System.out.println("Animal sound");
}
}
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Bark");
}
}
子类重写的方法名和参数列表必须和父类相同
返回值类型不能比父类更宽
访问权限不能比父类更严格(eg:父类protected,子类不能是private)
这是java中特殊的方法,它是程序的入口点,我们前面提到的jvm启动时会寻找并执行这个方法。
——它的签名是固定的,必须是public static void main(String[] xxx)
——每个程序有且仅有一个入口方法
这里指的是一个应用程序,一个项目中可以有多个main,但是只能把一个设为程序的入口,其他可以是测试入口,比如用我们之前提到的java命令,在终端中运行,eg:
java Application //运行应用程序
java TestClass //运行测试
——自动调用,由jvm执行,不需要手动调用
——使用static关键字修饰的方法,属于类,不属于对象
——可以通过类名直接调用,无需创建对象
public class Test {
public static void main(String[] args) {
// 静态方法可以直接通过类名调用
MyClass.staticMethod();
// 实例方法需要先创建对象
MyClass obj = new MyClass();
obj.instanceMethod();
}
}
——不能直接访问非静态成员的变量和方法
public class Example {
private int instanceVar = 10;
private static int staticVar = 20;
public static void staticMethod() {
// System.out.println(instanceVar); // ❌ 编译错误!不能访问实例变量
System.out.println(staticVar); // ✅ 可以访问静态变量
// instanceMethod(); // ❌ 编译错误!不能调用实例方法
staticMethod2(); // ✅ 可以调用其他静态方法
}
public static void staticMethod2() {
System.out.println("另一个静态方法");
}
public void instanceMethod() {
System.out.println(instanceVar); // ✅ 实例方法可以访问实例变量
System.out.println(staticVar); // ✅ 实例方法也可以访问静态变量
staticMethod(); // ✅ 实例方法可以调用静态方法
}
}
诶,那有没有间接访问的办法呢?
有的兄弟有的
1、创建类的实例对象(最常见)
public class Example {
private int instanceVar = 100;
private String name = "张三";
// 静态方法
public static void staticMethod() {
// ❌ 直接访问 - 编译错误
// System.out.println(instanceVar);
// ✅ 间接访问 - 通过创建对象实例
Example obj = new Example();
System.out.println(obj.instanceVar); // 输出: 100
System.out.println(obj.name); // 输出: 张三
}
public static void main(String[] args) {
staticMethod();
}
}
2、通过参数传递对象实例
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
// 静态方法通过参数访问非静态成员
public static void printPersonInfo(Person person) {
System.out.println("姓名: " + person.getName()); // 通过参数访问
}
public static void main(String[] args) {
Person p = new Person("李四");
printPersonInfo(p); // 输出: 姓名: 李四
}
}
3、在静态方法内部创建并使用对象
public class Calculator {
private int result = 0;
public void add(int value) {
result += value;
}
public int getResult() {
return result;
}
public static void performCalculation() {
// 在静态方法中创建对象并使用
Calculator calc = new Calculator();
calc.add(10);
calc.add(5);
System.out.println("计算结果: " + calc.getResult()); // 输出: 计算结果: 15
}
public static void main(String[] args) {
performCalculation();
}
}
——不能使用this和super关键字
——方法名和类名相同
——没有返回值类型,void也不能写
——可以重载
eg:
public class Person {
public Person() {
// 默认构造方法
}
public Person(String name) {
// 带参构造方法
}
}
——返回值类型 和实际return的值类型一定要相同
——形参列表中的数据类型和变量名不可以少
——普通方法可以调用普通方法,但是不能调用main方法
——方法必须先定义再使用
——实际参数类型一般要和形参类型一致(除非可以隐式类型转换,但是不建议)
这种情况不是重载:
重载和变量名无关,重点是变量的数据类型
public int add(int a, int b){
return a + b;
}
public int add(int b, int a){
return b + a;
}
虽然 对象调用静态方法是合法的,但是这样会误导大家,以为是实例方法,其实本质还是类调用的静态方法,平时一定注意避免这种写法!
不仅创建不必要的对象浪费性能,还会产生误导性,导致代码可读性差
public class MyClass {
public static void staticMethod() {
System.out.println("静态方法");
}
}
public class Main {
public static void main(String[] args) {
// 推荐方式:通过类名调用
MyClass.staticMethod();
// 不推荐但合法:通过对象调用静态方法
MyClass obj = new MyClass();
obj.staticMethod(); // 可以工作,但不建议这样做
}
}
java中所有参数传递都是值传递,包括对象引用也是传递引用的值(副本)
public static void changeValue(StringBuilder sb) {
// sb是原引用的一个副本,指向同一个对象
sb = new StringBuilder("new"); // 修改的是副本引用,指向新对象
// 原来的sb引用没有改变
}
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("old"); // sb指向"old"对象
System.out.println("调用前: " + sb.toString()); // 输出: old
changeValue(sb); // 传递sb引用的值(地址副本)
System.out.println("调用后: " + sb.toString()); // 输出: old(未改变)
}
public void print(int nums) {}
public void print(double nums) {}
// 调用
print(1); // 编译错误:不明确的方法调用
当调用print(1)时,1是int,可以匹配int,也可以自动类型转换匹配double,编译器选择困难了
今天的分享就到这里,欢迎大家补充斧正