学习面向对象
引入
面向对象编程例子:
- 得到一个随机数对象来获取随机数
Random r = new Random();
- 输出
System.out.paintln();
- 创建一个Scanner对象用于接受用户输入的数据
Scanner sc = new Scanner(System.in);
1.类和对象
类(类似于设计图): 是对象共同特征的描述
对象: 是真实存在的具体实例
在java中, 必须先设计类, 才能获取对象
类的定义:
- 成员变量(代表属性,一般是名词)
- 成员方法(代表行为,一般是动词)
- 构造器
- 代码块
- 内部类
获取类的对象:(创建对象)
类名 对象名 = new 类名();
例如: Phone p = new Phone();
对象的使用:
访问属性: 对象名.成员变量
访问行为: 对象名.方法名(...);
创建一个类, 把事物的特征描述放到类里面, 创建对象, 把类里的描述附加到对象上, 然后就可以进行访问操作等(比如: 打印输出)
注意事项:
- 用来描述一类事物的类, 专业叫做:Javabean类, 在Javabean类中, 是不写main方法的(就是在类里面引入的行为方法是不包含main方法的)
- 编写main方法的类就做测试类, 可以在测试类中创建Javabean类的对象并进行赋值调用, 比如: 上面的Phone类就是Javabean类, PhoneTest中包含main方法就是测试类,可以对里面的p对象进行赋值并调用
- 一个java文件中可以定义多个class类,但是只能有一个类是public修饰的, 并且public修饰的类名必须成为这个新建的java文件的代码文件名, 比如:假如在上面的Javabean类中不止定义了一个Phone的类名, 还定义了别的, 那么就只有一个类名可以有public修饰, 其他都不能用public修饰, 假如public修饰的是Phone类名,那么这个新建的java文件名就是Phone
- 但是在实际开发当中, 建议还是一个文件定义一个class类
- 成员变量的完整定义格式: 修饰符 数据类型 变量名称 = 初始化值
(一般无初始化值, 存在默认值, 只有当给对象赋值时才会进行初始化, 赋入初始化值; 修饰符比如:public)
举个例子理解:
面向: 拿, 找
对象: 东西
面向对象编程: 拿东西来进行编程操作
比如: Scanner对象, 在它的类中已经设计好它是用来干什么的了, 然后就把类中的属性附加到上面, 然后我们就可以拿这个Scanner对象来进行编程操作
比如: 洗衣机, 类就是洗衣机的设计图, 设计它的属性, 然后把属性附加到洗衣机上, 但是洗衣机有很多种, 就可以对类中的属性进行赋值, 再加到这个洗衣机上, 这样每个洗衣机就不一样了, 然后再拿这个已经做好的洗衣机对象进行操作
类名 对象名 = new 类名();
创建东西都是new出来的, 需要在内存中开辟空间进行存储, 是把类中的属性附加到对象中, 然后使用对象时, 在用一个名字来表示这个对象, 比如: 同一个手机类(设计图), 产生一个手机对象, 但是有不同的品牌, 所以把不同的品牌赋值到类当中, 然后再附加到对象上, 因为类只是一个设计图, 它的属性并没有进行赋值
比如: 手机(类) 小米手机(对象1), 苹果手机(对象2) 然后就可以拿这些不同的手机进行操作
理解:
测试类就是平时写代码那样, 在main方法中写代码然后运行测试, 只是在里面创建了对象, 并把类中的属性行为附加到对象上, 类就是描述一类事物的, 对象就是这一类事物的一个个个体, set和get是用来判断数据的合理性并进行获取, 在类当中定义属性和行为, 利用封装思想, 对数据进行判断的方法也应当写到类当中, 判断合理就直接赋值到private当中, 用this, 然后获取并调用, 可以直接用get调用, 也可以先用一个变量承接, 然后调用
简单练习,便于理解:
面向对象的三大特征:封装, 继承, 多态
2.封装
封装: 对象代表什么, 就得封装对应的数据, 并提供数据对应的行为
比如: 我们定义了一个类来代表圆的话, 就要定义一些属性来封装圆的信息, 例如半径,既然封装了圆的半径, 那么就要提供和半径相关的画圆的方法
比如: 人关门, 对象是门, 那么就封装门的状态数据, 并提供相应的开关门行为方法
比如: 在java中, socket对象代表网络连接, 那么就会有相关的属性,然后会封装想应的数据, 并提供如何进行网络连接的方法, 在java中已经写好了很多对象,比如计算数组长度,键盘录入,可以直接拿来用
面向对象实际上就是创建一个类记录属性等,然后创建对象承接这个类并进行赋值调用
封装可以让编程变得简单, 有什么事, 找对象, 调方法就行
封装实际就是让类包含对象应该拥有的相关的信息, 这样在使用时能够获取完整的信息, 会更加方便
private关键字:(用来考虑安全性问题)
- 是一个权限修饰符
- 可以修饰成员(成员变量和成员方法)
- 被private修饰的成员只能在本类当中才能访问,这样可以避免不安全,不合理的数据进入赋值给成员
- 针对private修饰的成员变量,如果需要被其他类使用, 要提供相应的操作, 提供"setXXX(参数)"方法,用于给成员变量赋值,方法用public修饰, 提供"getXXX()"方法, 用于获取成员变量的值,方法用public修饰
public关键字: 公用的, 任何类里都能用
在调用时把实参传递到setAge的形参当中, 然后再进行判断, 合理就赋给age变量, 若不合理就直接非法数据, 但是这仅仅只是把数据进行了传递, 并没有获取和调用, 所以要提供getAge方法来获取
3.就近原则和this关键字
比如:
那么如果想要把公用的值赋值给私有的就可以用this, 比如: this.age = age; 这里就是把公用的age赋值给私有age
对于数据安全的判断可以在public下进行, 合理则赋值给private, 不合理就不进行操作,这样可以保证数据的安全合理,在public判断完后赋值时就可以用this进行操作, 因为public外界的值是不可以直接赋给private
4.构造方法(/构造器/构造函数)
作用:给成员变量进行初始化, 在创建对象的时候给成员变量进行赋值的,可以在方法中判断数据的合理性, 然后再进行赋值, 直接赋值可能会产生数据的安全性问题
格式:
public class Student{修饰符 类名(参数){方法体;}
}public class Student{private String name;private int age;public Student(){....//空参构造}public Student(String name, int age){....//带参构造}
}
特点:
- 方法名与类名相同,大小写也要一致
- 没有返回值类型,连void都没有
- 没有具体的返回值(不能由return带回结果数据)
执行时机:
- 创建对象由虚拟机调用, 不能手动调用构造方法
- 每创建一次对象, 就会调用一次构造方法
空参构造和有参构造:
无参构造方法: 初始化的对象时, 成员变量的数据均采用默认值
有参构造方法: 在初始化对象的时候, 同时可以为对象进行赋值
平时最好把空参构造也写上, 因为有时候可能会碰到不知道对象的属性的情况, 比如属性内容是由键盘录入的, 那么就要先创建空参对象
(set和get的顺序没有关系, 因为调用的时候是set写在前面的)
注意事项:
构造方法的定义:
- 如果没有定义构造方法,系统将会给出一个默认的无参数构造方法
- 如果定义了构造方法,系统将不再提供默认的构造方法(比如上面的有参构造, 如果没有定义空参构造, 但是定义了有参构造, 但是调用时调用的是空参构造, 那么就会报错)
构造方法的重载:
看上面的例子可以看到带参构造方法和无参构造方法两者的方法名相同, 但是参数不同, 这叫做构造方法的重载
使用方式: 无论是否使用, 都手动书写无参构造方法和带全部参数的构造方法
5.标准的javabean类
在上面写过, 这里写快捷方式
更快捷:
使用插件1秒生成javabean类
6.对象内存图
一个对象的内存图:(两个对象和一个对象是一样的, 只是重复同样的步骤而已)
- 加载class文件
- 申明局部变量
- 在堆内存中开辟一个空间
- 默认初始化
- 显示初始化(就是把要进行的初始化数据覆盖到默认初始值)
- 构造方法初始化
- 将堆内存中的地址值赋值给左边的局部变量 (就是把对象的地址值赋值给对象的变量)
方法运行完后出栈,变量都会变成垃圾, 对象也都用不了了
两个引用指向同一个对象:
引用就是找到地址值, 并把地址值存储的数据引用过来进行使用
当把null赋值给对象时,地址值通向堆内存的通道就关闭了, 那么运行结果会发生异常
一旦地址值存储的数据发生改变, 那么无论是stu1还是stu2变量, 对属性的访问都会改变, 因为变量都指向同一个空间
另外: 关于引用数据类型和基本数据类型可以在笔记 "方法" 中看
7.this的内存原理
this的作用: 区分局部变量和成员变量
this的本质: 所在方法调用者的地址值
先把形参传递到实参中, 然后再赋值到this地址值所在的空间中去覆盖原来的数据值
8.成员变量和局部变量
在类当中定义属性定义的就是成员变量和成员方法
成员变量: 类中方法外的变量
局部变量: 方法中的变量