06.01_面向对象思想概述
- A:面向过程思想概述
- 第一步,第二步,第三步…
- B:面向对象思想概述
- 找对象(第一步,第二步,第三步…)
- C:面向对象的思想特点
- 是一种更符合我们思想习惯的思想
- 可以将复杂的事情简单化
- 将我们从执行者变成了指挥这,角色发生了转换。
- D:面向对象开发
- 就是不断的创建对象,使用对象,指挥对象做事情。
- E:面向对象设计
- 其实就是在管理和维护对象之间的关系。
- F:面向对象特征
- 封装(encapsulation)
- 继承(inheritance)
- 多态(polymoraphism)
06.02_类与对象概述
- A:学习编程是为了什么?
- 为了把我们日常生活中的实物用学习语言描述出来。
- B:如何描述现实世界事物?
- 属性 就是该事物的描述信息(事物身上的名词)
- 行为 就是该事物能够做什么(事物身上的动词)
- C:Java中最基本的单位是类,Java中用class描述事物也是如此。
- 成员变量 就是事物的属性
- 成员方法 就是事物的行为
- D:定义类其实就是定义类的成员(成员变量和成员方法)
- 成员变量 和以前定义的变量一样,只不过位置发生了改变。在类中,方法外。
- 成员方法 和以前定义方法一样,只不过把static去掉,后面详细讲解static的作用。
- E:类和对象的概念
- 类:是一组相关属性和行为的集合
- 对象:是该类事物的具体体现
- 举例:
- 类:学生
- 对象:具体的某个学生就是对象
06.03_学生类的定义
- A:案例演示
- 属性:姓名,年龄,性别
- 行为:学习,睡觉
- B:程序段
class Demo1_Student {
public static void main(String[] args) {
}
}
class Student {
String name; //姓名
int age; //年龄
String gender; //性别
//定义学习的方法
public void study() {
System.out.println("学生学习");
}
//定义睡觉的方法
public void sleep() {
System.out.println("学生睡觉");
}
}
06.04_手机类的定义
- A:案例演示
- 属性:品牌,价格
- 行为:打电话,发信息,玩游戏
- B:程序段
class Demo2_Phone {
public static void main(String[] args) {
}
}
class Phone {
String brand; //品牌
int price; //价格
//打电话
public void call() {
System.out.println("打电话");
}
//发信息
public void sendMessage() {
System.out.println("发信息");
}
//玩游戏
public void playGame() {
System.out.println("玩游戏");
}
}
06.05_学生类的使用
- A:文件名问题
- 在java文件中写两个类
- 基本类:如06.03的Demo1_Student类
- 测试类:如06.03的Student类
- 建议:文件名称和测试类名称一致
- 在java文件中写两个类
- B: 如何使用对象?
- 创建对象并使用
- 格式
- 类名 对象名 = new 类名();
- C:如何使用成员变量?
- 对象名.变量名
- D:如何使用成员方法?
- 对象名.方法名(…)
- E:程序段
class Demo1_Student { //测试类
public static void main(String[] args) {
//创建对象的格式:类名 对象名 = new 类名();
//对象名:其实就是合法的标识符,如果是一个单词,所有字母小写,如果是多个单词,从第二个单词开始首字母大写
Student s = new Student();
//使用成员变量
s.name = "张三";
s.age = 23;
System.out.println(s.name + "..." + s.age);
//使用成员方法
s.study();
s.sleep();
}
}
class Student { //基本类
String name; //姓名
int age; //年龄
String gender; //性别
//定义学习的方法
public void study() {
System.out.println("学生学习");
}
//定义睡觉的方法
public void sleep() {
System.out.println("学生睡觉");
}
}
06.06_一个对象的内存图
- 1.编译生成的字节码文件里的Demo1_Car.class类进入内存里的方法区,并执行主方法main。
- 2.主方法main压栈。
- 3.创建对象c1,首先是将编译生成的Car.class类进入到内存里的方法区,并在堆里开辟一块内存,其中成员变量赋值为默认值(即color =null,num = 0),最后将堆里的地址0x0011赋值给c1。
- 4.给堆里的成员变量赋值,color = “red”,num = 8;
- 5.执行成员方法run,此时run压栈。执行完成之后,再出栈。最后是main方法出栈。
06.07_二个对象的内存图
- A:内存里的执行流程
- 1.编译生成的字节码文件里的Demo1_Car.class类进入内存里的方法区,并执行主方法main。
- 2.主方法main压栈。
- 3.创建对象c1,首先是将编译生成的Car.class类进入到内存里的方法区,并在堆里开辟一块内存,其中成员变量赋值为默认值(即color =null,num = 0),最后将堆里的地址0x0011赋值给c1。
- 4.给堆里对象c1的成员变量赋值,color = “red”,num = 8;
- 5.执行成员方法从c1.run,此时c1.run压栈。执行完成之后,再出栈。
- 6.创建对象c2,因为Car.class类已经在方法区里存在,所以这里直接在堆里开辟一块内存,其中成员变量赋值为默认值(即color =null,num = 0),最后将堆里的地址0x0022赋值给c2,并且给堆里的成员变量赋值,color = “black”,num = 4;。
- 7.执行成员方法从c2.run,此时c2.run压栈。执行完成之后,再出栈。
- 8.将空指针null赋值给c2,此时,对象c2的引用为空,那么在调用c2.run()是就会报错,会报出空指针异常的错误。而且此时步骤6在堆里开辟的那块内存就会变成垃圾,最红由Java的垃圾回收机制回收
- 9.若将8对应的代码删去,最后就是main方法出栈。
- B:注意事项
- a:Java里的垃圾回收机制
- 如果没有任何引用指向该对象,那么该对象就会变成垃圾。Java中有完善的垃圾回收机制,会在不定时对其进行回收。这点与c语言不同,在c里,new出来的那块内存,必须要手动释放,即用delete释放。
- b:既然有垃圾回收机制,那么我们是不是每次都要在用完对象后赋值为null呢?
- 这是不必要的,因为随着主方法main的出栈,main里的所有对象都会变为null。
- a:Java里的垃圾回收机制
06.08_三个对象两个引用内存图
06.09_成员变量与局部变量的区别
- A:在类中的位置不同
- 成员变量:在类中方法外
- 局部变量:在方法的定义中或者方法的声明上
- B:在内存中的位置不同
- 成员变量:在堆内存(成员变量属于对象,对象进堆内存)
- 局部变量:在栈内存(局部变量属于方法,方法进栈内存)
- C:生命周期不同
- 成员变量:随着对象的创建而存在,随着对象的消失而消失
- 局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
- D:初始化值不同
- 成员变量:有默认的初始化值
- 局部变量:没有默认的初始化值,必须定义,赋值,然后才能使用
- E:注意事项
- 局部变量名称可以和成员变量名称一样。在方法中使用的时候,采用的是就近原则。
- 为什么?因为局部变量和成员变量的存储位置不一样,所以可以重名。
- 基本数据类型包括哪些:四类八种
- 引用数据类型包括哪些:数组,类,接口,枚举
- 局部变量名称可以和成员变量名称一样。在方法中使用的时候,采用的是就近原则。
- F:程序段
class Demo1_Person {
public static void main(String[] args) {
Person p = new Person();
p.speak(0);
/*
null //成员变量默认初始化值
0 //成员变量默认初始化值
10 //局部变量可以和成员变量同名,但使用前必须先初始化,并且使用时为就近原则。
*/
}
}
class Person {
String name; //成员变量
int num; //成员变量
public void speak(int x) { //x是局部变量
System.out.println(name);
System.out.println(num);
int num = 10; //与上面的num不同,这里的num是局部变量
System.out.println(num);
}
}
06.10_方法的形式参数时类名的时候如何调用
- A:案例演示
class Demo1_Student {
public static void main(String[] args) {
print(10);
Student s = new Student(); //创建对象,并将对象的地址值赋值给s
print(s);
}
public static void print(int x) { //基本数类型当作形参
System.out.println(x);
}
public static void print(Student stu) { //引用数据类型当作形式参数
stu.name = "张三";
stu.age = 23;
stu.speak();
}
}
class Student {
String name;
int age;
public void speak() {
System.out.println(name + "..." + age);
}
}
- B:如果你看到了一个方法的形式参数是一个类的类型(引用数据类型),这里其实需要的是该类的对象。
06.11_匿名对象的概述和应用
- A:什么是匿名对象?
- 没有名字的对象
- B:匿名对象应用场景
- a:调用方法,仅仅只调用一次的时候
- 那么,这种匿名调用有什么好处吗?
- 节省代码
- 注意:调用多次的时候,不适合。匿名对象调用完毕就是垃圾。可以被垃圾回收器回收。
- 那么,这种匿名调用有什么好处吗?
- b:匿名对象可以作为实际参数传递
- a:调用方法,仅仅只调用一次的时候
- C:案例演示
class Demo1_Car {
public static void main(String[] args) {
//说明问题1:有名字的对象和匿名对象的使用特点
/*
匿名对象没调用一次,就创建一个对象。
*/
/*
Car c1 = new Car(); //创建有名字的对象
c1.ru1();
c1.run1();
new Car().run1(); //匿名对象调用方法
new Car().run1(); //匿名对象只适合对方法的一次调用,因为调用多次就会产生多个对象,不如用有名字对象
*/
//说明问题2:匿名对象是否可以调用属性并赋值?有什么意义?
/*
匿名对象可以调用属性,但是没有意义, 因为调用后就变成垃圾。
如果需要赋值,还是要用有名字的。
*/
/*new Car().color = "red";
new Car().num = 8;
new Car().run2(); //null...0。
*/
//说明问题3:匿名对象作为实际参数传入方法可以提高代码的复用性
method(new Car());
/*
有名字的对象实现上述功能为
Car c1 = new Car();
method(c1);
*/
}
public static void method(Car cc) {
cc.color = "red";
cc.num = 8;
cc.run2();
}
}
class Car {
String color;
int num;
public void run1() {
System.out.println("车运行");
}
public void run2() {
System.out.println(color + "..." + num);
}
}
- D:说明问题2的内存图解
06.12_封装的概述
- A:封装概述
- 是指隐藏对象的属性和实现细节,仅对外提供公共的访问方式。
- B:封装好处
- 隐藏实现细节,提供公共的访问方式
- 提高了代码的复用性
- 提高安全性
- C:封装原则
- 将不需要对外提供的内容全都隐藏起来
- 把属性隐藏,提高公共方法对齐访问
06.13_private关键字的概述和特点
- A:人类赋值年龄的问题
class Demo1_Person {
public static void main(String[] args) {
Person p1 = new Person();
p1.name = "张三";
p1.age = -17;
p1.speak();
}
}
class Person {
String name; //姓名
int age; //年龄
public void speak() {
System.out.println(name + "..." + age);
}
}
上述程序段的不合理之处在于:人的年龄不可能为负数,所以,这就造成了数据安全性的问题。
在int age前面加上private,这样在Person类外就不可访问,age的值就修改不了。
-
B:private关键字特点
- 是一个权限修饰符
- 可以修饰成员变量和成员方法
- 被其修饰的成员只能在本类中被访问
-
C:那么对于被private修饰的成员,在类外怎么访问呢?
-
提供对应的getXXX()和setXXX()方法
-
程序段
class Demo1_Person { public static void main(String[] args) { Person p1 = new Person(); p1.name = "张三"; p1.setAge(-17); System.out.println(p1.getAge()); } } class Person { String name; //姓名 private int age; //年龄 public void setAge(int a) { //设置年龄 if (a > 0 && a < 200) { //在setAge里保证Age数据的安全性 age = a; }else { System.out.println("请回火星吧,地球不适合你"); } } public int getAge() { //获取年龄 return age; } public void speak() { System.out.println(name + "..." + age); } }
-
-
D:A与C的不同之处
- 加了private后,需要提供setXXX和getXXX方法。那么,我们就可以在setXXX和getXXX方法里保证数据的安全性
- private仅仅是封装的一种体现形式,不能说封装就是私有。
06.14_this关键字的概述和应用
- A:this关键字的特点
- 代表当前对象的引用
- B:案例演示
class Demo1_This {
public static void main(String[] args) {
Person p1 = new Person();
p1.setName("张三");
p1.setAge(23);
System.out.println(p1.getName() + "..." + p1.getAge());
}
}
class Person {
private String name; //姓名
private int age; //年龄
public void setAge(int a) { //设置年龄
if (a > 0 && a < 200) {
age = a;
}else {
System.out.println("请回火星吧,地球不适合你");
}
}
public int getAge() { //获取年龄
return age;
}
public void setName(String n) {
name = n;
}
public String getName() {
return name;
}
public void speak() {
System.out.println(name + "..." + age);
}
}
以上这段程序的输出就是 * 张三…23*,这是没有问题的。但如果改成如下的程序段,
class Demo1_This {
public static void main(String[] args) {
Person p1 = new Person();
p1.setName("张三");
p1.setAge(23);
System.out.println(p1.getName() + "..." + p1.getAge());
}
}
class Person {
private String name; //姓名
private int age; //年龄
public void setAge(int age) { //设置年龄
if (age > 0 && age < 200) {
age = age;
}else {
System.out.println("请回火星吧,地球不适合你");
}
}
public int getAge() { //获取年龄
return age;
}
public void setName(String name) {
name = name;
}
public String getName() {
return name;
}
public void speak() {
System.out.println(name + "..." + age);
}
}
上面的程序段输出就是 *null…0 *。为什么呢?因为就近原则,即当成员变量与局部变量重名时,方法里的操作会就近使用。那么上面程序段就没有起到对成员变量赋值的作用,所以输出的是默认初始化值。
那么造成上面描述的问题的关键:就是如何区分成员变量与局部变量。这就要用到this关键字。
- C:this关键字作用
-
用来区分成员变量与局部变量重名。
-
程序段
class Demo1_This { public static void main(String[] args) { Person p1 = new Person(); p1.setName("张三"); p1.setAge(23); System.out.println(p1.getName() + "..." + p1.getAge()); } } class Person { private String name; //姓名 private int age; //年龄 public void setAge(int age) { //设置年龄 if (age > 0 && age < 200) { this.age = age; }else { System.out.println("请回火星吧,地球不适合你"); } } public int getAge() { //获取年龄 return age; } public void setName(String name) { this.name = name; } public String getName() { return name; } public void speak() { System.out.println(name + "..." + age); } }
-
son {
private String name; //姓名
private int age; //年龄
public void setAge(int age) { //设置年龄
if (age > 0 && age < 200) {
this.age = age;
}else {
System.out.println("请回火星吧,地球不适合你");
}
}
public int getAge() { //获取年龄
return age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void speak() {
System.out.println(name + "..." + age);
}
}
```
上面程序段的输出 张三…23。说明this起到了区分作用。其实这里的this记录的就是p1的地址值。