Java07面向对象
-
面向对象并非一个技术,而是一种编程思想,这套思想来源于生活,指导我们用什么样的思路解决问题,用什么样的思路来组织代码。
-
Q:为什么要学习这种思想 ?
A:因为这套思想来源于生活。生活中解决任何问题其实就是一系列对象在一起打交道,从而解决问题。生活中的任何一件事物,都可以通过代码,将其描述为对象。用这种思想编程,会使得编程不那么抽象,更加便于让人理解,这样才能更好地用代码去解决问题。
举例1: 解决随机数的问题 ---> Random对象 举例2: 解决键盘录入的问题 ---> Scanner对象 举例3: 封装学生数据 ---> Student对象
-
面向对象学什么?
- 学习自己如何设计对象
- 学习已有的对象如何使用(API章节)
一.类和对象
1.类和对象的介绍
-
类
Java中创建对象前必须要先有类。类指的是一组相关属性和行为的集合。
-
对象
对象是根据类(设计图),创建出来的实体
2.类和对象的关系
依赖关系:需要根据类,创建对象
数量关系:根据一个类,可以创建出多个对象
3.类的组成
-
属性
代码中使用成员变量表示,成员变量定义格式跟之前定义变量的格式一样,只不过位置需要放在类中方法外
-
行为
代码中使用成员方法表示,成员方法定义格式跟之前定义方法格式一样,只不过需要去掉static关键字
4.类的设计思想
描述一件事物是名词和动词结合在一起描述。一般名词设计为属性,动词设计为行为。
例如:有一个{学生}叫做<张三>, 今年<23岁>, <180的身高>, 平时没什么特殊爱好, 就喜欢(吃饭)和(学习).
public class Student {
// 属性: 姓名, 年龄
String name;
int age;
int height;
// 行为: 吃饭, 学习
public void eat(){
System.out.println("吃饭");
}
public void study(){
System.out.println("学习");
}
}
5.对象的创建和使用
-
创建格式:类名 对象名 = new 类名();
Student stu = new Student();
System.out.println(stu); // com.itheima.oop.Student@233ac477 打印对象名看到的是内存地址
-
调用格式
-
调用成员变量格式:对象名.变量名;
-
调用成员方法:对象名.方法名();
-
//调用成员变量
stu.name = "张三";
stu.age = 23;
stu.height = 180;
System.out.println(stu.name);
System.out.println(stu.age);
System.out.println(stu.height);
//调用成员方法
stu.eat();
stu.study();
♥细节补充
1、定义类时,成员变量通常不赋值,要等对象创建完毕后,再给成员变量赋值。
2、成员变量就算没有赋值,也可以直接使用,使用的是默认值。
二.对象内存图
1.单个对象内存图
Q1.什么时候加载类字节码?A:从主函数main开始调用,其他的类要用时便加载到方法区。
理解过程:new对象进堆内存,同时为成员变量分配空间,不加载成员方法,而是记录成员方法的内存地址并交给方法区对应的字节码中的成员方法管理,创建完成后将对象的内存地址交给栈内存中的对象记录,便于调用时能查找到该对象的成员变量。同理,调用其成员方法时,先根据内存地址找到堆内存中,再根据堆内存中记录的地址找到方法区里的方法,层层嵌套找到再后调用该成员方法,调用结束后弹栈。
2.两个对象内存图(方法共用内存图)
注意!
1.在一次程序执行的过程中,某一个类就算创建了多个对象,该类的字节码文件只加载一次。
2.每new一个对象,就会在堆内存中重新开辟一片新的空间,分配新的内存地址,因此同一个类创建的两个对象以及其各自的成员变量是相互独立的,而他们的成员方法是共享的,因此该图也叫方法共用内存图。
3.两个引用指向相同内存图
两个对象指向同一个地址后,其实代表只有一个对象拥有两个不同的名字而已。不管用哪个对象名调用,都访问该对象地址。好比你的大名和小名,不管叫哪个,其实都是你。
三.成员变量和局部变量
1.成员变量与局部变量的区别
区别 | 成员变量 | 局部变量 |
---|---|---|
类中位置不同 | 方法外 | 方法中 |
初始化值不同 | 有默认初始化值 | 没有默认初始化值,使用之前必须完成赋值 |
内存位置不同 | 堆内存 | 栈内存 |
生命周期不同 | 随着对象的创建而存在,随着对象的消失而消失 | 随着方法的调用而存在,随着方法的运行结束而消失 |
作用域 | 类 | 成员方法中 |
注意变量的作用域范围其实就在自己归属的大括号里面!!!
四.this关键字
当局部变量和成员变量重名时,Java一般选择就近原则,优先使用局部变量。非要使用成员变量,就需要使用this关键字进行区分。
class Student {
int num = 10;
public void show(){
int num = 20;
System.out.println(num); // 20 局部变量
System.out.println(this.num); // 10 成员变量
}
}
1.this可以解决的问题
this可以区分局部变量和成员变量的重名问题。
2.作用&省略规则
用来调用本类成员
this.本类成员变量:如果局部变量和成员变量不涉及重名时,this.可以省略不写
this.本类成员方法():this.可以直接省略
3.对this的理解(助记)
代表当前类对象的引用(地址),谁来调用我,我就代表谁
五.构造方法
1.构造方法概述
-
构造方法(构造器)
初始化一个新的对象
构建、创造对象的时候,所调用的方法
-
格式
1.方法名与类名相同,大小写也要一直
2.没有返回值类型,连void都没有
3.没有具体的返回值(不能由return带回结果数据)
public class Student { public Student(){ System.out.println("我是Student类的空参数构造方法"); } }
-
构造方法的执行时机
1、在创建对象的时候,被调用执行
2、每创建一次对象,就会执行一次构造方法
-
作用
1.本质作用:创建对象
2.结合执行时机:在创建对象的时候,给成员变量赋值
public class Student {
String name;
int age;
public Student(String name, int age){
this.name = name;
this.age = age;
}
}
Student stu = new Student("张三", 23); //这里调用上述构造方法
-
注意事项
-
如果一个类中没写构造方法,系统将会提供一个【默认的】【无参的】构造方法;
-
如果手动编写过构造方法,系统将不再提供默认的无参构造方法
因此,建议刚开始写代码时将无参构造和含参构造全部编写
-
构造方法不允许手动调用,如stu.Student();是错误的调用
-
六.封装(非常重要)
面向对象三大特征:封装、继承、多态
1.封装
使用类设计对象时,将需要处理的数据,以及处理这些数据的方法,设计到对象中
-
合理暴露,合理隐藏
隐藏实现细节,仅对外暴露公共的访问方式。可结合插线板理解
-
封装在代码中的常见体现
-
将属性抽取到类中, 是对数据做了封装
使用封装前 : 维护一个用户信息, 定义了5个变量, 数据过于零散 String id = "001"; String name = "张三"; int age = 23; String tel = "156****1234"; String address = "北京"; ---------------------------------------------------------- 使用封装后 : 5个零散的数据, 就被封装到了一个整体的对象中 public class User { String id; String name; int age; String tel; String address; // 假设我写了带参数构造方法 } User u1 = new User("001","张三",23,"156****1234", "北京"); User u2 = new User("002","李四",23,"156****1244", "北京");
-
将代码抽取到方法中, 是对代码功能进行了封装
程序员A : 编写了一个遍历打印数组的方法 public void printArray(int[] arr){ ... } 程序员B : 无需关心方法内部实现, 只要知道怎么调用即可. 以上过程, 就是程序员A, 将遍历打印数组这个功能代码, 封装到了printArray方法中.
-
2.权限修饰符
-
public 任意位置,访问权限最大
-
private 同一个类中,访问权限最小
-
default 默认权限,同一个类中,同一个包中
-
protected 同一个包中,不同包的子类
3.标准JavaBean
-
所有成员变量私有private
-
提供空参以及带参的构造方法
-
对私有成员变量,提供对应的setxxx和getxxx方法
public class Student {
private String name; //私有成员变量
private int age; //私有成员变量
public Student() { //空参构造方法
}
public Student(String name, int age) { //带参构造方法
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
-
构造标准JavaBean的方法
1、纯手写哈哈哈哈哈哈哈哈哈哈哈,谁写谁是大怨种。
2、使用快捷键
首先在所在类的大括号中间,鼠标右击,选择Generate选项,当然业可以使用快捷键Alt+Insert
然后选择Constuuctor构造器
接着依次构造无参和含参构造函数
构造get和set方法如出一辙,在Generate下选择Getter and Setter,勾选全部的成员变量(全选快捷键Ctrl+A),点击ok即可生成。
3、使用插件
在idea左上角点击file->settings->plugins,搜搜ptg插件,选在install安装。安装之后回到类中鼠标右键就会出现Ptg To JavaBean选项,点击,即可一键生成空参有参构造方法以及所有成员变量对应的set、get方法