课前概括:
面向对象
- 面向对象概述:
Java语言是一种面向对象的程序设计语言,而面向对象思想是一种程序设计思想,我们在面向对象思想的指引下,使用Java语言去设计、开发计算机程序。
面向对象的对象泛指现实中一切事物,每种事物都具备自己的属性和行为。面向对象思想就是在计算机程序设计过程中,参照现实中事物,将事物的属性特征、行为特征抽象出来,描述成计算机事件的设计思想。
面向过程 : 有一个需求要实现, 思考我怎么去实现, 强调的是做事的步骤,需要自己一步一步的去操作实现。
面向对象区别于面向过程思想,有一个需求要实现,思考谁能帮我实现, 强调的是通过调用对象的行为来实现功能,而不是自己一步一步的去操作实现。
-
举例:
洗衣服:
面向过程:把衣服脱下来–>找一个盆–>放点洗衣粉–>加点水–>浸泡10分钟–>揉一揉–>清洗衣服–>拧干–>晾起来面向对象:把衣服脱下来–>打开全自动洗衣机–>扔衣服–>按钮–>晾起来
面向过程是面向对象的基础, 面向对象基于面向过程实现的, 但是代码思想层面上, 面向对象时更高级的设计思想
区别:
面向过程:强调步骤。
面向对象:强调对象,这里的对象就是洗衣机。
-
面向对象的好处:
1、更符合人类的做事思想
2、复杂的事情简单化
3、由执行者变为指挥者 -
面向对象的特征:
1、封装
2、继承
3、多态
类和对象
- 类的概述
类是一组相关属性和行为的集合,可以看成是一类事物的模板,使用事物的属性特征和行为特征来描述该类事物
属性 : 描述一类事物的特征
行为 : 描述该事物能够做什么(方法)
举例: 描述猫
属性: 名字、体重、年龄、颜色。
行为: 走、跑、叫, 吃饭, 睡觉…
- 对象的概述
java是一类事物的具体体现。
对象是类的一个实例,必然具备该类事物的属性和行为。
举例: 猫
属性:lili、3kg、2岁、黄色。
行为:溜墙根走、蹦跶的跑、喵喵叫。
- 类与对象的关系
- 类是对一类事物的描述,是抽象的。
- 对象是一类事物的实例,是具体的。
- 类是对象的模板,对象是类的实体。
知识点:
一. 面向对象
(一) 类的定义
-
概述: Java中类的定义其实就是使用代码对事物描述的一种体现,使用关键字class定义, 具有固定的格式
-
格式:
修饰符 class 类名 { 成员变量1; 成员变量2; ...... 成员方法1; 成员方法2; ...... }
-
类中的内容:
属性:
对事物特征的描述体, java代码中使用变量体现, 被称之为成员变量或全局变量。
【和以前定义变量几乎是一样的。只不过位置发生了改变。在类中,方法外。】
行为:
对事物功能【能干什么】的描述, java代码中使用方法体现,被称之为成员方法。
【和以前定义方法几乎是一样的。只不过把static去掉,static的作用在后面课程中再详细讲解】
(二) 对象的使用
-
创建对象:
类名 对象名 = new 类名(); 类本身就是一种引用数据类型
-
成员的使用:
获取成员变量值: 变量 = 对象名.成员变量; 修改成员变量值: 对象名.成员变量 = 新值; 访问成员方法: 对象名.成员方法(实参);
-
成员变量的默认值
(三) 对象内存图
-
一个对象创建的内存图
-
两个对象的内存图
-
两个对象引用指向同一个内存空间
public class Demo1 {
public static void main(String[] args) {
//创建Person对象
//per是引用类型的变量名, 类类型的变量名
Person per = new Person();
System.out.println(per); //Person@1540e19d
System.out.println(per.name); //null
System.out.println(per.age); //0
per.name="小红";
per.info();
//Person类是一个模板,根据模板理论上可以创建n个对象,没上限。
//但是实际有上限,因为对象需要在内存中存储。内存是有大小的。
//每创建一个对象,每个对象都有自己的属性信息。
Person per1 = new Person();
System.out.println(per1.name);
System.out.println(per1.age);
per1.name="小刚";
per1.info();
Person per2 = per; //两个引用指向同一个容器
System.out.println(per2.name); //小红
per = null; //断开与容器间的指向关系
per1 = null;
per2 = null;
// System.out.println(per.name);
// Person per3 = null;
// per3.name = "---"; //空指针异常
}
}
/*
* 描述 Person 事物
* 属性: name
* age
*
* 方法: 输出属性信息
* */
class Person{
String name;
int age;
public void info(){
System.out.println(name+"...."+age);
}
}
public class Demo2 {
public static void main(String[] args) {
Student stu = new Student();
stu.info();
Student stu1 = new Student();
stu1.info();
/*
* Student stu = new Student();初始化过程是:
* 1.加载student.class文件到方法区
* 2.栈中分配stu的引用变量
* 3.在堆中开辟空间,分配引用地址值
* 4.进行属性的默认初始化
* 5.如果属性有初始化值,进行显示初始化,通常此步骤省略
* 6.将引用地址值赋值给stu引用变量,stu指向堆中该容器。
* */
}
}
/*
* 描述学生这类事物
* */
class Student{
String name = "小明";
int age;
public void info(){
System.out.println(name+"..."+age);
}
}
public class Demo3 {
public static void main(String[] args) {
Cat cat = new Cat();
cat.name = "花花";
System.out.println(cat.name);
}
}
/*
* 描述事物类,是否可以写main方法
* 可以有。但是通常不会写。
* 如果写,也是用来做测试,测试当前类中的封装的方法是否有问题。
* */
class Cat{
String name;
String color;
/*public static void main(String[] args) {
Cat cat = new Cat();
cat.name = "花花";
System.out.println(cat.name);
}*/
}
import java.util.Scanner;
public class Demo4 {
public static void main(String[] args) {
//创建元素类型为 persons的数组
Persons[] pers = new Persons[3];
//创建扫描器对象
Scanner sc = new Scanner(System.in);
//创建对象,并将对现个存储到数组中,并且给每个对象的属性通过键盘录入的方式赋值
for (int i = 0; i <pers.length; i++){
pers[i] = new Persons();
System.out.println("请输入姓名:");
pers[i].name = sc.next();
System.out.println("请输入年龄:");
pers[i].age = sc.nextInt();
}
//遍历
for (Persons p:pers)
System.out.println(p.getInfo());
}
}
/* 定义一个Person类,属性为:name和age; 方法有:返回属性信息方法。可以自行添加
创建一个用于存储Person类型的元素的数组,存储3个Person对象,
通过键盘录入的方式为对象的属性进行赋值。
遍历数组,打印出对象的属性信息。
*/
class Persons{
String name;
int age;
public String getInfo(){
return name+"----"+age;
}
}
(四) 匿名对象的使用
- 概述 : 没有名字的对象
- 格式 : new 类名(实参);
- 特点 : 只能使用一次
- 使用场景:
(1) 如果某个对象在创建之后,其方法只调用一次,那么就可以使用匿名对象来调用。这种写法会节省一些内存空间。
(2) 可以作为某个方法的实际参数。在被调用的方法中,这个对象是有引用的对象,不是匿名对象。
(3) 可以作为某个方法的返回值。这种调用形式,在被调用方法中,这个对象是匿名对象,但是在调用者,这个对象可能不是匿名对象。
. 优势: 在内存中存在时间短, 相对节省内存
public class Demo5 {
public static void main(String[] args) {
/*
* 匿名对象:
* 字面理解:对象没有名字
* 实际指的是:没有使用引用变量来指向对象。
* 格式: new 类名();
* 是一个简写格式。
* */
//完整写法
Person1 p = new Person1(); //因为有p引用,所以是有名对象。
//简写写法
new Person1(); //没有引用,匿名对象。
p.name = "小红";
p.say();
p.name = "小丽";
p.say();
//对于有名对象来说,类中的成员可以多次进行访问操作。
//匿名对象---操作属性 ,无论获取还是赋值都只能操作其中一个属性,操作后对象成为垃圾,等待被回收。
new Person1().name = "小白";
String username = new Person1().name;
//匿名对象---操作方法,只能调用一次,方法可以执行。方法执行后,对象成为垃圾,等待被回收。
new Person1().say();
//调用test方法
test(new Person1());
//调用test方法
Person1 per = test(); //返回的对象不是匿名的
System.out.println(test()); //返回的对象是匿名的
}
//匿名对象---作为返回值
public static Person1 test(){
//return new Person1();
Person1 p = new Person1();
return p;
}
//匿名对象---作为参数
public static void test(Person1 p){ // p = new person1(); 传参 p指向了匿名对象,所以此时的对象不是垃圾,因为有引用指向。
p.say();
}
}
class Person1{
String name;
int age;
public void say(){
System.out.println(name+"..."+age);
}
public void eat(){
System.out.println(name+"在吃");
}
}
(五) 成员变量和局部变量的区别
-
定义位置不同
成员变量: 类中方法外
局部变量:方法中 -
内存位置不同
成员变量:堆空间
局部变量:栈空间
• -
生命周期不同
成员变量:随着类对象的创建而创建,随着对象的消失而消失
局部变量:随着所在方法的执行而创建,随着方法的执行完毕而消失
• -
默认值不同: JVM虚拟机赋初值
成员变量:有默认值
局部变量:没有默认值
二. 封装
(一) 封装的概述
-
面向对象编程语言是对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界无法直接操作和修改。封装可以被认为是一个保护屏障,防止该类的代码和数据被其他类随意访问。要访问该类的数据,必须通过指定的方式。适当的封装可以让代码更容易理解与维护,也加强了代码的安全性
-
封装的原则:
- 将属性隐藏起来
- 使用时对外提供公共的访问方式
-
封装的好处:
- 隐藏了事物的实现细节
- 提高了代码的复用性
- 提高了代码的安全性
(二) private关键字
- private : 是一个关键字, 私有的意思, 是一个修饰符
- 修饰内容:
- 修饰成员变量(最常用)
- 修饰成员方法
- 修饰构造方法
- 修饰内部类
- 修饰效果:
只能在本类中使用,其他所有外类不能直接使用private修饰的成员
(三) getter&setter
- getter方法和setter方法是对属性封装后对外提供的统一访问属性的访问方式
作用:
getXxx():获取封装属性的值
setXxx(参数列表):修改封装属性的值
注意:Xxx代表的是封装属性的名称,首字母大写
(四) 封装优化
把封装后对相关操作的修改操作称之为封装的优化
4.1变量的访问原则
- 总体原则:就近访问原则
- 就近访问:
当在访问某个变量名称的时候,会先寻找最近的该变量名称的定义,如果寻找到了,就使用该变量,如果没有找到,才到更远的位置寻找该变量名称的定义。
比如:
当局部变量和成员变量同名的时候,一定是先使用局部位置定义的变量
4.2 this关键字
- this关键字含义:代表所在类的当前对象的引用(地址值),即对象自己的引用。
- this关键字作用:
(1) 当成员变量和局部变量重名, 带有this关键字的变量表示成员变量的使用
(2) 开发中, setter方法中局部变量和成员变量同名赋值失败的问题就可以使用this关键字来解决
(3) 哪个对象调用了带有this关键字的方法, this关键字就表示哪个对象本身
import javax.sound.midi.Soundbank;
public class Demo6 {
public static void main(String[] args) {
Person2 p = new Person2();
/* p.name = "#$%#$%#%";
p.age = -19;
p.say();
*/
//通过方法进行属性的操作
// p.setAge(18);
// p.setName("张三");
// System.out.println(p.getAge());
// System.out.println(p.getName());
// System.out.println(p);
Person2 p2 = new Person2();
p2.setAge(20);
p2.setName("小刚");
p2.say();
}
}
/*
封装:
将对象的属性或行为隐藏起来,对外提供公共的访问方式。
隐藏:使用private修饰。 公共的访问方式: 使用public修饰的方法。
* private :
* 关键字: 私有的意思,修饰类中的成员(变量和方法),修改后称为叫做:私有成员。
* 只能在当前类中去使用,其他类不可以访问。
* 属性即变量,有获取和赋值两个操作
* 在类中,就定义两个方法,间接操作属性
方法名:
赋值: set属性名 setXxx
取值: get属性名 getXxx
jvm执行代码中的变量时,有一个就近原则,方法内部有直接使用,没有才会去成员位置上找。
成员位置和局部位置的变量名重名问题解决:
使用关键字:this。
this:
当前类对象的引用。 类似于: person p = new person(), 中的p。
谁调用this所在的方法,那么this就代表谁。
* */
class Person2{
private String name;
private int age;
public void setName(String name){
this.name = name; //上方调用了这里的那个变量是this代表的变量名
}
public String getName(){
return name;
}
//赋值--age
public void setAge(int age){ //age = 18
System.out.println(this+"....");
if(age > 0 && age < 150)
this.age = age; //参数上的age 赋值给 对象的age属性
else
System.out.println("年龄需在0-150之间");
}
//获取--age
public int getAge(){
return age;
}
public void say(){
System.out.println(this.name+"....."+this.age);//没有重复情况,this可以省略
this.show();
}
public void show(){
System.out.println(name+"---show");
}
}
(五) 构造方法
-
构造方法概述: 当一个对象被创建时,构造方法用来初始化该对象,给对象的成员变量赋初始值。构造方法有自己独有的方法格式。
-
构造方法分类: 有参构造, 无参构造
-
构造方法定义格式:
修饰符 构造方法名(参数列表){ // 方法体,主要就是给对象中成员变量进行赋值 }
-
构造方法特点:
- 方法名必须和类名一致
- 没有返回值类型,连void都不写
- 默认被jvm调用使用, 构造方法调用时机:
在创建对象时, JVM虚拟机主动调用,并且创建一次对象, 构造方法只调用一次, 构造方法无法手动通过对象名调用
-
注意事项:
- 如果不提供构造方法,系统会给出无参数构造方法。
- 如果提供了构造方法,系统将不再提供无参数构造方法。
- 构造方法是可以重载的,既可以定义参数,也可以不定义参数。
如果代码中定义了空参数构造, 也同时定义了有参数构造, 那么创建对象时, 可以从多个构造中选择其中任意一个调用即可
public Person3(int age){
this.age = age;
}
public Person3(String name,int age){
this(age);
this.name = name;
}
public void show(){
System.out.println("show");
}
}
/*
修饰类中的成员的修饰符:
public protected 默认 private
* this有两个作用:
* 1.解决重名问题
* 2.调用重载的构造方法
*
* 构造方法:
* 也是方法,只不过比较特殊。
* 普通方法:
* 修饰符 返回值类型 方法名(参数列表){
* 。。。
* return 返回值;
* }
* 构造方法:
* 修饰符 方法名(参数列表){
* ...
* }
* 特点:
* 1.没有返回值类型,即void也不能写
* 2.方法名就是类名,与类名相同
* 3.没有return 返回值语句,可以有 : return;
4.支持方法重载
当类中没有定义构造方法,那么系统会自动提供一个构造方法,格式为 public 类名(){},以便能创建对象。
如果类中定义了构造方法,那么系统不再提供,必须以定义的构造方法为准。
对象创建一次,构造方法对于该对象来说也只执行1次。
什么时候执行构造方法?
创建对象时,根据关键字new 后边的代码形式,自动调用与之匹配的构造方法。
作用是:
主要用于给对象的属性进行初始化。
构造方法可以给属性进行赋值,set方法也是属性赋值,那么还需要set方法?
需要。因为构造方法仅仅是在对象创建的时候执行,set方法是对象创建后可以多次调用。
构造方法中能调用其他普通方法吗? 可以
普通方法中可以调用构造方法吗?不可以。
重载构造方法间的调用:
this(参数列表);
注意:该语句必须放在构造方法的第一行
无论类中有几个重载形式的构造方法,至少有一个构造方法的第一行不能是 this(参数); 语句。
Person p = new Person("张三",20);实例化过程是:
* 1.加载Person.class文件到方法区
* 2.栈中分配 p 的引用变量
* 3.在堆中开辟空间,分配引用地址值
* 4.进行属性的默认初始化
* 5.如果属性有初始化值,进行显示初始化,通常此步骤省略
* 6.进行构造方法初始化
* 7.将引用地址值赋值给 p 引用变量,p指向堆中该容器。
* */
(六) 标准JavaBean
JavaBean是Java语言编写类的一种标准规范。符合JavaBean 的类,要求
-
类必须是具体的和公共的
-
所有属性使用private修饰
-
提供用来操作成员变量的set 和get 方法
-
并且具有无参数的构造方法(建议有)
格式:
public class ClassName{ //成员变量【必须封装】 //构造方法 //无参构造方法【必须】 //有参构造方法【建议】 //成员方法 //getXxx() //setXxx() }