final可以用来修饰:数据、方法和类
1、修饰数据:该数据一旦被赋值,将不能被改变
2、修饰方法:该方法不能被子类重写(覆盖),private修饰的方法隐含默认为final修饰
3、修饰类:该类不能被继承,final类中所有的方法都隐式指定为final
4、用于引用变量上,该引用变量的引用不能被改变
多态
什么是多态呢?
多态即一种事物多种形态,例如:一只二哈,我们可以叫其二哈,也可以叫其狗,也可以叫它小动物,比如水,可以有三种状态:液体,固体和气体
多态的定义:指同一操作作用于某一类对象,可以有不同的解释,产生不同的执行结果
实现多态的前提:
1.需要存在继承和实现关系
2.同样的方法调用而执行不同的操作,运行不同的代码(重写)
3.在运行时父类或者接口的引用变量可以引用其子类的对象
Animal a = new Dog();
Animal a : 为父类或者接口的引用变量
new Dog():子类的对象
下面举个例子:
根据人类的行为惯等,定义一个人的模板出来,即人类
package com.pyj.demo;
/**
* 定义一个人的类
* @author Pyj
*
*/
public class Person {
private String name;//姓名
private int age;//年龄
//一个无参的构造方法
public Person() {
}
//有参构造方法
public Person(String name, int age) {
this.name = name;
this.age = 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 void eat(){
System.out.println("吃饭");
}
//睡觉的方法
public void sleep(){
System.out.println("睡觉");
}
//输出个人的信息
public void show(){
System.out.println("姓名:"+name+",年龄:"+age);
}
}
package com.pyj.demo;
public class Student extends Person {
private int score;//分数
public Student() {
}
public Student(String name, int age,int score) {
super(name, age);
this.score = score;
}
//取值赋值方法
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
@Override
public void show() {
super.show();//使用父类的show方法
System.out.println("分数:"+score);
}
@Override
public void eat() {
//super.eat();//调用父类吃饭方法
System.out.println("学生吃营养餐");
}
@Override
public void sleep() {
super.sleep();//父类的睡觉方法
System.out.println("学生睡十个小时");
}
//学生自己的上课方法
public void attendClass(){
System.out.println("学生去上课");
}
}
下面我们用下面的例子来说明一下
package com.pyj.demo;
public class Test {
public static void main(String[] args) {
/*Student student = new Student("张三",17,90);
student.show();//调用学生的show方法
student.setScore(100);//为学生重新设置分数
student.attendClass();//学生自己的上课方法
student.eat();//学生的吃饭方法
student.sleep();//学生的睡觉方法
student.show();//学生的show方法*/
Person p = new Student("李四",20,88);
p.show();//调用show方法
//p.setScore(100);无法使用学生的设置分数的方法
//p.attendClass();无法使用学生的上课方法
p.eat();//吃饭方法
p.sleep();//睡觉方法
p.show();//show方法
}
}
下面我们来看test里面第一段注释代码,这段代码执行产生的结果,即Student student = new Student()一系列产生的结果
下面这个代码的图,为上面代码中没有注释的部分,即Person p = new Student();产生的结果
可以看出当我们使用的父类的引用变量时,会失去其子类的属性,子类特有方法,如果父类方法与子类方法名字一样,默认子类重写了父类的方法
总结了一下多态成员访问的特点:
1.父类的引用变量不能使用子类私有的方法,包括子类私有变量的取值赋值访法
2.当父类的变量调用方法时,如果这个方法被子类重写了,则调用被子类重写的方法,如果没有被重写,则会调用父类自身的方法。
3.子类可以访问父类的所有公开的方法以及属性
4.静态的方法或者变量存在方法区中,通过使用类名.属性 或者类名.方法来使用,哪个类有静态的变量或者方法,就用哪个类名
多态的好处和弊端:
好处:
1.多态解除了类型之间的耦合关系
2.多态的存在提高了程序的扩展性和后期的可维护性
弊端:
前期建立父类的引用虽然可以接收后期所有该类的子类对象。
但是只能使用父类中的功能,不能使用子类中的特有功能,
因为前期的程序无法知道后期的子类的特有内容的。
但是前期的程序可以使用子类覆盖了父类的方法的内容
多态的向上转型:
由子类转型成父类,在继承图上是向上移动的,所以一般称为向上转型,向上转型是从一个具体的类型向较通用类型的转换,所以总是安全的,也就是说子类是父类的一个超集。
缺陷:向上转型过程中,类或接口中唯一发生的事情就是方法的丢失,而不是获取方法,丢失子类特有的方法
Person p = new Student(“张三”,17,90);
Student会丢失特有的方法,即无法被调用,父类的引用变量只能调用父类的特有的方法或者子类重写父类的方法
多态的向下转型
由父类转型成子类,在继承图上是向下移动的,所以一般称为向下转型,向下转型是从一个较通用的类型向具体类型的转换,所以是不安全的,需要使用
instancof 操作符来判断,instanceof运算符返回的是一个布尔值,指出对象是否是特定类或者是它子类的一个实例。
用法: result = object instanceof class
result:布尔类型
object:必选项,任意对象的表达式
class:必选项,任意已定义的对象类
如果object是class或者其子类的一个实例,则instanceof运算符返回true,如果不是或者object为null,返回fasle
Person person = new Person();
if(person instanceof Student){
Student student = (Student)person;//false不执行
}
多态的静态绑定和动态绑定
Java中的引用变量有两种类型:一个是编译时的类型,一个是运行时的类型,编译时的类型由声明该变量时使用的类型,运行时的类型由实际赋值给该变量的对象决定,如果编译时类型和运行时类型不一致,就会出现所谓的多态。
静态绑定:程序执行前方法已经绑定(final,static,private,构造方法)
编译期运行,Person.sayHi();
动态绑定:根据变量实际引用的对象类型决定调用哪个方法
运行期运行,Person p = new Person();p.sayHi();
多态基于对象引用的动态绑定特性