文章目录
面向过程思想
面向过程OPP(Oriented Process Programmint):
-
面向过程关注的是要完成的事情本身,解决问题一共分为几步,逐步完成每一个环节,最终解决问题。
-
例如:把大象放进冰箱
-
第一步:把冰箱门打开
-
第二步:把大象放进去
-
第三步:把冰箱门关上
-
面向对象思想
面向对象OOP(Object-Oriented programmint):
-
面向对象和面向过程同样都是完成具体的事情,但是关注的重心不是怎么一步步完成而是在整个事情进行中,都有哪些对象参与,这些参与的对象需要具有什么样的特征和行为,也就是说关注的是类的设计,面向对象的核心是如何设计这些对象。
-
例如:把大象装进冰箱
-
需要有冰箱 需要有大象 需要有人
-
public class 冰箱(){此处省略属性和方法}
-
public class 大象(){此处省略属性和方法}
-
public class 人(){此处省略属性和方法}
-
public class Test(){main(此处省略实例化对象和调用方法)}
-
类
类就是对事物的抽象和提炼,可以把共性的信息提炼出来,做成一个模板,把提炼的特征变成类的属性,把提炼的行为变成类的方法。
一个类包含2部分内容:特征(属性)、行为(方法)
定义类的语法格式
修饰符 class 类名{
修饰符 类型 属性名 [= 初始值];
…
修饰符 返回值类型 方法名(参数列表){
方法体;
}
}
示例
public class A {
private String name = "bennett";
public A() {}
public A(String name) {
this.name = name;
}
}
实例化对象
对象是类的具体实例,想要使用对象,第一件事就是实例化对象也叫作创建对象。有了类之后,我们就可以创建对象了。
类型(类名) 变量名 = new 类型() ;
// 以上面的A类示例
A a = new A();
每个类中都有无参的构造方法(自己不写,系统隐式的写一个无参的构造方法),下面的实例化对象实则就是调用无参的或者有参的构造方法。
使用面向过程表示一个完整的事物比较麻烦,而且无法给这个事物添加功能
变量的作用域
变量的作用域就是变量起作用的区域。
局部变量
在 方法内定义的变量称为局部变量。
- 作用域:从定义的那一行开始,一直到所在的方法结束。
块变量
在一对{}
里面定义的变量。
- 作用域:从定义的那一行开始,一直到所在的大括号结束。
类的面向对象的三大特征
封装
隐藏内部细节,对外提供访问的接口,这里的接口是指广义的接口,提供访问的方式。
封装包含以下几个维度:
对属性的封装
具体做法是把属性私有化,用private修饰。
提供getter和setter方法,对属性封装能保证属性的安全性,不容易出现脏数据,也就是不合法的数据
对方法的封装
对具体功能实现的封装,隐藏实现细节,对外提供调用方式。
具体做法是在类中定义一个用public修饰的方法,调用的时候直接使用对象名.方法名就可以了
对类的封装
把属性和行为封装起来,使用的时候实例化对象,再调用相关方法。
继承
子类继承父类的属性和方法,当两个对象的特征和行为完全相同的时候,我们采用不同的类创建不同的对象即可,但是如果两个对象的行为和特征很相似但又不是完全相似的时候,我们就可以采用继承的方式来优化类的定义,一般相似的两个类会存在从属关系,比较模糊和抽象的是父类,比较具体的是子类,父类也叫作超类或者基类,子类是通过父类延伸或者派生出来的,所以也叫作派生类
示例
类的继承通过关键字extends
来完成
public class Student extends Person {
private String name;
private int age;
}
class Person {
private String sex;
public String food;
public void eat () {
System.out.println("eat" + food);
}
}
class Test {
public static void main(String[] args) {
Student stu = new Student();
// 因为继承,所以student对象也可以设置food这个属性
stu.food = "麻辣烫";
// 同样可以调用父类里public类型的方法
stu.eat();
}
}
关于继承,子类可以在父类的基础上增加属性或方法,子类还可以重写override父类的方法。
- 子类从父类那里继承了所有的非私有的属性和方法,但本质上私有的属性和方法也都继承了,只是不能直接访问。
- 父类的构造方法是继承不了的,因为构造方法的特点是方法名必须与类名相同,但是你可以调用父类的构造方法。
super
调用父类的构造方法使用super()
,super(参数列表)
。子类的构造方法会默认调用父类的构造方法,而且是在子类构造函数的第一行调用父类的构造方法。
super()必须写在第一行,否则会报错,或者直接不写,系统默认已经调用。
-
如果父类里没有写任何构造方法,子类会调用父类里系统默认生成的无参的构造方法。
-
如果父类里写了无参的构造方法,子类会调用你写的无参的构造方法。
-
如果父类里写了有参的构造方法,没有写无参的构造方法,子类只能调用有参的构造方法。
-
一个类中可以有无数个构造方法,这个构造方法的第一行必须调用自己的其他构造方法或者父类的构造方法。
-
一个类中如果有多个构造方法,往往用参数少的构造方法调用参数多的构造方法,这样一来,无论外界如何实例化对象,必然会执行这个参数多的构造方法。
我们可以把公共代码多的放在参数多的构造方法里,外界在实例化对象的时候会调用某个构造方法,这个构造方法会调用本类参数最多的构造方法,这个参数最多的构造方法会调用父类里参数最多的构造方法,父类的构造方法会调用父类参数最多的构造方法,以此类推,直到调用到根类。
**继承环节中,某个类想要初始化代码,写在参数最多的构造方法中即可。**实例化的时候视情况而定传递参数
多态
从字面意思理解,同一个方法有多种不同的实现。父类引用指向子类,相同的行为有不同的表现
例如:睡觉(public void sleep(){ }
)
- 狗:趴着睡
- 猫:卧着睡
- 人:各种姿势睡
- 马:站着睡
在讲多态之前,首先要了解对象方法和类方法的区别:
类方法(由static修饰的方法)里不能出现实例变量(对象变量)!因为类方法可以在不创建对象的情况下由类名去调用。这个时候就会出现问题,对象不存在,你在为对象的某个属性赋值。又或者你有很多对象,你究竟在为哪个对象的属性赋值?
-
引用类型:变量的类型。
-
对象类型:通过new创建对象时的类型,new后面的类名。
-
对象:对象是通过类这个模板生成的一个具体实例。对象存放在堆区,对象是通过new关键字创建的。
-
引用:代表所指向对象的变量。引用的本质是所指向的对象的首地址。引用是存放在栈或堆。系统会在编译期检查类型时候能调用某法或某属性。运行期,运行期运行方法的时候,只关注你对象类而不关注你引用类型。
向上转型
比如三个类Teacher、Person、Students,老师和学生都继承自Person类。
子类往父类转。系统自动完成,父类型变量可以保存子类型对象。
Person p1 = new Teacher("name1",18);
Person p2 = new Student("name2",25);
向上转型的问题:
- 范围缩小,子类特有的方法或者属性,父类没有。
- 只考虑共性,不考虑特性。
- 向上转型是必定成功的。
向下转型
父类往子类转。需要强转转换。有可能失败,有可能成功。如果转后的引用类型与对象的实际类型一致,可以成功。
Person p4 = new Student("name3",21);
Student stu2 = (Student)p4;
stu2.study();
- 如果转后的引用类型与对象的实际类型不一致,会失败。
Person p3 = new Person("name4",22);
// 下面的类型匹配可以强转成功
Student stu = (Student)p3;
stu.study();
// ----------华丽的分割线-----------
// 下面的类型不匹配会强转失败
Person p5 = new Teacher("name5",40);
Student stu3 = (Student)p5;
stu3.study();
向下转型的问题:
-
范围扩大,对象范围小,引用范围大。
-
引用类型是子类型,对象类型是父类型。
instanceof
instanceof是一个运算符。判断某个对象是否属于某一类,判断某个对象是不是某个类的实例。一般 instanceof 出现在if语句中。
先判断引用是不是某种类型,如果是,我再强转。
boolean a = stu10 instanceof Student;//------->true
boolean b = stu10 instanceof Person;// -------->true
boolean c = stu10 instanceof Object;// --------->true
boolean d = (Object)stu10 instanceof Teacher;// -------->false
在java里多态用于写抽象功能。提取共性,但是在运行的时候执行的又是特性(而不是共性)。 用的时候(编译期),把子类当父类看。无论你是Person还是Student还是Teacher 都当成Person来看待。(相当于只看了共性。)真正执行方法的时候(运行期),执行的是子类方法。
使用前提
想要在java里面实现多态有几个前提:
- 必须存在继承关系。
- 子类必须重写父类的方法。
- 用父类引用指向子类对象,执行的是子类的实现
示例
public class Person {
public void play(String name) {
System.out.println("person玩" + name);
}
}
class Student extends Person {
@Override
public void play(String name) {
System.out.println("student不玩" + name);
}
}
class Teacher extends Person {
@Override
public void play(String name) {
System.out.println("teacher想玩" + name);
}
}
class Test {
public static void main(String[] args) {
String name = "篮球";
Person person = new Person();
person.play(name);
Person student = new Student();
student.play(name);
Person teacher = new Teacher();
}
}
结果便是下面这样,这就是多态的思想。利用一个共有的类型就可以接收它下面所有的子类型,达到父类引用子类的简化代码的作用。
person玩篮球
student不玩篮球
teacher想玩篮球
-------------------------------------返回->JavaSE系列<-目录-------------------------------------