类的属性(成员方法)
成员变量是用来存储对象的数据信息的,那么如何表示对象的行为功能呢?就要通过方法来实现
方法的概念
方法也叫函数,是一个独立功能的定义,是一个类中最基本的功能单元。把一个功能封装为方法的目的是,可以实现代码重用,从而简少代码量。
方法的原则
- 必须先声明后使用。类,变量,方法等都要先声明后使用
- 不调用不执行,调用一次执行一次。
成员方法分为两类
- 实例方法:没有static修饰的方法,必须通过实例对象来调用。
package demo01;
//声明一个圆的图形类,
//Circle不同的对象,半径值不同,那么面积也不同,所以这里area()是非静态的
public class Circle {
// 属性(成员变量):半径,
double radius;
// 成员方法:求面积的方法,返回圆对象信息的方法
double area() {
return Math.PI * radius * radius;
}
}
- 静态方法:有static修饰的方法,也叫类方法,可以由类名来调用。
/*
CountTools只是一个工具类,求两个整数最大值的功能,和CountTools对象无关,
所以这里max方法声明为静态的更好,当然也可以声明为非静态的,
就是调用的时候需要创建CountTools对象而已。
*/
class CountTools {//声明一个计算工具类CountTools:
//求两个整数的最大值
static int max(int a, int b) {
return a > b ? a : b;
}
}
如何声明方法
方法声明的位置必须在类中方法外,声明位置示例:
语法格式
格式详解:
- 修饰符: 修饰符后面一一介绍,例如:public,static等都是修饰符
- 返回值类型: 表示方法运行的结果的数据类型,方法执行后将结果返回到调用者。可以写的数据类型可以是丶基本数据类型丶引用数据类型。如果不需要返回数据给调用者可以使用void来修饰。
- 方法名:给方法起一个名字,见名知意,能准确代表该方法功能的名字
- 参数列表:方法内部需要用到其他方法中的数据,需要通过参数传递的形式将数据传递过来,可以是基本数据类型、引用数据类型、也可以没有参数,什么都不写
- 方法体:特定功能代码
- return:结束方法,并将方法的结果返回去。如果返回值类型不是void,方法体中必须保证一定有return 返回值;语句,并且要求该返回值结果的类型与声明的返回值类型一致或兼容。如果返回值类型为void时,return 后面不用跟返回值,甚至也可以没有return语句。return语句后面就不能再写其他代码了,否则会报错:Unreachable code
调用时,如果方法有返回值,可以接受或处理返回值结果,当然也可以不接收,那么此时返回值就丢失了。如果方法的返回值类型是void,不需要也不能接收和处理返回值结果。
如何在其他类中调用方法
实例方法
代码示例
class Circle{
double radius;
public double area() {
return Math.PI * radius * radius;
}
}
public class TestCircle {
public static void main(String[] args) {
//创建对象
Circle c1 = new Circle();
//给成员变量赋值
c1.radius = 1.2;
System.out.println("c1的面积:" + c1.area());
//非静态方法只能通过"对象."进行访问
// System.out.println("c1的面积:" + Circle.area());错误
Circle c2 = new Circle();
c2.radius = 2.5;
System.out.println("c2的面积:" + c2.area());
}
}
类方法
代码示例
class CountTools{
static int max(int a, int b) {
return a > b ? a : b;
}
}
public class TestCount {
public static void main(String[] args) {
//类名.类方法(【实参列表】)分数调用,推荐
System.out.println(CountTools.max(4, 1));//4
//静态方法也可以通过“对象.”访问,不推荐
CountTools c = new CountTools();
System.out.println(c.max(2, 5));//5
}
}
在本类中访问本类的成员变量和成员方法
直接用,不需要加“对象名."和"类名." 。唯一例外:静态方法中不能直接访问本类的非静态的成员变量和成员方法
class Test{
static void test(){
System.out.println("");
}
void method(){
test();
}
public static void main(String[] args){
method();//错误
test();//正确
}
}
需求:设计一个方法可以获取两个int数的较大值,数据来自于参数
package demo01;
/*
1.方法的概念:
就是将具有独立功能的代码块组织成为一个整体,使其具有特殊功能的代码集。
将具有特殊功能的一段代码,使用大括号{}括起来,添加必要的修饰符,起个名字, 方便使用
2.方法的格式:
修饰符 返回值类型 方法名称(数据类型1 变量名称1,数据类型2 变量名称2...) {
功能代码;
return 返回值;//如果return 后面 有具体的结果数据,不能省略return
}
注意:
(1)方法没有参数,不用写参数列表,但是必须保留小括号()
(2)方法内部没有返回值返还给调用者,返回值类型必须固定写为void
3.格式解释:
(1)修饰符: public static 目前固定写法,先记住
(2)返回值类型: 告诉方法的调用者,我方法结束后,给你一个什么类型的数据
方法的功能代码执行完毕后,产生的需要返还给方法的调用者的结果数据的具体类型
举例:
如果方法内部返回整数数字100,返回值类型写为int
如果方法内部返回小数数字6.6,返回值类型写为double
如果方法内部返回true/false,返回值类型写为boolean
(3)方法名称:
给方法起个名字(符合标识符的命名规范,小驼峰原则(第一个单词首字母小写,其它单词首字母大写)),方便使用
(4)参数列表: 你调用我这个方法时,需要给我几个什么样子的数据
就是在定义方法时,小括号()中定义了一个/多个变量
定义方法参数列表举例:
(int a): 调用方法时,必须传递给方法一个int类型的数据
(int a,int b): 调用方法时,必须传递给方法两个int类型的数据
(double a,double b): 调用方法时,必须传递给方法两个double类型的数据
(5)功能代码: 完成特殊功能的一行/多行代码
(6)return 返回值/结果数据;:
a.结束方法
b.把return 后面的返回值/结果数据,返还到方法的调用处
5.定义方法的三要素
(1)方法名称:
(2)参数列表:
(3)返回值类型:
6.注意:
方法定义完毕后不调用不执行
方法可以调用任意多次
*/
public class Demo03Method {
public static void main(String[] args) {
System.out.println("main...start...");
//调用方法: 传递的是常量
int result = getMax(100, 200);
System.out.println("100和200的最大值: " + result);//100和200的最大值: 200
//调用方法方法: 传递变量
int a = 10, b = 20;
int max = getMax(a, b);
System.out.println(a + "和" + b + "的最大值: " + max);//10和20的最大值: 20
System.out.println("main...end...");
}
//设计一个方法可以获取两个int数的较大值,数据来自于参数
/*
你调用我的方法getMax时,必须给我传递两个int类型的数据,
我getMax方法内部执行完毕后,会返还给你一个int类型的数据
你: 方法的调用者
我: 方法本身
有进(参数)有出(返回值)
*/
//int: 告诉方法的调用者,方法功能代码执行完毕后,会返回数据的具体类型(会返回一个什么样子的数据)
public static int getMax(int a, int b) {
int max = (a > b) ? a : b;
return max;//结束方法,并且把max中的数据,返还给方法的调用处/者
}
}
图解分析:
形式参数和实际参数的区别
- 形参:在定义方法时方法名后面括号中声明的变量称为形式参数(简称形参)即形参出现在方法定义时。
- 实参:调用方法时方法名后面括号中的使用的值/变量/表达式称为实际参数(简称实参)即实参出现在方法调用时。
调用时,需要传“实参”,实参的个数、类型、顺序顺序要与形参列表一一对应如果方法没有形参,就不需要也不能传实参。
代码示例
package demo01;
/*
形式参数和实际参数的区别
1.形式参数:
(1)概念: 定义方法时()中定义的参数(定义变量),叫做形式参数
(2)特点:
a.定义形式参数的时候,是没有值的
b.当调用该方法时,形式参数才会有值
2.实际参数:
(1)概念: 调用方法时()中给出的参数(常量/变量),叫做实际参数
(2)特点:
a.调用方法时,()中写的数据(常量/变量)
b.必须要有值才可以
*/
public class ParamDiff {
public static void main(String[] args) {
System.out.println("main...start...");
/*
2.实际参数:
(1)概念: 调用方法时()中给出的参数(常量/变量),叫做实际参数
(2)特点:
a.调用方法时,()中写的数据(常量/变量)
b.必须要有值才可以
*/
//调用方法: 传递常量
printSum(10, 20);//10,20叫做实际参数
//调用方法: 传递变量
int m = 100, n = 200;
printSum(m, n);//m,n叫做实际参数
System.out.println("main...end...");
}
/*
1.形式参数:
(1)概念: 定义方法时()中定义的参数(定义变量),叫做形式参数
(2)特点:
a.定义形式参数的时候,是没有值的
b.当调用该方法时,形式参数才会有值
*/
//定义方法,打印2个int数字之和
public static void printSum(int a, int b) {
int sum = a + b;
System.out.println("和: " + sum);
return;//结束方法,返回到方法的调用处,注意没有带回任何数据
}
}
图解形参和实参
方法调用内存分析
方法不调用不执行,调用一次执行一次,每次调用会在栈中有一个入栈动作,即给当前方法开辟一块独立的内存区域,用于存储当前方法的局部变量的值,当方法执行结束后,会释放该内存,称为出栈,如果方法有返回值,就会把结果返回调用处,如果没有返回值,就直接结束,回到调用处继续执行下一条指令。
方法的参数传递机制
基本类型作为方法参数传递
public class Test1 {
/*
方法参数传递为基本数据类型 :
传入方法中的, 是具体的数值.
*/
public static void main(String[] args) {
int number = 100;
System.out.println("调用change方法前:" + number);
change(number);
System.out.println("调用change方法后:" + number);
}
public static void change(int number) {
number = 200;
}
}
结论:
- 基本数据类型的参数,形式参数的改变,不影响实际参数
结论依据:
- 每个方法在栈内存中,都会有独立的栈空间,方法运行结束后就会弹栈消失
方法参数传递引用类型
public class Test2 {
/*
方法参数传递为引用数据类型 :
传入方法中的, 是内存地址.
*/
public static void main(String[] args) {
int[] arr = {10, 20, 30};
System.out.println("调用change方法前:" + arr[1]);
change(arr);
System.out.println("调用change方法后:" + arr[1]);
}
public static void change(int[] arr) {
arr[1] = 200;
}
}
结论:
- 对于引用类型的参数,形式参数的改变,影响实际参数的值
结论依据:
- 引用数据类型的传参,传入的是地址值,内存中会造成两个引用指向同一个内存的效果,所以即使方法弹栈,堆内存中的数据也已经是改变后的结果
方法重载
方法重载:指在同一个类中,允许存在一个以上的同名方法,只要它们的参数列表不同即可,与修饰符和返回值类型无关。
参数列表不同表现:
- 数据类型个数不同
- 数据类型不同
- 数据类型顺序不同
重载方法调用:JVM通过方法的参数列表,调用不同的方法。
代码示例
package demo01;
//使用方法重载的思想,设计比较两个数据是否相等的方法,兼容全整数类型(byte,short,int,long)
public class Demo04 {
public static void main(String[] args) {
//5.分别调用以上四个方法
System.out.println(compare(10, 20));
System.out.println(compare((byte) 10, (byte) 20));
System.out.println(compare((short) 10, (short) 20));
System.out.println(compare(10L, 20L));
}
// 两个byte类型的
public static boolean compare(byte a, byte b) {
System.out.println("byte");
return a == b;
}
// 两个short类型的
public static boolean compare(short a, short b) {
System.out.println("short");
return a == b;
}
// 两个int类型的
public static boolean compare(int a, int b) {
System.out.println("int");
return a == b;
}
// 两个long类型的
public static boolean compare(long a, long b) {
System.out.println("long");
return a == b;
}
}