目录
引入
回想一下客观世界,|我们的客观世界是由两种东西所组成的:
生活在客观世界中的个体(客体,或物体)
以及个体之间的联系
正是由于现实世界中的个体们,“各司其职”,直接或间接的“相互协作”,才保证了这个世界的正常,有序的流转。
我们面向对象的程序世界和现实世界也极其相似:
运行中的程序,由多个个体(也就是对象)组成
运行中的个体,需要相互协作,共同完成程序的功能
也就是说,要想写出面向对象的程序,必须首先学会构建面向对象程序的基本组成单位——对象。
如何描述一个对象呢?试想下如下场景:
假设你面对一个对地球一无所知的X星人,你要向他描述一只他从未见过的小花猫,你会怎么向他描述呢?
对象:属性和行为
属性(外貌)
行为
面向对象的理解
1.类比于现实世界中的个体(客体),运行中的面向对象程序也是由一个一个的 对象(个体)组成
2.所以,要想让面向对象程序运行,必须首先学,构造对象,对象中包含哪些内容呢?
属性
行为
3.也就是说,要想创建一个对象,就必须向jvm描述,对象的属性和行为,但是我们不可能对每一个对象都去向jvm描述一次,该对象的属性和行为(因为我们的程序中,可能会有成千上万个对象)
4.如何向jvm描述,我们要创建怎么样的对象呢?核心从对象的 属性 和 行为
将同种类型的对象的属性和行为共性,抽取出来 -> 类(描述对象),描述同种类型的所有对象所具有的属性和行为
类 和 对象
5.类和对象,以及对象与对象之间的关系
类VS对象:
类:描述同种类型的对象,共有的属性和行为,但是类描述的是对象有哪些属性,有哪些行为
对象:对象属性的具体取值,类并没有规定,也就是说,对象属性的具体取值,是由每一个具体的对象自己来决定的
对象VS对象:
a:不同类型的对象,对象可能具有不同的属性和行为
b:同种类型的对象,也有区别,区别就在同种类型的不同对象,他们的属性取值,可以不同
我们要向让写好的java程序运行起来,
得有对象,所以首先应该学习如何创建对象,但是,要创建对象,必须首先描述 对象 -〉类来描述对象
所以,为了创建出对象,学习类定义,来描述同种类型的所有对象(属性和行为)
定义一个类,类比于现实世界,说明一种类型(属性和行为)
现实中的事物类型(比如人这个类型):
属性 人的身高,体重... .
行为 人可以,吃饭,睡觉,学习,思考......
Java语言中定义类,也是从这两个方面入手
成员变量 就是事物的属性
成员方法 就是事物的行为
成员变量(对比局部变量):成员变量和局部变量定义的位置不同,成员变量定义在方法体之外,类体之中
成员方法(对比之前的方法)︰之前的方法修饰符都是public static,修饰符中去掉static修饰符的方法就是成员方法
基本语法
Java中定义类其实就是定义类的成员(成员变量(属性)和成员方法(行为))
//成员变量
int a;
//成员方法
public void memberMethod() {
}
1、定义类
/**
定义学生类,来描述所有学生对象共有的属性
1.属性:姓名、性别、年龄、学号
2.行为:吃饭、睡觉、学习
*/
class Student {
String name;
boolean isMale;
int age;
int sno;
public void eat() {
System.out.println(name + "吃饭");
}
public void sleep() {
System.out.println(name + "睡觉");
}
public void study() {
System.out.println(name + "学习");
}
}
2、创建对象及访问对象和行为
public static void main(String[] args) {
//类名 对象名 = new 类名();
Student stu1 = new Student();//stu1引用变量,引用变量需要自己去在堆上创建存储空间
//每个对象的属性都有不同的取值
stu1.name = "shangsan";
stu1.age = 20;
stu1.isMale = true;
stu1.sno = 1;
System.out.println(stu1.name + "--" + stu1.age + "--" + stu1.isMale + "--" + stu1.sno);
//访问对象行为
stu1.eat();
}
从语法层面再次认识类和对象:
1. 回忆一下在基础语法部分讲过的什么是数据类型?
数据类型:一个数据集合和基于这个数据集合的一组操作 byte short int char (比如int可以加减乘除操作)【自带的数据类型】,自己定义的类(自定义数据类型)
2. 类定义:类体中包括成员变量和成员方法
类中定义的数据集合:成员变量的集合
类中定义的操作集合:成员方法的集合
内存原理
Student stu1 = new Student();
Student stu2 = new Student();
Student stu3 = stu1;
特殊语法
1、成员变量:定义在类体中,方法体之外
2、哪些变量是局部变量? 方法中定义的变量和方法的形式参数
3、局部变量和成员变量的比较:
1.在类中定义的位置不同
2.在内存中的位置不同
a.局部变量:都是存储在方法对应的栈帧中
b.成员变量:存储在堆上,在对象的内存中
3.初始化值不同
a.局部变量:局部变量没有天生的初始值,必须在使用前,用代码初始化成员变量的值
b.成员变量:成员变量存储在堆上的,堆上的成员变量,天然有默认初始值
4.生命周期不同
a.局部变量存储在栈帧中,因此,随着方法运行开始和结束,随着栈帧而存在或销毁
b.成员变量,在堆上,对象的内存空间中,成员变量随着对象的存在或销毁(当对象无法使用,变成垃圾的时候)
class Demo1 {
int a;
}
public class TestDemo {
public static void main(String[] args) {
Demo1 d1 = new Demo1();
d1.a = 1;
Demo1 d2 = new Demo1();
d2.a = 2;
System.out.println(d1.a);//1
System.out.println(d2.a);//2
function(d1, d2);
System.out.println(d1.a);//2
System.out.println(d2.a);//1
}
//交换 d1 和 d2这两个引用变量所指向的对象 成员变量的值
public static void function(Demo1 d1, Demo1 d2) {
int a;
a = d1.a;
d1.a = d2.a;
d2.a = a;
}
}
class Demo1 {
int a;
}
public class TestDemo {
public static void main(String[] args) {
Demo1 d1 = new Demo1();
d1.a = 1;
Demo1 d2 = new Demo1();
d2.a = 2;
System.out.println(d1.a);//1
System.out.println(d2.a);//2
function(d1, d2);
System.out.println(d1.a);//1
System.out.println(d2.a);//2
}
//不成立,在栈帧中的形式参数值调换后,函数运行结束,栈帧即销毁,实际参数没有影响
public static void function(Demo1 d1, Demo1 d2) {
Demo1 temp;
temp = d1;
d1 = d2;
d2 = temp;
}
}
构造方法
作用:使得jvm 在构造对象的时候,帮助我们进行成员变量的初始化
public class Constructor {
public static void main(String[] args) {
//使用4参数构造方法
Student zhangsan = new Student("zhangsan", true, 20, 1);
System.out.println(zhangsan.name + " " + zhangsan.isMale + " " + zhangsan.age + " " + zhangsan.sno);//zhangsan true 20 1
//使用2参数构造方法
Student lisi = new Student("lisi", 20);
System.out.println(lisi.name + " " + lisi.isMale + " " + lisi.age + " " + lisi.sno);//lisi false 20 0
}
}
class Student {
String name;
boolean isMale;
int age;
int sno;
//构造方法
public Student(String nameValue, boolean isMaleValue, int ageValue, int snoValue) {
name = nameValue;
isMale = isMaleValue;
age = ageValue;
sno = snoValue;
}
//重载
public Student(String nameValue, int ageValue) {
name = nameValue;
age = ageValue;
}
}
首先,在类中,定义构造方法语法,有两个不同于一般方法的地方
a. 构造方法的方法名固定,和类名相同(这一点,java语言的语法规范,所以构造方法命名,违反了驼峰命名规则)
b. 构造方法(没有返回值)的方法声明中,没有返回值这一项
注意事项:
1. 一个类中可以,定义多个重载的构造方法
2. 我们需要知道,其实,当我们没有在类中定义任何一个构造方法的时候,jvm会自动添加一个默认的构造方法(无参构造方法)
但是,一旦自己在类定义中,定义了哪怕只有一个构造方法,jvm就不会自动添加无参构造方法了
jvm为什么这么干?这和jvm执行固定流程有关系
开辟对象的存储空间 -〉 给对象成员变量赋子默认初值 -〉使用构造方法,初始化对象成员变量的值
3. 构造方法何时执行?
由jvm,来真正调用执行的,在创建对象的最后一步,执行构造方法,给对象的成员变量赋予Coder传递的初值
成员变量的隐藏问题
public class Constructor {
public static void main(String[] args) {
Student student = new Student("zhangsan", true);
System.out.println(student.name + " " + student.isMale + " " + student.age + " " + student.sno);//null false 0 0
}
}
class Student {
String name;
boolean isMale;
int age;
int sno;
//构造方法
public Student(String name, boolean isMale) {
name = name;
isMale = isMale;
}
}
成员变量的隐藏问题
1.方法中定义了和类中同名的成员变量
2.在方法体中,通过通过同名变量的,变量名来访问变量值,只能访问到方法中的,那个局部同名变量的值,而访问不到,同名成员变量的值
3.在方法体中,就好像同名成员变量,被同名局部变量给隐藏起来了
如何解决隐藏问题?核心,就是在方法体中,以某种方式,区分同名成员变量和同名局部变量
引入一个关键字:this,帮助我们解决了,成员变量的隐藏问题
this关键字
this关键字:代表(对象自身)当前对象 的引用
当前对象:
a.在构造方法中的this,指代的当前对象,其实就是,构造方法执行时,jvm正在创建的对象
b.在普通成员方法而言,对象名.方法() 在哪个对象上调用方法,方法中的this就指的是哪个对象
his关键字的作用:
1.解决成员变量的隐藏的问题
2.访问对象的成员(访问当前对象的成员变量值,访问当前对象的成员方法)
3. 访问对象的构造方法 this(实参列表) 在某个构造方法中,调用其他构造方法
a.this调用构造方法,只能出现在某个构造方法的方法体中
b.this调用构造方法,必须处在构造方法的第一条语句的位置
public class Constructor {
public static void main(String[] args) {
Student student = new Student("zhangsan", true);
System.out.println(student.name + " " + student.isMale + " " + student.age + " " + student.sno);//lisi false 20 0
}
}
class Student {
String name;
boolean isMale;
int age;
int sno;
public Student() {
//this调用其他构造方法
//System.out.println();错误 this在第一行
this("lisi", true);
}
//构造方法
public Student(String name, boolean isMale) {
this.name = name;
this.isMale = isMale;
}
public void study() {
System.out.println(this.name + "学习");
//调用普通成员方法
this.test();
}
public void test() {
}
}