Java面向对象是Java中的重点,也是难点,上一篇文章中我们讨论了其中一些的知识点,本篇文章我们将继续讲述Java面向对象,探讨方法的使用以及一些注意点。
目录
5、类的成员之二:方法(method)
5.1 方法(method、函数)的理解
1、方法是类或对象行为特征的抽象,用来完成某个功能操作。在某些语言也称为函数或过程。
2、将功能封装为方法的目的是,可以实现代码重用,减少冗余,简化代码
3、Java里的方法不能独立存在,所有的方法必须定义在类里。
举例:
public class Person{
private inr age;
public int getAge(){ //声明方法getAge()
return age;
}
public void setAge(int i){ //声明方法setAge()
age = 1; //将参数i的值赋给类的成员变量age
}
}
5.2如何生命方法
声明方法的语法格式
[修饰符] 返回值类型 方法名([形参列表])[throws 异常列表]{
方法体的功能代码
}
(1)一个完整的方法=方法头+方法体
方法头就是 [修饰符] 返回值类型 方法名([形参列表]) [throws 异常列表],也称为方法签名。通常调用方法是只需要关住方法头就行,从方法头可以看出这个方法的功能和调用方式。
方法体就是方法被调用后要执行的代码。对于调用者来说,不了解方法体如何实现的,并不影响方 法的使用。
(2)方法头可能包含5个部分
1.修饰符:可选的。方法的修饰符也有很多,例如:public、protected、private、static、abstract、 native、final、synchronized等,后面会一一学习。
其中,权限修饰符有public、protected、private。在讲封装性之前,我们先默认使用pulbic修 饰方法。 其中,根据是否有static,可以将方法分为静态方法和非静态方法。
其中静态方法又称为类方 法,非静态方法又称为实例方法。咱们在讲static前先学习实例方法。
2.返回值类型: 表示方法运行的结果的数据类型,方法执行后将结果返回到调用者。
无返回值,则声明:void
有返回值,则声明出返回值类型(可以是任意类型)。与方法体中“ return 返回值 ”搭配使 用
3.方法名: 属于标识符,命名时遵循标识符命名规则和规范,“见名知意”
4.形参列表:表示完成方法体功能时需要外部提供的数据列表。可以包含零个,一个或多个参数。
无论是否有参数,()不能省略
如果有参数,每一个参数都要指定数据类型和参数名,多个参数之间使用逗号分隔
参数的类型可以是基本数据类型、引用数据类型
(3)方法体
方法体必须有{}括起来,在{}中编写完成方法功能的代码
(4)关于方法体中return语句的说明
1.return语句的作用是结束方法的执行,并将方法的结果返回去
2.如果返回值类型不是void,方法体中必须保证一定有 return 返回值; 语句,并且要求该返回值结果的 类型与声明的返回值类型一致或兼容。
3.如果返回值类型为void时,方法体中可以没有return语句,如果要用return语句提前结束方法的执 行,那么return后面不能跟返回值,直接写return ; 就可以.
4.return语句后面就不能再写其他代码了,否则会报错:Unreachable code
代码示例:
package com.atguigu.test04.method;
public class MethodDefineDemo {
public void sayHello(){
System.out.println("hello")
}
public void printRectangle(int length, int width, char sign){
for (int i = 1; i <= length ; i++) {
for(int j=1; j <= width; j++){
System.out.print(sign);
}
System.out.println();
}
}
public int getIntBetweenOneToHundred(){
return (int)(Math.random()*100+1);
}
public int max(int a, int b){
return a > b ? a : b;
}
}
5.3 如何调用实例方法
方法调用格式:对象.方法名([实参列表])
示例:
package com.atguigu.test04.method;
public class MethodInvokeDemo {
public static void main(String[] args) {
//创建对象
MethodDefineDemo md = new MethodDefineDemo();
System.out.println("--------------------方法调用演示----------------");
//调用MethodDefineDemo类中无参无返回值的方法sayHello
md.sayHello();
md.sayHello();
md.sayHello();
//调用一次,执行一次,不调用不执行
System.out.println("------------------------------------------------");
//调用MethodDefineDemo类中有参无返回值的方法printRectangle
md.printRectangle(5,10,'@');
System.out.println("------------------------------------------------");
//调用MethodDefineDemo类中无参有返回值的方法getIntBetweenOneToHundred
md.getIntBetweenOneToHundred();//语法没问题,就是结果丢失
int num = md.getIntBetweenOneToHundred();
System.out.println("num = " + num);
System.out.println(md.getIntBetweenOneToHundred());
//上面的代码调用了getIntBetweenOneToHundred三次,这个方法执行了三次
System.out.println("------------------------------------------------");
//调用MethodDefineDemo类中有参有返回值的方法max
md.max(3,6);//语法没问题,就是结果丢失
int bigger = md.max(5,6);
System.out.println("bigger = " + bigger);
System.out.println("8,3中较大者是:" + md.max(8,9));
}
}
5.4 使用的注意点
(1)必须先声明后使用,且方法必须定义在类的内部
(2)调用一次就执行一次,不调用不执行。
(3)方法中可以调用类中的方法或属性,不可以在方法内部定义方法。
5.5 关键字return的使用
return在方法中的作用:
作用1:结束一个方法
作用2:结束一个方法的同时,可以返回数据给方法的调用者
注意点:在return关键字的直接后面不能声明执行语句
5.6 方法调用内存分析
1.方法没有被调用的时候,都在方法区中的字节码文件(.class)中存储。
2.方法被调用的时候,需要进入到栈内存中运行。方法每调用一次就会在栈中有一个 入栈 动作,3即给当前方法开辟一块独立的内存区域,用于存储当前方法的局部变量的值。
3.当方法执行结束后,会释放该内存,称为出栈 ,如果方法有返回值,就会把结果返回调用处,如 果没有返回值,就直接结束,回到调用处继续执行下一条指令。
4.栈结构:先进后出,后进先出。
示例:
public class Person {
public static void main(String[] args) {
Person p1 = new Person();
p1.eat();
}
public static void eat() {
sleep();
System.out.println("人:吃饭");
}
public static void sleep(){
System.out.println("人:睡觉");
doSport();
}
public static void doSport(){
System.out.println("人:运动");
}
}
内存分析:
6.对象数组
数组的元素可以是基本数据类型,也可以是引用数据类型。当元素是引用类型中的类时,我们称为对象 数组。
注意点:
对象数组,首先要创建数组对象本身,即确定数组的长度,然后再创建每一个元素对象,如果不创建, 数组的元素的默认值就是 null ,所以很容易出现 空指针异常NullPointerException 。
7.再看方法(进阶)
7.1 方法的重载
1、概念及特点
方法重载:在同一个类中,允许存在一个以上的同名方法,只要他们的参数列表不同即可。参数列表不同,意味着参数个数或参数类型的不同
重载的特点:与修饰符、返回值类型无关,只看参数列表,且参数列表必须不同。(参数个数或参 数类型)。调用时,根据方法参数列表的不同来区别。
重载方法调用:JVM通过方法的参数列表,调用匹配的方法。 先找个数、类型最匹配的,再找个数和类型可以兼容的,如果同时多个方法可以兼容将会报错
7.2 可变个数的形参
格式:方法名(参数的类型名 ...参数名)
示例:
//JDK 5.0以前:采用数组形参来定义方法,传入多个同一类型变量
public static void test(int a ,String[] books);
//JDK5.0:采用可变个数形参来定义方法,传入多个同一类型变量
public static void test(int a ,String...books);
特点:
1. 可变参数:方法参数部分指定类型的参数个数是可变多个:0个,1个或多个
2. 可变个数形参的方法与同名的方法之间,彼此构成重载
3. 可变参数方法的使用与方法参数部分使用数组是一致的,二者不能同时声明,否则报错。
4. 方法的参数部分有可变形参,需要放在形参声明的最后
5. 在一个方法的形参中,最多只能声明一个可变个数的形参
7.3 方法的参数传递机制
1、形参和实参
形参(formal parameter):在定义方法时,方法名后面括号()中声明的变量称为形式参数,简称形 参。
实参(actual parameter):在调用方法时,方法名后面括号()中的使用的值/变量/表达式称为实际 参数,简称实参。
2、参数传递机制:值传递
Java里方法的参数传递方式只有一种:值传递 。即将实际参数值的副本(复制品)传入方法内,而参数 本身不受影响。
形参是基本数据类型:将实参基本数据类型变量的“数据值”传递给形参
形参是引用数据类型:将实参引用数据类型变量的“地址值”传递给形参
示例:
形参是基本数据类型
public class Test {
public static void main(String[] args) {
int m = 10;
int n = 20;
System.out.println("m = " + m + ", n = " + n);
ValueTransferTest1 test = new ValueTransferTest1();
test.swap(m, n);
System.out.println("m = " + m + ", n = " + n);
}
public void swap(int m,int n){
int temp = m;
m = n;
n = temp;
}
}
形参是引用数据类型
public class Test {
public static void main(String[] args) {
Data d1 = new Data();
d1.m = 10;
d1.n = 20;
System.out.println("m = " + d1.m + ", n = " + d1.n);
//实现 换序
ValueTransferTest2 test = new ValueTransferTest2();
test.swap(d1);
System.out.println("m = " + d1.m + ", n = " + d1.n);
}
public void swap(Data data){
int temp = data.m;
data.m = data.n;
data.n = temp;
}
}
class Data{
int m;
int n;
}
7.4 递归方法
递归方法调用:方法自己调用自己的现象就称为递归。
递归的分类:直接递归、间接递归。
直接递归:方法自身调用自己。
public void methodA(){
methodA();
}
间接递归:可以理解为A()方法调用B()方法,B()方法调用C()方法,C()方法调用A()方法。
public static void A(){
B();
}
public static void B(){
C();
}
public static void C(){
A();
}
1.递归方法包含了一种 隐式的循环 。
2.递归方法会 重复执行 某段代码,但这种重复执行无须循环控制。
3.递归一定要向 已知方向 递归,否则这种递归就变成了无穷递归,停不下来,类似于 死循环 。最终 发生 栈内存溢出 。
8.类的成员之三:构造器(Constructor)
8.1 构造器的作用
new对象,并在new对象的时候为实例变量赋值。
示例:Person p = new Person(“Peter”,15) ;
8.2 构造器的语法格式
[修饰符] class 类名{
[修饰符] 构造器名(){
// 实例初始化代码
}
[修饰符] 构造器名(参数列表){
// 实例初始化代码
}
}
1.构造器名必须与它所在的类名必须相同。
2. 它没有返回值,所以不需要返回值类型,也不需要void。
3. 构造器的修饰符只能是权限修饰符,不能被其他任何修饰。比如,不能被static、final、 synchronized、abstract、native修饰,不能有return语句返回值。
示例:
public class Student {
private String name;
private int age;
// 无参构造
public Student() {}
// 有参构造
public Student(String n,int a) {
name = n;
age = a;
}
public String getName() {
return name;
}
public void setName(String n) {
name = n;
}
public int getAge() {
return age;
}
public void setAge(int a) {
age = a;
}
public String getInfo(){
return "姓名:" + name +",年龄:" + age;
}
}
public class TestStudent {
public static void main(String[] args) {
//调用无参构造创建学生对象
Student s1 = new Student();
//调用有参构造创建学生对象
Student s2 = new Student("张三",23);
System.out.println(s1.getInfo());
System.out.println(s2.getInfo());
}
}