java 方法
(1)什么是方法
完成一个功能。一个方法只完成一个功能。
public class Demo01 {
// 主方法
public static void main(String[] args) {
int sum = add(1, 2);//调用方法。1,2是实参:实际传递的参数
System.out.println(sum);
test();//调用方法
}
/**
* static 类变量,静态变量(public、static修饰符)
* int(static后的int) 返回值的类型
* add 方法名
* int a, int b 形参:定义的参数
*/
public static int add(int a, int b) {
return a + b;
}
/**
* void 返回值为空
* test 方法名
*/
public static void test() {
// 练习2:输出1-1000之间能被5整除的数,并且每行输出3个
for (int i = 0; i <= 1000; i++) {
if (i % 5 == 0) {
System.out.print(i + "\t");//print不换行,println换行
}
if (i != 0 && (i - 10) % (5 * 3) == 0) {//5 * 3表示3个
System.out.println();
}
}
}
}
(2)方法的定义和调用【笔试题】
- 修饰符:可选。如何调用该方法,定义了该方法的访问类型。
- 返回值类型:[returnValueType]方法可能会返回值。没有返回值用关键字 void 。
- 方法名:方法的实际名字。
- 参数类型:可选。当方法被调用时,传递值给参数。方法的两种参数:实参、形参。
- 实参:实际传递的参数
- 形参:定义的参数
- 方法体:方法的具体功能。
修饰符 返回值类型 方法名(参数类型 参数名){
……
方法体
……
return 返回值; 一般放在最下面。有终止方法作用。
}
[拓展]值传递(java)和引用传递【笔试题:Java中为什么只有值传递?】
- 值传递:方法调用时,实参数把值传形参,形参的值改变不影响实参的值。
- 引用传递:也称为传地址。方法调用时,实参的引用(地址,而不是参数的值)传给形参,形参的值改变将会影响实参的值。
Java是值传递:在Java中无论是按值传递还是按引用传递都是把值传递过去,所以一般在Java中称作按值传递。引用传递也是一种值传递,只不过它的值不是具体的数据,而是一个地址。
参数是基本数据类型,复制的是具体值;如果参数是引用类型,把地址当成值,复制的是地址;还有String类是一个非常特殊的类,它是不可修改的。
// User 对象
public class User {
public String name="xiao ming";
public String toString() {
return "Person{" +
"name='" + name +
'}';
}
}
package com.chendian.method;
public class Demo02 {
public static void main(String[] args) {
// 基本数据类型
int a = 2;
test1(a);
System.out.println("test1 实参:" + a);
// 引用类型:字符串
String s1 = "hello world";
test2(s1);
System.out.println("test2 实参:" + s1);
// 对于引用类型
User user1 = new User();
test3(user1);
System.out.println("test3 实参:" + user1);
User user2 = new User();
test4(user2);
System.out.println("test4 实参:" + user2);
}
/**
* 基本数据类型:传递的是该变量的一个副本,形参的修改不会影响到实参
* print:
* test1 形参:16
* test1 实参:2
*/
public static void test1(int a) {
a = 16;
System.out.println("test1 形参:" + a);
}
/**
* 引用类型:字符串 特殊引用类
* print:
* test2 形参:test2
* test2 实参:hello world
*/
public static void test2(String s1) {
s1 = "test2";
System.out.println("test2 形参:" + s1);
}
/**
* 引用类型:传递的是该对象地址的一个副本,形参实参指向同一个对象,所以形参的修改会影响到实参
* print:
* test3 形参:Person{name='xiao wang}
* test3 实参:Person{name='xiao wang}
*/
public static void test3(User user1) {
user1.name = "xiao wang";
System.out.println("test3 形参:" + user1);
}
/**
* 引用类型:创建一个新对象,对传入的引用的改变,形参实参指向不同的对象,形参的修改就不会影响到实参
* print:
* test4 形参:Person{name='xiao wang}
* test4 实参:Person{name='xiao ming}
*/
public static void test4(User user2) {
user2 = new User();
user2.name = "xiao wang";
System.out.println("test4 形参:" + user2);
}
}
(3)方法的重载【笔试题】
在一个类中,方法名相同,但形参的个数、类型或顺序不同,与返回值无关。
- 方法的重载规则:【笔试题】
- 方法名必须相同
- 参数列表必须不同(个数不同、类型不同或参数排列顺序不同等)
- 方法返回的类型可以相同或不相同。
- 只有返回类型不同不是方法的重载。
- 只是形参名不同也不是方法的重载。
- 方法名相同时,编译器会根据调用方法的参数个数、参数类型等逐个匹配,已选择对应的方法,如果匹配失败,则编译器报错
// 定义一个Person类
public class Person {
public void Student() {
System.out.println("Student");
}
public void Student(String name) {
System.out.println("Student name:" + name);
}
//形参:类型不同
public void Student(int age) {
System.out.println("类型不同:" + age);
}
//形参:数量不同
public void Student(String name, int age) {
System.out.println("数量不同:" + name + " " + age);
}
//形参:顺序不同
public void Student(int age, String name) {
System.out.println("顺序不同:" + age + " " + name);
}
}
// 使用Person类
public class Demo03 {
public static void main(String[] args) {
Person person = new Person();
person.Student("Xiao Li");//Student name:Xiao Li
person.Student(18);//类型不同:18
person.Student("Xiao Li",18);//数量不同:Xiao Li 18
person.Student(18,"Xiao Li");//顺序不同:18 Xiao Li
}
}
(4)命令行传参
靠命令将参数传给main函数。[了解]
package com.chendian.method;
public class Demo04 {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
System.out.println("arg[" + i + "]:" + args[i]);
}
}
}
// 命令=>进到当前文件,编译,退到src文件夹,传值并且解释。
// C:\Users\chendian\Desktop\Hello\src>cd .\com\chendian\method
// C:\Users\chendian\Desktop\Hello\src\com\chendian\method>javac Demo04.java
// C:\Users\chendian\Desktop\Hello\src\com\chendian\method>cd..
// C:\Users\chendian\Desktop\Hello\src\com\chendian>cd..
// C:\Users\chendian\Desktop\Hello\src\com>cd..
// C:\Users\chendian\Desktop\Hello\src>java com.chendian.method.Demo04 my name is chendian
// arg[0]:my
// arg[1]:name
// arg[2]:is
// arg[3]:chendian
(5)可变参数
- JDK1.5开始,Java支持同类型的可变参数给一个方法
- 在方法声明中,在指定参数类型后加省略号(…)。
- 一个方法只能指定一个可变参数,必须时方法的最后一个参数。(任何普通参数在它之前声明)
public class Demo05 {
public static void main(String[] args) {
Demo05 demo05 = new Demo05();
demo05.test(1, 2, 3, 4);
}
/**
* @param x 普通参数
* @param i 可变参数:也称不定项参数(...i)
*/
public void test(int x, int... i) {
System.out.println(x);//1
for (int j = 0; j < i.length; j++) {
System.out.print(i[j] + ",");//2,3,4,
}
// System.out.println(i[4]); // 报错:ArrayIndexOutOfBoundsException 数组越界 没有i[4]
}
}
(6)递归【面试题】
- A方法调用A方法。自己调用自己。
- 尽量不要使用,虽然减少代码量,但效率慢,可能会造成内存溢出。[了解递归思想即可]小计算才可用
- 可以把大型复杂的问题层层转化为一个规模较小的问题求解。
- 递归结构包括:
- 递归头:什么时候不调用自身方法。没有头,将陷入死循环。
- 递归体:什么时候需要调用自身方法。
public class Demo06 {
public static void main(String[] args) {
Demo06 demo06 = new Demo06();
demo06.test();
System.out.println(f(5));
}
/*
阶乘 5!=5*4*3*2*1
在栈中 5 * f(4) * f(3) * f(2) * f(1) f(1)=1有值(边界条件,递归头) 返回来带值进去运算
*/
public static int f(int n) {
if (n == 1) {
return 1;
} else {
return n * f(n - 1);
}
}
public void test() {
//test();//StackOverflowError 内存溢出 没有递归头
}
}