面向对象的三大特征:封装(Encapsulation)、继承(Inheritance)和多态(Polymorphism)。
一、封装(Encapsulation)
封装:将类的某些信息隐藏在类的内部,不允许外部程序访问,而是通过该类提供的公共方法来实现对隐藏信息的操作和访问。
封装的目的是:增强安全性和简化编程,使用者不必了解具体的实现细节,而只是要通过外部接口,以特定的访问权限来使用类的成员。
封装的基本要求是:把所有的属性私有化,对每个属性提供getter和setter方法,如果有一个带参的构造函数的话,那一定要写一个不带参的构造函数。在开发的时候经常要对已经编写的类进行测试,所以在有的时候还有重写toString方法,但这不是必须的。
1、四大访问权限控制修饰符:这四个修饰符都可以修饰变量和方法
1)private(类访问权限):使用 private 修饰的成员(字段,方法,构造器),就只能在当前类中范围.
2)什么都不写(缺省的/包访问权限):此时只有在同一个包中,才可以访问的到,若不在同包中,不能访问.
3)protected(子类访问权限):即使父类和子类不在同一个包中,也可以访问.
4)public(公共访问权限):在任何地方都可以访问到.
public class Student {
private String name;
private int 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;
}
public static void main(String[] args) {
Student stu = new Student();
stu.setName("李四");
stu.setAge(17);
System.out.println(stu.getName() + "--" + stu.getAge()); //李四--17
}
}
2、继承(Inheritance)
继承是类与类的关系,在Java中类的继承,只允许单继承,不支持多继承。 一个类,只能有一个直接的父类,但是允许多重继承.。
在Java中,即使A类没有显示的去继承B类,此时A类的父类是Object.推论:任何类(除了Object),都有一个父类.
继承是一种“(is-a)”的关系,就是从一般到特殊的过程。 构造方法不能被继承,因为构造方法的名称与类名相同。
继承的好处:继承是面向对象实现软件复用的重要手段,即子类对父类代码的复用
子类可以继承到父类哪些成员:
1)若父类成员使用public或者protected修饰,子类可以继承.
2)若父类成员使用包访问权限(不写):
若子类和父类在同包中,可以继承.
若子类和父类不在同包中,则不能继承.
3)若父类成员使用private修饰,子类不能继承.
4)父类的构造器,子类也继承不到.
继承的语法规则:修饰符 class 子类 extends 父类
public class Human {
public void sleep(){
System.out.println("睡觉。。。");
}
}
public class Student extends Human{
private String name;
private int age;
public static void main(String[] args) {
Student stu = new Student();
stu.sleep(); // 睡觉。。。
}
}
方法覆盖(Override)
当父类中的某一行为特征不适应子类的自身特征时,可采用方法的覆盖,即子类包含与父类同名方法,并重新编写方法体。
方法覆盖(Override):存在继承关系,强调的是父类和子类的方法.
方法覆盖遵循原则:"一同两小一大".
一同:方法的名称要相同.
两小:
1)子类方法的返回类型应该小于等于父类方法的返回类型.
子类方法的返回类型要么等于父类方法的返回类型,要么是父类方法返回类型的子类.
2))子类方法声明抛出的异常应该小于等于父类方法抛出的异常
一大:子类方法的访问修饰符,必须大于等于父类方法的访问修饰符.
注意:方法覆盖(复写,覆写),只能对方法有效,类,构造器,字段没有覆盖的概念.
判断方法是否是覆盖的准则:
在Java5开始,其中有一个注解:@Override.用于帖子子类方法上,用于判断当前方法是否是覆盖方法.
子类的创建过程:
1)创建子类对象时,会调用子类的构造器,而在调用子类构造器之前,会先调用父类的构造器.
2)先对父类做初始化,再对子类做初始化.
public class Student extends Human{
private String name;
private int age;
@Override
public void sleep() {
System.out.println("student sleep...");
}
public static void main(String[] args) {
Student stu = new Student();
stu.sleep(); // student sleep...
}
}
this关键字与super关键字区别
this关键字:代表当前对象,哪一个对象调用了this所在的方法,该方法中的this就指那个对象
super关键字:代表当前对象的父类对象
this关键字的应用场景:
1)解决成员变量和局部变量之间的二义性,必须使用;(setter方法)
2)同一个类中多个实例方法间互调。
3)将当前对象作为参数传递给另一个方法;
4)将当前对象作为方法的返回值(链式方法编程);
5)构造器重载的互调,this([参数])必须写在构造方法第一行;this();//表示调用无参数构造器.
super关键字的应用场景:
1)在子类方法中,调用父类被覆盖掉的方法,如:super.sleep();不能省略.
2)在子类方法中,返回父类被隐藏掉的成员变量. (极少使用)
3)在子类的构造器中,调用父类的构造器:super([参数]);
隐藏/遮蔽:把之前的给挡住了,有三种情况:1)局部变量和成员变量同名,局部变量隐藏成员变量,使用this关键字解决:
2)在满足继承条件之下(少见):
子类存在和父类同名的成员变量,子类变量隐藏了父类变量,使用super关键字解决.
3)在满足继承条件之下(少见):
子类存在和父类相同的静态方法.-->静态方法不存在覆盖.
public class Student extends Human{
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
@Override
public void sleep() {
super.sleep();
System.out.println("student sleep...");
}
public static void main(String[] args) {
Student stu = new Student();
stu.sleep();
// 睡觉。。。
// student sleep...
}
}
3、多态(Polymorphism)
多态:子类对象可以直接赋给父类变量,但运行时依然表现出子类的行为特征。
多态的作用:
当把不同的子类对象都当作父类类型来看,可以屏蔽不同子类对象之间的实现差异,从而写出通用的代码达到通用编程,以适应需求的不断变化。
多态的前提:
A:要有继承/实现关系
B:要有方法覆盖/重写
C:要有父类引用指向子类的对象。 父 f = new 子();
多态中成员访问的特点分别是什么?
多态实现的机制是: 动态绑定机制: 属性看声明(左边),方法看对象(右边).
成员变量: 编译看左边(父类),运行看左边(父类)
成员方法: 编译看左边(父类),运行看右边(子类)。
静态方法:编译看左边(父类),运行看左边(父类)。静态方法属于隐藏,不属于方法覆盖
只有非静态的成员方法,编译看左边,运行看右边
引用类型转换:
自动类型转换:把子类对象赋给父类变量(多态形式).
强制类型转换:Student stu = (Student) human;
instanceof 运算符:判断某一对象是否是某一种类型
语法格式:boolean result = 对象 instanceof 类名/类型;
public class Student extends Human{
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
@Override
public void sleep() {
super.sleep();
System.out.println("student sleep...");
}
public static void main(String[] args) {
Human human = new Student();
human.sleep();
boolean result = human instanceof Student;
if(result){
Student stu = (Student) human;
System.out.println(true);
}else{
System.out.println(false);
}
// 睡觉。。。
// student sleep...
// true
}
}
ends ~