oop初级

类与对象(初级)

类是抽象的,对象是实例的,类是对象的模板,对象是类的一个个体

1. 对象内存布局

基本数据类型直接放在堆中,不放方法区的常量池

在new对象的时候会在方法区中加载Cat类信息

2. 基本介绍

叫法:成员变量 = 属性 = field(字段)

属性一般是基本数据类型,也可以是引用数据类型

属性的注意事项及其说明:

(1).属性的定义: 访问修饰符 属性类型 属性名;

(2).访问修饰符:控制属性的访问范围; 4种访问修饰符(public;proctected;默认;private)

(3).属性一般是基本数据类型,也可以是引用数据类型

(4).属性如果不赋值有默认值

访问属性:对象.方法

jvm的内存分析代码执行流程

0198集

类信息只会加载一次

//Person b;
b = null;//b -> null;b不再具有堆中存放的属性(或者说不再指向堆中存放原有属性的地址)(也就不能调用b中原有的属性)

方法调用机制

方法调用流程(小结):

  1. 在main栈中new一个Person类的对象,指向堆中的(对象);

  2. 用该对象调用方法,就会开辟一个独立的空间(栈空间)(getSum栈(独立空间))

  3. 当方法执行完毕,或者执行到return语句时,就会返回

  4. 返回到调用方法的地方

  5. 返回后,继续执行方法后面的代码

  6. 当main方法(栈)执行完毕,整个程序退出

3. 成员方法的定义

基本语法:

访问修饰符 返回数据类型 方法名 (形参列表..){

方法体语句;

return 返回值;

}

  1. 形参列表:表示成员方法输入 cal(int n),getSum(int num1,int num2);

  2. 数据类型(返回类型):表示成员方法输出,void表示没有返回值

  3. 结合void是否使用return语句

  4. 方法体:为了实现某一功能的代码块

4. 方法注意事项与细节

  1. 访问修饰符(public, protected, 默认,private);如果不写默认访问

  2. 一个方法最多有一个返回值[如何返回多个值? --> 返回数组]

  3. 返回类型可以为任意类型,基本数据类型和引用类型

  4. 参数类型可以为任意类型,包含基本类型或引用类型

  5. 如果方法要求有返回数据类型,则方法体最后为 return 值;且要求返回值类型必须和return类型一致或者兼容

  6. 如果方法是void,则方法体中可以没有return语句,或者只写 return;

  7. 方法定义时的参数称为形参方法调用时的传入参数称为实参;实参与形参类型一致或兼容个数、顺序必须一致

  8. 方法不能嵌套定义

方法调用细节:

  1. 同一个类中的方法调用:直接调用就行

  2. 跨类方法调用:通过对象名调用

特别说明:跨类的方法调用与方法的访问修饰符有关

5. 方法传参!!!(paramete 参数)

(1).基本数据类型的传参机制

以一个冒泡交换的案例引:

swap栈与main栈空间独立

结论:基本数据类型传递的是(值拷贝),形参的任何改变不影响实参。(如上图)

(2).引用数据类型的传参机制(数组)

引用类型(数组) 指向 堆中一个地址

调用一个方法就会产生一个新栈

引用类型传递地址!!

结论:引用类型传递的是地址(地址中有值),可以通过形参影响实参。(如上图)

(3). 传对象

p.age = 10000; //修改对象属性

深刻剖析:

实质上就是传对象

原来的 p.age = 10 ; 然后调用test200方法,将p传进去,然后修改对象属性 p.age = 10000;

思考?

1.如果将上面B类中的 p.age = 10000; 改为 p = null; 结果如何?

B类中的p对象为空,只是自己变为空,对age无影响,所以age没有改变,所以 main 的p.age=10

 

2.如果将上面B类中的 p.age = 10000; 改为 p = new Person(); p.name = "tom"; p.age = 99; 结果如何?

深刻剖析:

出现 p = new Person(); 实质上是创建了一个新的对象p(开辟了一个新的空间,与main方法中的对象p空间相互独立),

p.name = "tom"; p.age = 99; 实质上是对这个新创建的对象进行赋值与main方法中的p对象无关

形参类型与方法类型一致

6. 递归

入门案例

案例一:

自己调用自己,不断开辟新栈;当不满足条件,执行输出语句;不断返回上一个栈(从最顶级的栈开始返回),执行未完成的语句;

直到返回到最后一个栈,程序退出

案例二:

阶乘

递归重要规则

  1. 执行一个方法时,就创建一个新的受保护的独立空间(栈空间)

  2. 方法的局部变量是独立的,不会相互影响,比如n变量

  3. 如果方法中使用的是引用类型变量(数组,对象)(指向地址),就会共享该引用类型的数据(相互影响)

  4. 递归必须向退出递归的条件逼近

  5. 当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕(程序退出)

实质:递归就是从后往前推,在最前面找一个临界条件;根据所给的最后条件一步步往前推

递归具有回溯现象!!!(老鼠走迷宫)

汉诺塔,八皇后

7. 方法重载

java中允许一个类中,多个同名方法的存在,但要求形参列表不一致!

当使用方法时系统自动匹配符合形参列表的方法

细节:

  1. 方法名相同

  2. 形参不同(不是说形参的名字不同)

  3. 返回类型无要求(可以是void也可以是基本数据类型)

可变参数

java允许将同一个类中多个同名同功能参数个数不同的方法,封装成一个方法。就可以通过可变参数实现

基本语法:

访问修饰符 返回类型 方法名 (数据类型... 形参名){ }

使用可变参数时可以当作数组来使用(加上循环)

细节:

  1. 可变参数个数可以为0个或者多个

  2. 可变参数的实参可以为数组

  3. 可变参数的本质就是数组

  4. 可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后

  5. 一个形参列表中只能出现一个可变参数

8.变量作用域!!!

细节:

  1. 主要变量是属性(成员变量)和局部变量(是指在成员方法中定义的变量)

  2. 属性作用域为整个类局部变量(除了属性外的变量)作用域在定义它的代码块中

  3. 属性可以不赋值(有默认值),局部变量必须赋值

注意:

  1. 属性和局部变量可以重名,访问时遵循就近原则

  2. 在同一个作用域中,比如在同一个成员方法中,两个局部变量,不能重名

  3. 属性生命周期长(随对象),局部变量声明周期短

  4. 作用域范围不同:属性可以被本类或其他类使用(new对象)(1.方法调用 2.传对象);局部变量只能在本类中对应的方法使用

  5. 属性可以加修饰符,局部变量不能加修饰符

9. 构造器(construor)

基本语法:

[修饰符] 方法名 (形参列表){

方法体;

}

  1. 修饰符可以默认

  2. 没有返回值,也不能写void

  3. 方法名和类名一样

  4. 参数列表和成员方法一样的规则

  5. 构造器调用由系统完成

作用:初始化对象

一个没有返回值的方法(用来给属性初始化值传入的)

Person p1 = new Person("smith", 80); //传入初始化属性的值

当构造器被调用的时候,对象已然存在(不是创建对象,是初始化)(传入属性)

补充细节:

  1. 一个类可以定义多个构造器,即构造器的重载(形参列表)(可以通过不同对象传入不同实参理解)

  2. 如果没有写定构造器,系统会给出一个默认无参构造器(Dog dog1 = new Dog();)

  3. 如果定义了自己的构造器,默认无参构造器就不能使用(覆盖),除非显示定义一下(Dog( ){ })

真正的对象在堆中,栈中的只是对象名

流程分析:

  1. 加载Person类信息(Person.class),只会加载一次

  2. 在堆中分配空间(地址)(实际对象)

  3. 完成对象初始化 [3.1 默认初始化 age = 0,name = null; 3.2 显示初始化 age = 90,name = null; 3.3 构造器的初始化 age = 20, name = 小倩]

  4. 将对象在堆中的地址,返回给p(p是对象名,也可以理解成是对象的引用)

10. this关键字

Dog dog1 = new Dog("大壮",3);
dog1.info();//大壮 3
//一个对象就是一个独立空间
//栈中存放方法,堆中存放对象
class Dog{
   String name;
   int age;
   public Dog(String name,int age){
       //this.name 就是当前对象的属性name
       this.name = name;
       //this.age 就是当前对象的属性age
       this.age = age;
       //也就是令传入的("大壮",3)(String name,int age) 赋给当前对象dog1,则dog1的name = "大壮",age = 3
       System.out.println("this.hashCode" + this.hashCode());//可通过hashcode来看this和dog1的地址(不是真的地址)
  }
   public void info(){
       System.out.println(name + "\t" + age + "\t");
  }
}

jvm内存深入理解this

this小结:哪个对象调用,this就代表哪个对象!!!

细节:

  1. this关键字可以用来访问本类的属性(准确访问)、方法、构造器

  2. this用于区分当前类的属性和局部变量

  3. 访问成员方法的语法:this.方法名(参数列表);

  4. 访问构造器语法:this(参数列表);注意只能在构造器中使用(在一个构造器中访问另一个构造器 this(参数列表)必须放在开始)(构造器复用)

  5. this不能在类定义的外部使用,只能在类定义的方法中使用

new Test().count1(); //new Test()是匿名对象,匿名对象使用后,就销毁(不能再使用)
System.out.println("count=" + count++);//先输出count,再自增

 

posted @ 2022-01-10 21:57  两生jh  阅读(49)  评论(0)    收藏  举报