JAVA中面向对象的三大特征:继承性、封装性、多态性。
可以实现现有类的所有功能,并且在无需重新编写原有类代码的情况下进行功能上的扩展。
1. 继承的特点
a. 继承的语法以及继承的目的(扩展已有类的功能,使代码重用)
b. 子类对象的实例化流程:不管如何操作,一定要先实例化父类对象。
c. 不允许多重继承,只允许多层继承。
2. 继承的实现
在Java中,继承使用extends关键字来实现,定义的语法如下:
class 子类 extends 父类
继承定义的说明:子类在一些书上也被称为派生类,父类也被称为超类。
例:继承的基本实现
//定义父类
class Person{
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;
}
}
//定义子类
class Student extends Person{
}
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.setName("Steven");
student.setAge(18);
System.out.println("姓名:"+student.getName()+
",年龄:"+student.getAge());
}
}
3. 继承的限制
子类对象在进行实例化前一定会首先实例化父类。
例:观察子类对象创建
class Person{
public Person(){
System.out.println("**Person类对象产生**");
}
}
class Student extends Person{
public Student(){
super() ; //此语句在无参时写于不写一样
System.out.println("**Student类对象产生**");
}
}
public class Test{
public static void main(String[] args) {
new Student();
}
}
4. 类的主要组成部分的子父类继承关系中的特点
4.1 成员变量
继承关系中同名的子类成员变量、局部变量、父类的成员变量这三者之间使用顺序:在具有相同变量名的这种情况下,不使用this、super等关键字进行调用时,即成员变量前什么都不写调用顺序按照由局部变量位置—当前类成员变量位置—父类成员变量位置依次进行查找变量,什么位置先有值,就会使用这个值。
调用方式:this,super。
4.2 成员方法
a. 继承中的成员方法
继承中的成员方法 使用顺序:当子类具有与父类同名成员方法时,进行调用过程中不使用this、super等关键字,即成员方法前什么都不写方法的有效顺序:当前类的成员方法—父类的成员方法子类中有方法实现,则按照子类的实现进行,若在子类中使用super调用了父类的方法,那么父类方法也要执行!但是默认成员方法内是没有super调用的。
b. 重写
• 定义:如果子类定义与父类完全相同(不算权限)的方法或者属性的操作。 c. 重写注意事项 • 父类中的私有方法不可以被重写; 4.3 构造方法 a. 构造方法三大特征 • 构造方法名称必须与类名称相同; 将客观事物封装成为抽象的类,每个类都有自己的属性与方法,并且类可以让自己的数据与方法只让可信的类或对象操作,对不可信的进行信息隐藏,即内部操作对外部不可见(保护性)。 1. 优点 • 将变化隔离; 2. 缺点 将变量等使用private修饰,或者封装进方法内,使其不能直接被访问,增加了访问步骤与难度。 3. 封装原则 a. 将不需要对外提供的内容都隐藏起来; 4. 封装的实现形式 4.1 属性私有化 格式:private 数据类型 变量名 = 属性值; 4.2 提供get/set方法 get格式: set格式: 一个类实例的相同方法在不同地情形下有不同的表现形式与多态机制,使得具有不同内部结构的对象可共享相同的外部接口。 1. 多态存在的前提 a.必须有子类和父类,具有继承或实现 2. 方法的多态性 a. 方法的重写 3. 对象的多态性 a. 向上转型(90%) 作用:用于参数统一; b. 向下转型(1%) 作用:父类需要调用子类扩充的方法; c. 注意 要发生向下转型,必须先发生向上转型(认爹); d.引用 instanceof 类 表示该引用是否能表示该类实例,返回boolean类型。
• 方法的重写:子类定义了与父类方法名称、参数列表、返回值完全相同的方法(被重写的方法不能拥有比父类更加严格的访问权限)。
• 判断调用的是子类方法或者父类方法:
- 看new在哪(当前使用的对象是通过哪个类new的);
- 调用的方法是否被子类重写,如果被重写,调用的一定是被重写后的方法。
- 权限比较:private
• 子类重写父类方法后,继续使用父类的方法时候,可以使用super调用;
• 重写时,子类的方法的访问权限要大于或者等于父类成员方法的访问权限;
• 静态方法只能被静态方法覆盖;
• 子类对于父类的功能有增强需求的时候,可以重写父类的方法以增强其功能。
范例:父类使用private定义的方法,子类中使用public覆写class Person{
public void fun(){
this.print();
}
//如果现在父类方法使用了private定义,那么就表示该方法只能被父类使用,子类无法使用。换言之,子类根本
//就不知道父类有这样的方法。
private void print(){
System.out.println("1.[Person]类的print方法");
}
}
class Student extends Person{
//这个时候该方法只是子类定义的新方法而已,并没有和父类的方法有任何关系。
public void print(){
System.out.println("2.[Student]类的print方法");
}
}
public class Test{
public static void main(String[] args) {
new Student().fun();
}
}
• 构造方法没有返回值类型声明;
• 每个类中一定至少存在一个构造方法,如果没有明确定义,系统会自动生成无参构造;若在中自定义了构造方法,则系统不再生成无参构造。
b. 构造方法重载
参数个数不同;
c. 类定义顺序
属性->构造方法->普通方法;
例:使用构造方法设置对象属性class People{
private String name;
private int age;
public People(String n,int i){
name = n ;
setAge(i);
}
public void setName(String n){
name = n ;
}
public String getName(){
return name;
}
public void setAge(int i){
if (i>0&&i<=200) {
age = i ;
}else {
age = 0 ;
}
}
public int getAge(){
return age;
}
public void getPersonInfo(){
System.out.println("姓名:"+name+",年龄:"+age);
}
}
public class Test{
public static void main(String[] args) {
People People = new People("张三",-200);
People.getPersonInfo();
}
}
二、封装性
• 便于使用;
• 提高重用性;
• 提高安全性。
b. 把属性都隐藏,提供公共方法对其访问。
给外界提供一个获取属性值的方式。public 数据类型 get + 属性名() {
return 属性名;
}
public void set + 属性名(数据类型 形参名){
this.属性名 = 形参名;
}
三、多态性
在Java中,多态的核心表现为方法的多态性和对象的多态性。
b.子类必须重写父类的方法
c.父类的引用变量指向子类的对象
同一个方法名称可以根据参数的类型或个数不同调用不同的方法体;
b. 方法的覆写
同一个父类的方法,可能根据实例化子类的不同也有不同的实现。
格式:父类 父类引用 = new 子类();
例:向上转型,参数统一化class Person {
public void print() {
System.out.println("Person类的print()!");
}
}
class Student extends Person {
public void print() {
System.out.println("Student类的print()!");
}
}
class Teacher extends Person {
public void print() {
System.out.println("Teacher类的print()!");
}
}
class Worker extends Person {
public void print() {
System.out.println("Worker类的print()!");
}
}
public class Test{
public static void main(String[] args) {
//向上转型
test(new Person());
test(new Student());
test(new Teacher());
test(new Worker());
}
//参数统一化
public static void test(Person per) {
per.print();
}
}
格式:子类 子类引用 = (子类)父类引用;
运行时异常:ClassCaseException,发生在两个不能强转的类之间。
例:先向上转型,再向下转型class Person{
public void print(){
System.out.println("1.我是爸爸!");
}
}
class Student extends Person{
public void print(){
System.out.println("2.我是儿子!");
}
public void fun(){
System.out.println("3.只有儿子有!");
}
}
public class Test1{
public static void main(String[] args) {
Person per = new Student();
per.print();
//这个时候父类能够调用的方法只能是本类定义好的方法;
//所以并没有Student类中的fun()方法,那么只能够进行向下转型处理;
Student stu = (Student) per;
stu.fun();
}
}
例:instanceof操作public class Test {
public static void main(String[] args) {
Person per = new Student();
System.out.println(per instanceof Person);
System.out.println(per instanceof Student);
//避免ClassCastException
if (per instanceof Student) {
Student stu = (Student) per ;
stu.fun();
}
}
}