一、方法
1、方法的定义
根据方法是否有返回值,将方法分为无返回值的方法和有返回值的方法
1)无返回值的方法,返回值类型写void
2)有返回值的方法,返回值类型写返回数据的类型
有返回值的方法,需要通过return关键字返回指定的数据类型
public class MethodDemo01 {
// 定义一个无返回值的方法
public void m1(){
System.out.println("m1()是一个无返回值的方法");
}// 定义一个返回int类型数据的方法m2()
// 定义有返回值需要用return关键字返回指定的数据类型
// 不写return则会报错
public int m2(){
int num = 300;
return num;
}// 定义一个返回String类型数组的方法
// 返回值可以是8大基本数据类型,也可以是3大引用数据类型
public String[] m3(){
String[] strs = {"qwert","asdfg"};
return strs;
}
}
public class MethodDemo01Test {
public static void main(String[] args) {
// 创建MethodDemo01对象
MethodDemo01 methodDemo01 = new MethodDemo01();
// 调用无返回值的方法m1
// 调用没有返回值的方法时,直接调用方法,不需要再做其他任何操作
methodDemo01.m1();// 调用有返回值的方法m2
// 方法返回什么类型的结果,就使用什么类型的变量接收返回值
int result1 =methodDemo01.m2();
System.out.println("result1 = "+result1);// 不使用变量接收方法返回值,直接将返回值输出
System.out.println(methodDemo01.m2());// 调用有返回值的方法m3
String[] strings =methodDemo01.m3();
System.out.println(Arrays.toString(strings));}
}
2、无参方法和有参方法
根据方法是否有参数来分类:
1)无参方法:没有参数的方法
2)有参方法:有参数的方法,参数可以是一个或者多个,可以是相同类型的也可以是不同类型的
所以方法最终的表现形式有四种:
1)无返回值的无参方法
2)无返回值的有参方法
3)有返回值的无参方法
4)有返回值的有参方法
方法调用原则:
1)给什么接什么:方法返回什么类型的值,要么直接输出返回值,要么拿对应类型的变量接收返回值
2)要什么给什么:方法需要什么样的参数,按照参数列表的要求传递参数
public class MethodDemo02 {
// 定义一个无参方法 无返回值
public void m1(){
System.out.println("没有参数的方法m1()");
}// 定义一个需要传递一个int类型数据的方法 有参 无返回值
// num是一个形式参数,简称形参
public void m2(int num){
System.out.println("你传递过来的值:"+num);
}// 定义一个需要传递两个int类型数据的方法 有参 无返回值
public void m3(int num1,int num2){
System.out.println("你传递过来的两个数据之和:"+(num1+num2));
}// 定义一个需要传递一个int类型数据和一个double类型数据的方法
public void m4(int num1,double num2){
System.out.println("你传递过来的两个数据是:"+num1+","+num2);
}// 定义一个方法,需要传递一个int类型的数组,然后将传递过来的数组元素进行求和,将结果和返回 有参 有返回值
public int arraySum(int[] nums){
// 声明一个变量sum用来累加数组之和
int sum = 0;
// 通过循环进行累加
for(int i =0;i<nums.length;i++){
sum+=nums[i];
}
return sum;
}
}
public class MethodDemo02Test {
public static void main(String[] args) {
// 创建MethodDemo02类对象
MethodDemo02 methodDemo02 = new MethodDemo02();// 调用无参方法:不需要传递参数
methodDemo02.m1();// 调用有参方法,传递一个int类型数据
methodDemo02.m2(200); // 调用方法时传递的实际参数是200,简称实参
int a =300; // 定义一个变量并赋值
methodDemo02.m2(a); // 调用方法时传递的实际参数是a,简称实参
// methodDemo02.m2(199.99); m2方法需要的是int类型的,你传递的是double类型的数据,不符合参数列表要求// 调用有参方法,传递两个int类型数据
methodDemo02.m3(100,200);// 调用有参方法,传递一个int类型数据和一个double类型数据
methodDemo02.m4(100,99.99);
//methodDemo02.m4(99.99,100); // 调用有参方法时需要根据参数的类型、个数、顺序传递参数// 总结:调用有参方法时,必须按照方法参数列表的数据类型、个数、顺序要求传递参数
// 定义一个int类型数组
int[] array1 = {11,22,33};
int result1 = methodDemo02.arraySum(array1);
System.out.println("array1数组元素之和:"+result1);int[] array2 = {11,33,44,55,66};
System.out.println(methodDemo02.arraySum(array2));}
}
无return即无参方法,在main方法中不能用相应的数据类型接收
3、方法的调用
方法的三种调用方式:
1)通过对象调用方法:在其他类中调用非静态方法
2)通过类名直接调用方法:要求方法使用static修饰,直接通过类名.方法名()
3)在同一个类中,方法之间可以直接调用,无需创建对象或者通过类名调用
非静态方法(没有使用static修饰的方法)既可以调用非静态方法,也可以调用静态方法
静态方法只能调用静态方法
public class MethodDemo03 {
public void m1(){
System.out.println("无返回值的无参方法m1()");
}public void m2(){
System.out.println("无返回值的无参方法m2()");
m1();
m3(); // 非静态方法中既可以调用非静态方法,也可以调用静态方法
}public static void m3(){
System.out.println("使用static修饰的无参回值的无参方法m3()");
}public static void m4(){
System.out.println("使用static修饰的无参回值的无参方法m4()");
m3();
// m1(); 静态方法中只能调用同一个类的静态方法,不能调用非静态方法
}
}
public class MethodDemo03Test {
public static void main(String[] args) {
// 调用方法的方式一:通过对象调用方法
MethodDemo03 methodDemo03 = new MethodDemo03();
methodDemo03.m1();// 调用方法的方式二:通过类名调用方法
// 使用static修饰的方法也可以通过对象名调用
methodDemo03.m3(); // 输出结果 使用static修饰的无参回值的无参方法m3()
// 类名调用方法
MethodDemo03.m3(); // 输出结果 使用static修饰的无参回值的无参方法m3()System.out.println("--------------------");
methodDemo03.m2();
// 输出结果
// 无返回值的无参方法m2()
// 无返回值的无参方法m1()
// 使用static修饰的无参回值的无参方法m3()System.out.println("--------------------");
MethodDemo03.m4(); // 使用类名调用方法
// 输出结果
// 使用static修饰的无参回值的无参方法m4()
// 使用static修饰的无参回值的无参方法m3()}
}
对象调用方法可以是静态方法或非静态方法
使用类名调用方法只能是静态方法,使用static
方法之间的相互调用是在类中,静态方法只能调用静态方法
4、创建工具类方法
public class MyArrays {
// 定义操作数组的静态方法,用来操作数组中的元素
// 定义一个静态方法实现遍历数组
public static void printArrayData(int[] array) { // static修饰的作用 不用也可以// 遍历数组
for (int i = 0; i < array.length; i++) {
if (i == 0) {
System.out.print("[");
}
if (i < array.length) {
System.out.print(array[i]);
}
if (i < array.length-1) {
System.out.print(",");
}
if (i == array.length-1) {
System.out.print("]");
}
}
}// 定义获取int类型数组最大值的方法
// 定义将int类型数组进行升序排序的方法
//...........
}
五、练习题
1、景区门票
根据年龄段决定能够购买门票价格并进行输出
public class Ticket {
public static void ticket(String name,int age) {
// 根据不同年龄收取不同价位门票:12周岁及65周岁以上免门票,其余的收取门票20元
if (age <= 12 || age >= 65) {
System.out.println(name+"的年龄为:"+age+",门票免费");
}else {
System.out.println(name+"的年龄为:"+age+",门票20元");
}}
}
public class TicketTest {
public static void main(String[] args) {Scanner scanner = new Scanner(System.in);
// 获取一次姓名和年龄
System.out.println("请输入姓名:");
String name = scanner.next();// name = "n"时,equals输出true,取反为false,停止while循环
while(!name.equals("n")) {
System.out.println("请输入年龄:");
int age = scanner.nextInt();// 类名调用方法
Ticket.ticket(name,age);System.out.println("请输入姓名:");
name = scanner.next();}
System.out.println("程序退出");
}
}
2、用户密码
模拟实现用户密码管理:输入旧的用户名和密码,如果正确,从键盘获取新的密码,方有权限更新
public class AccountUtils {
// 定义一个静态方法实现修改密码 (形参 用户名,密码)
public static void changePwd(String name,String password) {
Scanner scanner = new Scanner(System.in);
// 设置原用户名和密码
String beforeName = "admin";
String beforePwd = "123456";// 输入的原用户名和原密码与存储的原用户名和原密码相同,才能进行修改密码操作
// 比较字符串用equals不然就会报错 比较数据类型用==就可以 ??????
if(name.equals(beforeName) && password.equals(beforePwd)) {
System.out.println("请输入新密码:");
beforePwd=scanner.next();
System.out.println("密码修改成功,新密码为:"+beforePwd);
}else{
System.out.println("用户名或者密码不正确,您没有权限修改管理员密码");
}
}
}
public class AccountTest {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 在类和对象中了解用户输入的思想,键盘输入,传参到创建的方法中
System.out.println("请输入原用户名:");
String name = scanner.next();
System.out.println("请输入原密码:");
String pwd = scanner.next();// 通过工具类AccountUtils调用方法实现修改密码操作
AccountUtils.changePwd(name,pwd);}
}
二、方法重载
一、方法的参数传递
1、定义带参数的方法
<访问修饰符> 返回类型 <方法名>(形参列表) {
// 方法的主体
}
2、调用带参数的方法
对象名.方法名(参数1,参数2,......参数n,实参列表)
3、带参方法实现案例
在保存了多个学生姓名的数组中,指定查找区间,查找某个学生姓名并显示是否查找成功
public class StudentUtils {
// 在保存了多个学生姓名的数组中,指定查找区间,查找某个学生姓名并显示是否查找成功
// 返回值类型为布尔值
public static boolean searchStudent(String[] studentNames,int begin,int end,String name){
// 首先判断你输入的索引是否处于数组的索引范围之内
if(begin<0 || end>studentNames.length-1){
// 否则返回false
return false;
}// 使用循环的方式将你要查找的姓名在数组一一进行比较,如果数组有元素与查找姓名相同,就返回true
for(int i =begin;i < end;i++){
if(name.equals(studentNames[i])){
return true;
}
}return false;
}
}
public class StudentTest {
public static void main(String[] args) {// 首先准备一个student姓名的数组
String[] names = {"张三","李四","王五","赵六","孙七","吴八","周九"};// 查询names数组中下标2-5这个区间内是否有张三
boolean result =StudentUtils.searchStudent(names,2,5,"赵六");
System.out.println("我要查找的姓名在指定区间是存在的:"+result);}
}
4、方法传参
基本数据类型,操作传递的是变量的值,改变一个变量的值不会影响另一个变量的值
引用数据类型(类、数组、接口),赋值是把原对象的引用(内存地址)传递给另一个引用
public class Student {
//定义两个属性
public String name;
public int age;}
public class Test {
// 定义2个方法
public void calc1(int num){
// n = 8 值传给了 num
num=num+1;
System.out.println("num:"+num); // num = 9
}
// 传一个对象 对象是一个容器 容器里面包含很多属性
public void calc2(Student student){
student.age=student.age+1;
System.out.println("stuage:"+student.age); // stuage:19
}
public static void main(String[] args) {
// 测试类
Test test=new Test();
int n=8;
test.calc1(n);
System.out.println("n="+n); // n = 8// 创建Student对象,并给age属性赋值
Student stu=new Student();
stu.age=18;
System.out.println("student.age="+stu.age); // student.age=18
test.calc2(stu); // 传Student创建的对象stu
System.out.println("student.age="+stu.age); // student.age=19
}}
5、对象数组
即创建的对象放在同一个数组中
// 定义一个Dog类,类也是一种数据类型,是我们自己定义的数据类型
public class Dog {
// 定义属性
public String name;
public int age;
public char gender;// 定义方法
public void eat(){
System.out.println("狗吃肉......");
}public void shout(){
System.out.println("汪汪汪......");
}
}
public class DogTest {
public static void main(String[] args) {
// 创建3个Dog类对象
// 对象也可以理解为一个容器,这个容器中可以存储多个不同类型的数据(即对象的属性)
// 至于这个对象能够存储多少个数据取决于对象的类里定义了多少个属性
Dog dog1 = new Dog();
// 给属性赋值
dog1.name = "奥迪";
dog1.age = 2;
dog1.gender = '公';Dog dog2 = new Dog();
// 给属性赋值
dog2.name = "宝马";
dog2.age = 2;
dog2.gender = '母';Dog dog3 = new Dog();
// 给属性赋值
dog3.name = "奔驰";
dog3.age = 2;
dog3.gender = '公';// 将这个三个dog对象存储到数组中
// 数据类型[] 数组名 = new 数据类型[数组长度];
// 数据类型[] 数组名 = new 数据类型[]{数据1,数据2,...,数据n};
// 数据类型[] 数组名 = {数据1,数据2,...,数据n};
Dog[] dogs = {dog1,dog2,dog3}; //// 取出数组中第一个元素,数组中的元素是dog对象,直接输出对象,输出的是地址值
System.out.println(dogs[0]);
// 可以输出取出来的对象的属性值
System.out.println(dogs[0].name);
System.out.println(dogs[0].age);
System.out.println(dogs[0].gender);System.out.println("--------------------");
// 遍历dogs数组,输出数组中所有dog对象的所有属性值
for(int i =0;i< dogs.length;i++){
System.out.println(dogs[i].name);
System.out.println(dogs[i].age);
System.out.println(dogs[i].gender);
System.out.println("--------------------");
}
}
}
二、构造方法
无参构造方法,每个类都有个默认无参构造方法
Student student = new Student();
带参构造方法
Student stu = new Student("张三",40);
带参的构造方法在创建对象时就可以赋值,而不用对象名.属性再次赋值,节省代码
构造方法的特点
1)构造方法没有返回值,void也不写
2)构造方法的名称与类名相同
3)当你在类中添加了其它的构造方法,会覆盖类中默认添加的无参构造方法,如果你还需要使用无参构造方法,就需要手动添加一个
public class Animal {
// 定义属性
public String type;
public String name;
public int age;
public char gender;
public double height;
public double weight;
public String color;
// 每定义一个类,系统默认给这个类添加一个无参构造方法,并且隐藏不显示/*
构造方法:
访问修饰符 类名([形参列表]){}
* 构造方法的特点:
* 1)构造方法没有返回值,void也不写
* 2)构造方法的名称与类名相同
* 3)当你在类中添加了其它的构造方法,会覆盖类中默认添加的无参构造方法,如果你还需要使用无参构造方法,就需要手动添加一个
* */
// 定义一个无参构造方法
public Animal(){}
// 定义有参构造方法
// 这个有参构造方法中的形参没有做到见名知意,在调用的时候,无法通过参数名称知道参数代表的含义
/*
public Animal(String a,String b,int c,char d,double e,double f,String g){
type =a;
name=b;
age=c;
gender=d;
height=e;
weight=f;
color=g;
}
*/public Animal(String type,String name,int age,char gender,double height,double weight,String color){
// 当你调用有参构造方法传递参数时,参数的值应该传递给创建的对象的属性
// 但是这里形参名称和属性形成一致,方法里面会将形参的值再次传递给了形参,没有传递到创建的对象的属性中
/*
type =type;
name=name;
age=age;
gender=gender;
height=height;
weight=weight;
color=color;
*/
// 在这里使用this关键字表示你创建的对象,谁调用该构造方法,this就表示谁
this.type =type;
this.name=name;
this.age=age;
this.gender=gender;
this.height=height;
this.weight=weight;
this.color=color;
}// 定义一个方法实现输出对象的属性信息
public void printInfo(){
System.out.println(type+"-"+name+"-"+age+"-"+gender+"-"+height+"-"+weight+"-"+color);
}}
public class AnimalTest {
public static void main(String[] args) {
// 创建Animal对象
// 类名 对象名 = new 类名();--->使用无参构造方法创建对象
Animal animal1 = new Animal();
// 给对象属性赋值
animal1.type = "狗";
animal1.name = "旺财";
animal1.age = 3;
animal1.gender = '公';
animal1.height = 90;
animal1.weight = 85.5;
animal1.color = "黄色";
animal1.printInfo();// 通过有参构造方法创建Animal类对象--->你看看多省事
Animal animal2 = new Animal("猫","Tom",2,'母',25.2,8.3,"白色");
animal2.printInfo();Animal animal3 = new Animal("猪","香猪",3,'公',21.2,6.5,"黑白色");
animal3.printInfo();
}
}
三、this关键字
public class Worker {
// 定义属性
public String name;
public int age;
public char gender;
public double height;
public double weight;
public String phone;
public String address;
public double salary;// 添加一个无参构造方法
public Worker() {
System.out.println("Worker类里的无参构造方法");
}public Worker(String name, int age, char gender) {
this.name = name;
this.age = age;
this.gender = gender;
}public Worker(String name, int age, char gender, double height, double weight, String phone, String address, double salary) {
this(); // 在一个构造方法中通过this去调用其它构造方法,调用代码必须写在构造方法的第一行
this.name = name;
this.age = age;
this.gender = gender;
this.height = height;
this.weight = weight;
this.phone = phone;
this.address = address;
this.salary = salary;
// this(); 写在这里就会报错
}// 定义一个方法输出对象的属性信息
public void printInfo(){
System.out.println("姓名:"+this.name+",年龄:"+this.age);
}// 定义方法
public void m1(){
System.out.println("m1()方法");
}public void m2(){
System.out.println("m2()方法");
this.m1();
}
}
public class WorkerTest {
public static void main(String[] args) {
Worker worker1 = new Worker();
Worker worker2 = new Worker("张三",28,'男',178,78,"13612345678","安徽合肥",8200);
}
}
思考:
在方法中定义的形参个数,创建对象时,是否传入的实参应与形参数量、顺序一致,如下进行测试:
public class Test {
public String name;
public int age;
public char gender;
public double height;
public double weight;
// 无参构造方法
public Test() {}
// 有参构造方法 三个参数
public Test(String name, int age, char gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
// 有参构造方法 五个参数 方法重载
public Test(String name, int age, char gender, double height, double weight) {
this.name = name;
this.age = age;
this.gender = gender;
this.height = height;
this.weight = weight;
}public void info1(int a,int b,int c) {
System.out.println("这里有三个形参"); // 不使用形参
}
// info1普通方法重载
public void info1(int a,int b) {
System.out.println("这里有两个形参"+a+","+b); // 输出
}public void info2(int a,int b) {
int c = a + b;
System.out.println("这里有两个形参"+a+","+b);
System.out.println("和为:"+c);
}
}
public class TestTest {
public static void main(String[] args) {Test test1 = new Test();
Test test2 = new Test("sqs",12,'b');
// test1.Test("sas",12,'男'); 报错,无法用对象.方法名调用
// 构造方法在创建对象时使用,完成传参,实参数量、顺序要与构造方法中的形参一致
// 调用普通方法info1 传入的实参数量、顺序应与形参一致
test1.info1(1,2,3);
// 输出结果 这里有三个形参
test1.info1(1,2);
// 输出结果 这里有两个形参1,2
System.out.println("------");
// 调用普通方法info2
test1.info2(1,2);
// 输出结果 这里有两个形参1,2,和为:3}
}
所以无论是在构造方法还是普通方法,实参数量、顺序应与形参保持一致
并且需要使用有参的构造方法,当创建对象时,就可以直接将参数传递进去,数量、顺序需保持一致
如果需要增加或减少参数,可以对方法进行重载
四、方法重载
1、自定义构造方法(在同一个类中)
1)方法名相同
2)参数列表不同
3)与返回值、访问修饰符无关
2、此时系统不再提供默认无参构造方法
3、普通方法也可以重载
五、成员变量和局部变量
变量的作用范围由花括号{ }来决定
变量声明的位置决定变量作用域
变量作用域确定可在程序中按变量名访问该变量的区域
区别
1、作用域不同
1)成员变量的作用域在整个类内部都是可见的
2)局部变量的作用域仅限于定义它的方法
2、初始值不同
1)Java会给成员变量一个初始值
2)Java不会给局部变量赋予初始值
3、注意
1)在同一个方法中,不允许有同名局部变量
2)在不同的方法中,可以有同名局部变量
3)在同一个类中,成员变量和局部变量同名时,局部变量具有更高的优先级
例:
public class Demo01 {
// 成员变量(全局变量):在类中、在方法外,声明的变量
int num1 = 100;
// int num1 = 200; 在同一个类中,不能有同名的成员变量
static int num2 = 200; // 声明静态的变量num2public void m1(){
System.out.println("num1="+num1);
System.out.println("num2="+num2);
}public void m2(){
// 局部变量:在方法中或者其他结构中声明的变量,其作用范围就是方法内或者某个结构内
int num4 =400;
// int num4 = 300; 在同一个方法或者结构中,不能有同名的局部变量
System.out.println("num4:"+num4);
int num1 = 2000;
// 成员变量和局部变量可以同名
System.out.println("num1:"+num1);
}public void m3(){
// 在不同的方法或者结构内,可以有同名的局部变量
int num4 = 500;
System.out.println("num4:"+num4);
}public static void main(String[] args){
// System.out.println("num1:"+num1); // 静态方法中只能访问静态的成员变量,不能访问非静态的成员变量
System.out.println("num2:"+num2);int num3 = 300;
for(int i =1;i<=5;i++){
System.out.println("num3:"+num3);
}for(int j =1;j<=3;j++){ // j是局部变量
System.out.println(j);
}// System.out.println(j); j是在for循环中声明的,它的作用范围仅限于for循环
}
}
public class Demo02 {
// 声明一个全局变量
int num1 =100;
// 全局变量可以不赋值,因为全局变量有默认值
int num2;public void m1(){
// 成员变量和局部变量可以同名,但是局部变量具有更高的优先级
// int num1 = 200;
// 局部变量没有默认的初始值,在使用前必须赋值
int num3;
System.out.println("num1="+num1);
System.out.println("num2:"+num2);
num3 = 300;
System.out.println("num3:"+num3);
}public static void main(String[] args) {
// 创建Demo02类对象
Demo02 demo02 = new Demo02();// 调用m1()方法
demo02.m1();
}
}