类的成员-方法
# 类的成员
Java的基本单位是类class
,Java成员即类中的成员,包括以下五个部分:
- 属性
- 方法
- 构造器
- 代码块/初始化块
- 内部类
# 方法method
什么是方法?
方法是类或对象行为特征的抽象,用来完成某个功能操作。在某些语言中也称为函数或过程。
将功能封装为方法的目的是,可以实现代码重用,简化代码。
==Java里的方法不能独立存在,所有的方法必须定义在类里。==
方法的声明与使用
# 语法格式
修饰符 返回值类型 方法名(形参列表){
……
return 返回值;
}
2
3
4
修饰符
- public,缺省,private, protected
- static、final (暂不考虑)
返回值类型:声明出返回值的类型。与方法体中“return 返回值”搭配使用
- 可以是基本数据类型
- 如果返回值类型是
void
,代表没有返回值,不需要用return
- 也可以是==对象==
方法名:属于标识符,命名时遵循标识符命名规则和规范,“见名知意”
形参列表:可以包含零个,一个或多个参数。多个参数时,中间用“,”隔开
- 参数类型可以是基本数据类型,也可以是对象
- 语法格式:数据类型 变量名1,数据类型 变量名2,数据类型 变量名3……
- 形参属于局部变量。
return:代表方法结束,作用是方法在执行完毕后返还给调用它的程序的数据。来返回指定类型的变量或常量。
- 如果返回值类型是
void
,就不用使用return
关键字; - 在同一个作用域(就是大括号的意思),return后面不能有执行语句
- 如果返回值类型是
返回值:可以是变量或者常量,配合
return
关键字一起用- 返回值的类型必须和返回值类型是一致的。
例如:
public class Person{
private String name;
private int age;
public int getAge(){
return age;
}
public void setAge(int i){
age = i;
}
public void eat(){
System.out.println("吃饭");
}
public void sleep(int hour){
System.out.println("睡了"+hour+"小时");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
如果按照是否有形参及返回值来对方法分类:
无返回值 | 有返回值 | |
---|---|---|
无形参 | void 方法名(){} | 返回值的类型方法名(){} |
有形参 | void 方法名(形参列表){} | 返回值的类型方法名(形参列表){} |
# 方法的调用
方法通过方法名被调用,且只有被调用才会执行
方法的调用过程分析:
注意:
方法被调用一次,就会执行一次
没有具体返回值的情况,返回值类型用关键字void表示,那么方法体中可以不必使用return语句。如果使用,仅用来结束方法。
定义方法时,方法的结果应该返回给调用者,交由调用者处理。
方法中只能调用方法或属性,不可以在方法内部定义方法。
# 方法的重载
重载的概念
overload
在同一个类中,存在多个同名的方法,方法的参数个数或者参数类型不同,与返回值无关,这叫做重载。
重载的特点
与返回值类型无关,只看参数列表,且参数列表必须不同。(参数个数或参数类型)。调用时,根据方法参数列表的不同来区别。
重载实例
//返回两个整数的和
int add(intx,inty){return x+y;}
//返回三个整数的和
intadd(intx,inty,intz){return x+y+z;}
//返回两个小数的和
double add(double x,doubley){return x+y;}
2
3
4
5
6
在通过对象调用方法时,如何确定某一个指定的方法
看好方法名和参数列表,重载的参数列表都是不相同的,所以只要找到对应的方法所需要的参数,就可以了。
其实我们用到最多的是重载是System.out.println
练习
package overload;
/**
* 编写程序,定义三个重载方法并调用。方法名为mOL。
* 三个方法分别接收一个int参数、两个int参数、一个字符串参数。分别执行平方运算并输出结果,相乘并输出结果,输出字符串信息。
* 在主类的main ()方法中分别用参数区别调用三个方法。
*/
public class Demo1 {
public static void main(String[] args) {
new Demo1().mOL(7);
new Demo1().mOL(9, 9);
new Demo1().mOL("test");
}
public void mOL(int num) {
System.out.println(num * num);
}
public void mOL(int num1, int num2) {
System.out.println(num1 * num2);
}
public void mOL(String str) {
System.out.println(str);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package overload;
/**
* 定义三个重载方法max(),
* 第一个方法求两个int值中的最大值,
* 第二个方法求两个double值中的最大值,
* 第三个方法求三个double值中的最大值,
* 并分别调用三个方法。
*/
public class Demo2 {
public static void main(String[] args) {
System.out.println(new Demo2().max(34, 46));
System.out.println(new Demo2().max(3.4, 1.2));
System.out.println(new Demo2().max(4.7, 45.3, 72.1));
}
public int max(int num1, int num2) {
return num1 > num2 ? num1 : num2;
}
public double max(double d1, double d2) {
return d1 > d2 ? d1 : d2;
}
public double max(double d1, double d2, double d3) {
return d1 > d2 ? (d1 > d3 ? d1 : d3) : (d2 > d3 ? d2 : d3);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 可变形参的方法
JavaSE 5.0 中提供了Varargs
(variable number of arguments)机制,允许直接定义能和多个实参相匹配的形参。从而,可以用一种更简单的方式,来传递个数可变的实参。
//JDK 5.0以前:采用数组形参来定义方法,传入多个同一类型变量
public static void test(int a ,String[] books);
2
//JDK5.0:采用可变个数形参来定义方法,传入多个同一类型变量
public static void test(int a ,String...books);
2
说明:
- 声明格式:==方法名(参数的类型名...参数名)==
- 可变参数:方法参数部分指定类型的参数个数是可变多个:0个,1个或多个
- 可变个数形参的方法与同名的方法之间,彼此构成重载
- 可变参数方法的使用与方法参数部分使用数组是一致的。二者不能共存,不能构成重载。
- 方法的参数部分有可变形参,需要放在形参声明的最后
- 在一个方法的形参位置,最多只能声明一个可变个数形参
例如:
package com.sauljwu.mybatisdemo;
public class TestOverload {
public void test(String[] msg) {
System.out.println("含字符串数组参数的test方法");
}
public void test1(String book) {
System.out.println("****与可变形参方法构成重载的test1方法****");
}
public void test1(String... books) {
System.out.println("****形参长度可变的test1方法****");
for(int i=0;i<books.length;i++){
System.out.println(books[i]);
}
}
public static void main(String[] args) {
TestOverload to = new TestOverload();
//下面两次调用将执行第二个test方法
to.test1();to.test1("aa" , "bb");
//下面将执行第一个test方法
to.TestOverload(new String[]{"aa"});
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 方法参数的值传递机制
方法,必须由其所在类或对象调用才有意义。若方法含有参数:
- 形参:方法声明时的参数
- 实参:方法调用时实际传给形参的参数值
Java的实参值如何传入方法呢?
Java里方法的参数传递方式只有一种:值传递。即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。
形参是==基本数据类型==:将实参基本数据类型变量的“
数据值
”传递给形参形参是==引用数据类型==:将实参引用数据类型变量的“
地址值
”传递给形参
意思是,
基本数据类型的参数传递
package method;
import switchTest.demo1;
public class Demo1 {
public static void main(String[] args) {
int x = 5;
System.out.println("main方法中的x = " + x);
Demo1 demo1 = new Demo1();
demo1.change(x);
System.out.println("main方法中的x = " + x);
}
public void change(int x){
System.out.println("change方法中的x = " + x);
x = 3;
System.out.println("change方法中的x = " + x);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
main方法中的x = 5
change方法中的x = 5
change方法中的x = 3
main方法中的x = 5
2
3
4
如果变量是基本数据类型,此时赋值是变量保存数据值,就算其他变量也赋值相同的数据,不会有影响,相互独立。
引用数据类型的参数传递
package method;
public class Demo2 {
public static void main(String[] args) {
Person person = new Person();
person.age = 5;
System.out.println("main方法中,未调用change,person.age = " + person.age);
change(person);
System.out.println("main方法中,已调用change,person.age = " + person.age);
}
public static void change(Person person){
System.out.println("change方法中,改变之前,person.age = " + person.age);
person.age = 3;
System.out.println("change方法中,改变之之后,person.age = " + person.age);
}
}
class Person{
int age;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
main方法中,未调用change,person.age = 5
change方法中,改变之前,person.age = 5
change方法中,改变之之后,person.age = 3
main方法中,已调用change,person.age = 3
2
3
4
内存分析:
如果变量是引用数据类型,此时赋值是变量保存对象内存整数地址,当2个变量都指向同一个对象时,其中一个变量改变数据时,另一个变量访问时,也会发现已经改变了的值。
还记得我前面提到的话吗?
如果把一个新的引用指向已经存在的对象,通过这个变量改变对象的值时,那么原来的变量访问对象的值时,会发现也改变了,因为2个引用都指向同一个对象的内存地址。
如果非要比喻的话:
引用(变量),可以理解为遥控器。
对象,理解为电视机。
引用可以多个,那么遥控器可以多个,也可以独立存在,任意一个遥控器改变了电视频道,就像代码中,使用其中一个引用改变对象的值,那么第二个引用去访问对象时,发现对象的值已经改变了,因为2个(变量)引用都指向同一个对象的内存地址。
# 面试题
方法一:调用完
method
方法退出系统
package method;
public class Test {
public static void main(String[] args) {
int a= 10;
int b= 10;
method(a, b);
System.out.println("a = " + a);
System.out.println("b = " + b);
}
public static void method(int a, int b) {
a *= 10;
b *= 20;
System.out.println("a = " + a);
System.out.println("b = " + b);
System.exit(0);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
方法2:重写
System.out.println
package method;
import java.io.PrintStream;
public class Test {
public static void main(String[] args) {
int a = 10;
int b = 10;
method(a, b);
System.out.println("a = " + a);
System.out.println("b = " + b);
}
public static void method(int a, int b) {
PrintStream ps = new PrintStream(System.out) {
@Override
public void println(String x) {
if ("a = 10".equals(x)) {
x = "a = 100";
} else if ("b = 10".equals(x)) {
x = "b = 200";
}
super.println(x);
}
};
System.setOut(ps);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 面试题2
# 面试题3
int[] arr = new int[10];
System.out.println(arr);//地址值? 是地址值
char[] arr1 = new char[10];
System.out.println(arr1);//地址值? 不是
2
3
4
5
int调用的方法如下:
public void println(Object x) {
String s = String.valueOf(x);
synchronized (this) {
print(s);
newLine();
}
}
2
3
4
5
6
7
因为传递的是引用数据类型,所以是相当于把地址值传递过去
char调用的方法如下:
public void println(char x[]) {
synchronized (this) {
print(x);
newLine();
}
}
2
3
4
5
6
因为传递的基本数据类型,所以打印的不是地址,直接拷贝一份数据,输出真实数据。
# 练习
定义一个Circle类,包含一个double型的radius属性代表圆的半径,一个findArea()方法返回圆的面积。
定义一个类PassObject,在类中定义一个方法printAreas(),该方法的定义如下:public void printAreas(Circle c,int time)在printAreas方法中打印输出1到time之间的每个整数半径值,以及对应的面积。例如,times为5,则输出半径1,2,3,4,5,以及对应的圆面积。
在main方法中调用printAreas()方法,调用完毕后输出当前半径值。程序运行结果如图所示。
package method;
public class Circle {
double radius;
public double findArea(){
return Math.PI * radius * radius;
}
}
2
3
4
5
6
7
8
9
10
package method;
public class PassObject {
public void printAreas(Circle c,int time){
System.out.println("半径\t面积");
for(int i=1;i<=time;i++){
c.radius = i;
System.out.println(i+"\t"+c.findArea());
}
}
public static void main(String[] args) {
PassObject passObject = new PassObject();
passObject.printAreas(new Circle(), 5);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
半径 面积
1 3.141592653589793
2 12.566370614359172
3 28.274333882308138
4 50.26548245743669
5 78.53981633974483
2
3
4
5
6
# 递归 recursion
什么是递归?
递归方法:一个方法体内调用它自身。
方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制。
递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环。
计算1-100之间所有自然数之和:
package recursion;
public class Demo1 {
public int recursion(int num){
if(num == 1){
return 1;
}
return num + recursion(num-1);
}
public static void main(String[] args) {
//计算1-100之间所有自然数之和
int recursion = new Demo1().recursion(100);
System.out.println("recursion = " + recursion);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
recursion = 5050
请用Java写出递归求阶乘(n!)的算法:
已经超出int范围了,如果是100,只能用BigInteger
package recursion;
import java.math.BigInteger;
public class Demo2 {
public BigInteger recursion(BigInteger num){
if(num.compareTo(new BigInteger("1")) == 0){
return new BigInteger("1");
}
return num.multiply(recursion(num.subtract(new BigInteger("1"))));
}
public static void main(String[] args) {
//计算1-100之间所有自然数之积
BigInteger recursion = new Demo2().recursion(new BigInteger("100"));
System.out.println("recursion = " + recursion);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
recursion = 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
已知有一个数列:f(0) = 1,f(1) = 4,f(n+2)=2*f(n+1) + f(n),其中n是大于0的整数,求f(10)的值。
f(n+2)=2*f(n+1) + f(n)
假设n等于0
f(0 + 2) = 2 * f(0 + 1) + f(0)
f(2) = 2*f(1)+f(0)
f(2) = 2 * 4 +1 = 9
求f(10) = f(8+2) = 2 * f(8+1) + f(8)
所以f(n)= 2*f(n-1)+f(n-2)
package recursion;
public class Demo3 {
public static void main(String[] args) {
//已知有一个数列:f(0) = 1,f(1) = 4,f(n+2)=2*f(n+1) + f(n),其中n是大于0的整数,求f(10)的值。
int f = new Demo3().f(10);
System.out.println("f = " + f);
}
public int f(int n) {
if(n == 0){
return 1;
}else if(n == 1){
return 4;
}else{
return 2 * f(n - 1) + f(n-2);
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
f = 10497
而且这个公式,当n=2时,也能计算出结果是9。
输入一个数据n,计算斐波那契数列(Fibonacci)的第n个值1 1 2 3 5 8 13 21 34 55
规律:一个数等于前两个数之和
要求:计算斐波那契数列(Fibonacci)的第n个值,并将整个数列打印出来
package recursion;
/**
* 输入一个数据n,计算斐波那契数列(Fibonacci)的第n个值 1 1 2 3 5 8 13 21 34 55
* <p>
* 规律:一个数等于前两个数之和
* <p>
* 要求:计算斐波那契数列(Fibonacci)的第n个值,并将整个数列打印出来
*/
public class Demo4 {
public static void main(String[] args) {
int n = 10;
for (int i = 1; i <= 10; i++) {
int fibonacci = new Demo4().fibonacci(i);
System.out.print(fibonacci + "\t");
}
}
public int fibonacci(int n) {
if (n < 3) {
return 1;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
1 1 2 3 5 8 13 21 34 55
汉诺塔(港台:河内塔)是根据一个传说形成的数学问题:
有三根杆子A,B,C。A杆上有 N 个 (N>1) 穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至 C 杆:
- 每次只能移动一个圆盘;
- 大盘不能叠在小盘上面。
提示:可将圆盘临时置于 B 杆,也可将从 A 杆移出的圆盘重新移回 A 杆,但都必须遵循上述两条规则。
问:如何移?最少要移动多少次?
package recursion;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* **汉诺塔**(港台:**河内塔**)是根据一个传说形成的数学问题:
* <p>
* 有三根杆子A,B,C。A杆上有 N 个 (N>1) 穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至 C 杆:
* <p>
* 1. 每次只能移动一个圆盘;
* 2. 大盘不能叠在小盘上面。
* <p>
* 提示:可将圆盘临时置于 B 杆,也可将从 A 杆移出的圆盘重新移回 A 杆,但都必须遵循上述两条规则。
* <p>
* 问:如何移?最少要移动多少次?
*/
public class Demo5 {
public static void main(String[] args) {
// new Demo5().hanoi(3, 'A', 'B', 'C');
List list = new ArrayList<>();
list.add(15);
list.add(10);
list.add(5);
new Demo5().init(list);
}
public void init(List a) {
int n = a.size();
List b = new ArrayList();
List c = new ArrayList();
test(n, a, b, c,new int[]{0});
}
public void test(int n, List a, List b, List c,int[] count) {
if (n == 1) {
count[0]++;
System.out.println("--------第"+count[0]+"次-------");
c.add(a.remove(a.size() - 1));
System.out.println(a.toString());
System.out.println(b.toString());
System.out.println(c.toString());
System.out.println("---------------------");
}else{
test(n - 1, a, c, b,count);
test(1, a, b, c,count);
test(n - 1, b, a, c,count);
}
}
public void hanoi(int n, char a, char b, char c) {
if (n == 1) {
System.out.println(a + ">>" + c);
} else {
hanoi(n - 1, a, c, b);
hanoi(1, a, b, c);
hanoi(n - 1, b, a, c);
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63