一、方法递归调用
-
基本介绍:递归就是方法自己调用自己,每次调用时传入不同的变量,
例子:
public void test(int n){ if(n > 2){ test(n-1); } System.out.println("n=" + n); }
-
递归重要规则
- 执行一个方法的时候,就创建一个新的受保护的独立空间(栈空间)
- 方法的局部变量是独立的,不会互相影响
- 如果方法中使用的是引用类型变量(比如数组,对象),就会共享该引用类型的数据
- 递归必须向退出递归的条件逼近,否则就会出现无限递归
- 当一个方法执行完毕,或者遇到 return ,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕
二、方法重载(OverLoad)
- 基本介绍:java中允许同一个类中,多个同名方法的存在,但是要求形参列表不一致!!!
- 重载的好处:
- 减轻了起名的麻烦
- 减轻了记名的麻烦
- 注意事项和细节
- 方法名:必须相同
- 形参列表:必须不同(形参类型或个数或顺序,至少有一样不同,参数名无要求)
- 返回类型:无要求
三、可变参数
-
基本概念
java允许将同一个类中多个同名同功能,但是参数个数不同的方法,封装成一个方法。就可以通过可变参数来实现
-
基本语法
访问修饰符 返回类型 方法名(数据类型…形参名){
}
-
例子(可以计算2个数的和,3个数的和,4个数的和…)
punlic class VarParameter01{ public static void main(String[] args){ HspMethod m = new HspMethod(); System.out.println(m.sum(1, 5, 100)); } } class HspMethod{ public int sum(int n1, int n2){//2个数的和 return n1 + n2; } public int sum(int n1, int n2, int n3){//3个数的和 return n1 + n2 + n3; } public int sum(int n1, int n2, int n3, int n4){//4个数的和 return n1 + n2 + n3 + n4; } //上面的三个方法名称相同,功能相同,参数个数不同—>可使用可变参数优化。 //解读 //1.int... 表示接收的是可变参数,类型是int,即可以接收多个(0~多)int //2.使用可变参数的时候,可以当作数组来使用,即 nums 可以当作数组 //3.遍历 nums 求和即可 public int sum(int... nums){ int res = 0; for(int i = 0; i < nums.length; i++){ res += nums[i]; } return res; } } }
-
注意事项和使用细节
- 可变参数的实参可以为0个或者任意多个
- 可变参数的实参为数组
- 可变参数的本质就是数组
- 可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后
- 一个形参列表中只能出现一个可变参数
四、作用域
-
基本使用
-
在Java编程中,主要的变量就是属性(成员变量)和局部变量
-
所谓的局部变量一般是值在成员方法中定义的变量
-
Java中作用域的分类:
全局变量:也就是属性,作用域为整个类体
局部变量:也就是除了属性之外的其他变量,作用域为定义它的代码块中。
-
全局变量可以不赋值,直接使用,因为有默认值。局部变量必须赋值后才能使用,因为没有默认值。
punlic class VarScope{ public static void main(String[] args){ } } class Cat{ //1.全局变量:也就是属性,作用域为整个类体 Cat类:cry eat 等方法使用属性 //属性在定义时,可以直接赋值 int age = 10;//指定的值是 10 public void cry(){ //1.局部变量一般是值在成员方法中定义的变量 //2.n 和 name 就是局部变量 //3.n 和 name 的作用域在cry方法中 int n = 10; String name = "jack"; System.out.println("在cry中使用属性 age=" + age); } public void eat(){ System.out.println("在eat中使用属性age=" + age); System.out.println("在eat中使用 cry的变量name" + name);//错误 } }
-
-
注意事项和细节
-
属性和局部变量可以重名,访问时遵循就近原则
-
在同一个作用域中,比如在同一个成员方法中,两个局部变量,不能重名
-
属性生命周期较长,伴随着对象的创建而创建,伴随着对象的销毁而销毁。
-
局部变量的生命周期较短,伴随着所在代码块的执行而创建,伴随着代码块的结束而销毁 ,即在一次方法调用过程中。
-
作用域的范围不同:全局变量/属性—>可以被本类使用,或者其他类使用(通过对象调用)
局部变量—>只能在本类中对应的方法中使用
-
修饰符不同:全局变量/属性—>可以加修饰符
局部变量—>不可以加修饰符
-
五、构造方法/构造器
-
介绍
是类的一种特殊的方法,主要作用是完成对新对象的初始化。
-
基本语法
[修饰符] 方法名(形参列表){
方法名
}
-
说明
- 构造器的修饰符可以是默认,也可以是public,protected,private
- 构造器没有返回值
- 方法名和类名必须一样
- 参数列表 和 成员方法 一样的规则
- 构造器的调用有系统完成
- 在创建对象的时候,系统会自动的调用该类的构造器完成对 对象的初始化
punlic class VarScope{
public static void main(String[] args){
Person p1 = new Person("smith", 80);
System.out.println("p1的信息如下");
System.out.println("p1对象name=" + p1.name);
System.out.println("p1对象age=" + p1.age);
}
}
class Person{
String name;
int age;
//构造器
//解读
//1.构造器没有返回值,也不能写void
//2.构造器的名称要和类 Person 一样
//3.(String pName, int pAge) 是构造器的形参列表,规则和成员方法一样
public Person(String pName, int pAge){
System.out.println("构造器被调用~~,完成对象的属性初始化")
name = pName;
age = pAge;
}
}
结果:
-
注意事项和使用细节
-
一个类可以定义多个不同的构造器,即构造器重载
比如:我们在给Person类定义袷构造器,用来创建对象的时候,只指定人名,不需要指定年龄。
punlic class ConstructorDetail{ public static void main(String[] args){ Person p1 = new Person("smith", 80);//第一个构造器,输出 smith,80 Person p1 = new Person("smith");//第二个构造器,输出Smith,0 } } class Person{ String name; int age; // 默认0 //第一个构造器 public Person(String pName, int pAge){ System.out.println("第一个构造器被调用~~,完成对象的属性初始化") name = pName; age = pAge; } //第二个构造器,只指定人名,不需要指定年龄 public Person(String pName){ System.out.println("第二个构造器被调用~~,完成对象的属性初始化") name = pName; } }
-
构造器名和类名要相同
-
构造器没有返回值
-
构造器是完成对象的初始化,并不是创建对象
-
在创建对象时,系统自动的调用该类的构造方法
-
如果程序员没有定义构造器,系统会自动给类生成一个默认无参构造器(也叫默认构造器)
//默认构造器(无参构造器) 类名(){ //空的 }
-
一旦构造了自己构造器,默认的构造器就覆盖了,就不能再使用默认的无参构造器,除非显式的定义一下。
punlic class ConstructorDetail{ public static void main(String[] args){ Dog dog1 = new Dog();//使用的是默认的无参构造器 } } class Dog{ //自己定义的构造器 public Dog(String name){ } //显示的定义无参构造器 Dog(){ } }
-
六、对象创建流程
-
流程:
- 加载Person类信息(Person.class),只会加载一次
- 在堆中分配空间(地址)
- 完成对象初始化
- 默认初始化, age = 0 name = null
- 显式初始化 age = 90 name = null
- 构造器的初始化 age = 20, name = 小倩
- 把对象在堆中的地址,返回给p(p是对象名,也可以理解成是对象的引用)
七、this 关键字
-
this : java虚拟机会给每个对象分配 this ,代表当前对象。
public class This01{ public static void main(String[] args){ Dog dog1 = new Dog("大壮",3); dog1.info(); } } class Dog{ //属性 String name; int age; //构造器 public Dog(String name, int age){ //this.name 就是当前对象的属性 this.name = name; //this.age就是当前对象的属性 this.age = age; } public void info(){//成员方法,输出属性和信息 System.out.println(name + "\t" + age + "\t"); } }
-
小结:哪个对象调用,this 就代表哪个对象
-
注意事项和细节
- this关键字可以用来访问本类的属性,方法,构造器
- this 用于区分当前类的属性和局部变量
- 访问成员方法的语法:this.方法名(参数列表)
- 访问构造器语法:this(参数列表);注意只能在构造器中使用(即只能在构造器中访问另外一个构造器) 访问构造器的语法 this(参数列表);必须放在第一条语句
- this不能在类定义的外部使用,只能在类定义的方法中使用
public class ThisDetail{
public static void main(String[] args){
T t1 = new T();
t1.f2();
T t2 = new T();
}
}
class T{
//访问构造器语法:this(参数列表);注意只能在构造器中使用(即只能在构造器中访问另外一个构造器)
public T (){
//这里取访问T(String name, int age)构造器
this("jack",100);
System.out.println("t() 构造器");
}
public T(String name, int age)构造器
{
System.out.println("(String name, int age 构造器")
}
//细节:访问成员方法的语法:this.方法名(参数列表)
public void f1(){
System.out.println("f1() 方法..");
}
public void f2(){
System.out.println("f1() 方法..");
//调用本类的 f1
//第一种方式
f1();
//第二种方式
this.f1()
}
//this关键字可以用来访问本类的属性
public void f3(){
//以前的方法,找的是最近的name 和 age(即就近原则)
System.out.println("name = " + name,+ "age= "+ age);
//this访问,准确访问类的属性
System.out.println("name = " + this.name,+ "age= "+ this.age);
}
}