目录
1. 面向对象的理解
1.1 学习线路
面向对象 学习的三条主线:
- java类以及类的成员: 属性,方法, 构造器,代码块,内部类
- 面向对象的三大特征,封装 继承 多态,(抽象性)
- 其他关键字
属性,方法, 构造器使用 最多
代码块,内部类使用较少
1.2 面向对象的要素
面向对象的2个要素:
类 :对一类事物的描述, 是抽象的
对象: 实际存在的个体,也叫实例
- 面对对象的程序设计重点是类的设计;
- 类的设计就是类成员的设计;
2. 类和对象
2.1 类的示例
设计类,其实就是设计类的成员。
一个类包含的属性和方法;
属性: 对应类中的成员变量, 属性=成员变量, field, 字段, 域
方法:对应类中的成员方法,方法=成员方法, 函数
通过 “对象.属性” 或者 ‘ 对象.方法“ 调用对象的结构 。
可以通过对象反推出类,叫做反射。【高级部分涉及到】
package com;
/*
*
* 如果一个类创建了多个对象,则每个对象都独立的拥有一套类的属性。【非static的】
* 如果修改一个对象的属性a, 则不影响另一个对象的属性a的值。
*
* 在方法中是能调用当前类中的属性的
*
* */
public class apple {
public static void main(String[] args) {
System.out.println("Start");
// 创建对象 == 实例化类
Person person1 = new Person();
// 调用对象的 方法
person1.eat();
person1.language("chinese");
// 调用对象的 属性
System.out.println(person1.age);
person1.age = 1099;
System.out.println(person1.age);
//**************************
Person person2 = new Person();
System.out.println(person2.name); // null
//**************************
//将p1变量保存的对象地址赋值给p3, 导致p1和p3指向了堆空间中的同一个对象实体。
Person person3 = person1;
System.out.println(person3.age); // 1099 同p1的age
}
}
class Person{
String name;
int age = 1;
public void eat(){
//在方法中是能调用当前类中的属性的
System.out.println(name);
System.out.println("eat");
}
public void language(String language){
System.out.println("speak " + language);
}
}
2.2 对象的内存解析
堆:存放对象实例,包括new 语句出来的对象, new 出来的数组也会存放在堆里。创建的实体, 真实的对象都存在这里面。
栈:存放的是局部变量;
方法区:类的加载信息, 常量,静态池都是在这
2.2.1 对象的内存解析
第一句:new Person, 会在堆里面创建一个空间, 并有一个地址;并赋值给p1,p1是在main方法中, 方法中的变量都是局部变量, 所以p1会存到栈中, 是将堆里的空间赋值给p1,即0x12ab。通过这个地址值, 栈空间中p1就指向的堆空间中的实体【红色箭头】;在Person类中,还有三个属性,name,age,isMale, 这三个不同于局部变量【即p1】,三个属性是存在堆空间中的。 而且属性在没有赋值的时候会有默认值的,字符类型的默认值是null,布尔值默认的是false,int类型默认值是0.。如果属性有赋值那就是所赋的数值。
第二句:p1.name=‘Tom’ 将堆空间中的name的默认值null, 修改为Tom,实际上Tom是存在方法区的。
p1.isMale=true 这句同理。
第四句:Person p2 = new Person(); 和p1对象的创建同理, 如图
第五句:sysout(p2.name) 是在局部变量p2指向的堆空间地址为0x7788的name取值, 因为没有赋值,默认值就为null;
第六句:Person p3=p1 p3是局部变量,所以存在栈中,p1同理。 将p1的值赋值给p3,即p3和p1指向同一个堆空间地址。所以p3对象能取到的和p1对象能取到的是同一个值。 p3在这句中,算是新声明了变量,并不是新创建了对象。如果是p3修改了属性值, 那么p1取到的属性值也是修改后的。
要点注意:
- 只要是new的结构,都是在堆里
- 栈的特点:先进后出
- 方法中变量都是局部变量,所以定义的变量,p1 p2 p3是存在栈中
2.2.2 对象数组的内存解析
如上图:
第一句:new Student[5] 创建数组, 且数组是接受Student类,在堆空间中开辟一个地址存放,即0x7788。赋值给stus变量,stus是局部变量,所以存在栈空间中。且指向堆空间的中的0x7788。
第二句:在堆中地址为0x7788的空间内,开辟了5个长度的数组,默认全部为null。执行到stus[0] = new Student();
new Student() 在堆空间中创建一个对象,地址为0x1122,且其中存有Stubent的三个属性,并且赋值给stus[0],即将堆空间中的地址为0x7788的数组的第一个空间赋值为0x1122, 指向的是新建的对象。
第三句: sysout(stus[0].state) 取出的是1,先到数组的第一个元素位置, 取到Student类的地址,到了0x1122地址中,取到state的值, 即指针的指针。
第四句:因为没有给stus[1] 赋值 默认为空
第五句:因为stus[1] 默认为空, 是没有指针的,所以取不到后面的number,会报错空指针;
第六句:stus[1]=new Student() 同理第一句
2.3 属性与局部变量
属性(成员变量) vs 局部变量
1)相同点:
1.1)定义格式是一样的;数据类型 变量名=变量值
1.2)先声明再使用;
1.3)变量都有其对应的作用域
2)不同点:
2.1)声明的位置不同
属性:声明在类的{}中, 就是python类中的类属性的位置;
局部变量: 声明在方法内,方法形参,代码块,构造器内部的变量;
2.2)权限修饰符不同
属性:可以指定权限修饰符;private public 缺省 protected
局部变量:不能加权限修饰;会报错
2.3)默认初始化值不同
属性:
整型(byte、short、int、long):0
浮点型(float、double):0.0
字符型(char):0 (或'\u0000')
布尔型(boolean):false
引用数据类型(类、数组、接口):null
局部变量:没有默认初始化值。意味着,我们在调用局部变量之前,一定要显式赋值。特别地:形参在调用时,我们赋值即可。
2.4) 在内存中加载的位置:【参考上面2.2的对象内存解析过程】
局部变量:加载到栈空间
属性:加载到堆空间中 (非static)
class User{
// 属性 成员变量
String name;
int age;
public void talk(String language){ // language 就是形参 是局部变量
System.out.println("+++ " + language);
}
public void food(){
String foodName = "MAN TOU"; // 局部变量
}
}
2.4 方法
2.4.1 方法的声明
权限修饰符 返回值类型 方法名(形参列表){
方法体
}
static、final、abstract 也是来修饰的方法,后续再整理。
2.4.2 方法的说明
2.4.2.1 关于权限修饰符:
默认方法的权限修饰符先都使用public。Java规定的4种权限修饰符:private、public、缺省、protected -->封装性再细说
2.4.2.2 返回值类型
有返回值 vs 没有返回值:
如果方法有返回值,则必须在方法声明时,指定返回值的类型。同时,方法中,需要使用return关键字来返回指定类型的变量或常量:“return 数据”。 如果方法没有返回值,则方法声明时,使用void来表示。通常,没有返回值的方法中,就不需要使用return.但是,如果使用的话,只能“return;”表示结束此方法的意思。
方法名:属于标识符,遵循标识符的规则和规范,“见名知意”
2.4.2.3 形参列表
方法可以声明0个,1个,或多个形参。
格式:数据类型1 形参1,数据类型2 形参2,…
2.5 方法重载
定义:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
两同一不同":同一个类、相同方法名
- 参数列表不同:参数个数不同,参数类型不同
判断是否是重载:
- 跟方法的权限修饰符、返回值类型、形参变量名、方法体都没有关系!
在通过对象调用方法时,如何确定某一个指定的方法:
- 方法名 —> 参数列表
2.6 关于变量的赋值
- 如果变量是基本数据类型,此时赋值的是变量所保存的数据值。
- 如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值。
2.7 方法的形参的传递机制:值传递
形参:方法定义时,声明的小括号内的参数
实参:方法调用时,实际传递给形参的数据
值传递机制:
如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值。
如果参数是引用数据类型,此时实参赋给形参的是实参存储数据的地址值。