------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
第一讲 多态
一,多态
1.父类的引用指向它的某个子类的对象。这种形式就叫:多态
2.多态的前提和体现:
1).前提:一定要有继承关系;
要有方法的重写;
用父类的引用指向子类的对象
class Animal
{
}
class Cat extends Animal
{
}
class Dog extends Animal
{
}
class Employee
{
}
class Demo
{
public static void main(String[] args)
{
//正常情况下,实例化一个Cat对象
Cat c = new Cat();
//使用多态,父类的引用指向子类的对象
Animal a = new Cat();//OK的
Animal a2 = new Dog();//OK的
Animal a3 = new Employee();//编译错误。多态必须要有继承关系;
}
}
二,多态中成员的访问特点
1.多态时,通过父类的引用访问的必须是父类中定义的,不能访问子类特有的成员;
二.发生覆盖时:
1.普通成员变量:编译看左边:编译时,父类中必须要有此成员,否则编译错误
运行看左边:运行后,打印的,也是父类的内容;
2.普通成员方法:
编译看左边: 编译时,父类中必须要有此成员,否则编译错误
运行看右边:运行时,运行时的是"子类中的方法"
3.静态成员方法:静态的,跟"类"有关,跟"对象"无关,不存在动态绑定:
编译看左边:编译时,父类中必须要有此成员,否则编译错误
运行看左边:运行后,打印的,也是父类的内容;
总结一句话:多态时,访问的成员,父类中必须要有;只有成员方法是调用的子类的,其它都是父类的
三,多态好处与弊端
好处:提高了程序的维护性(由继承保证)
弊端:多态时,不能访问子类特有的成员
class A
{
}
class B extends A
{
void show(){
System.out.println("B --> show()");
}
}
class Demo
{
public static void main(String[] args)
{
A a = new B();
a.show();//编译错误,不能访问子类特有的成员;
}
三,多态的类型转换
1.向上转型:父类的引用指向了子类对象。隐式的自动转换
class A{}
class B extends A{}
main(){
A a = new B();//向上转型
}
特点:
1.多态;
2.访问的只能是父类中定义的成员,不能访问子类特有的成员;
2.向下转型:如果确定父类类型指向了某个子类的对象,那么可以将这个父类型的引用
强制转换为它所指向的子类类型的引用。
注意:向下转型时,由于有可能会发生ClassCastException。所以,为了安全起见,Java为我们提供了一个
判断的运算符:instanceof
1.双目运算符:
2.使用格式:变量 instanceof 某个类类型
3.它会返回一个boolean值,如果"变量"是"某个类类型",那么返回true,否则返回false;
4.在强制转换前,可以使用这个操作符进行判断;
class A
{
void show(){
System.out.println("A-->show()");
}
}
class B extends A
{
void method(){
System.out.println("B-->method()");
}
}
class C extends A
{
}
class Demo
{
public static void main(String[] args)
{
A a = new B();//隐式的,向上转型
a.show();
/// a.method();//不可以,编译错误,不能访问子类特有成员;
//可以将变量a强制转换为B类类型;
B b = (B)a;
//转换后,就可以访问子类特有的成员了
b.method();
// C c = (C)a;//不可以。B和C没有关系,不能强制转换。编译可以通过,运行时异常:ClassCastException
System.out.println("将子类类型自动提升为父类类型:");
A a2 = b;//可以直接赋值,隐式的自动转换
a2.show();
//在向下转型时,使用instanceof操作符进行判断
if(a instanceof B){
System.out.println("a 指向的是 B的对象,可以安全向下转换为B类型");
B b2 = (B)a;
}
if(a instanceof C){
System.out.println("a 指向的是 C的对象,可以安全向下转换为C类型");
C c2 = (C)a;
}
}
}
第二讲 抽象类
一,抽象类
1.有些时候,有些父类中的一些方法,会被每个子类都要重写,
所以此时,父类中这个方法的定义就没有意思。
2.这时,可以将父类中的这个方法定义为"抽象的方法";只有方法声明,没有方法体;
需要一个关键字:abstract
例如:
abstract void show();//直接分号结束,没有大括号;
3.如果父类中,有一个方法是"抽象方法",那么这个类也必须是"抽象的",在类的定义处
需要使用关键字:abstract
4.如果一个类是"抽象类",就意味着这个类"不能被实例化"了。
5.一个抽象类,就是用来做"父类",被其它类"继承"的。
abstract class Person
{
abstract void show();
}
class Student extends Person
{
//重写show
void show(){
System.out.println("我是黑马的一名学生");
}
}
class Teacher extends Person
{
//重写show
void show(){
System.out.println("我是黑马的一名教师");
}
}
class Demo
{
public static void main(String[] args)
{
Person p1 = new Student();
p1.show();//子类
}
}
二,抽象类的特点
1.抽象类和抽象方法,使用关键字:abstract修饰;
2.抽象类中,可以什么都不定义。包括抽象方法;
3.抽象类中的可以有什么东西:
1).成员变量:
2).成员方法;
3).构造方法:
4).抽象方法:
4.子类继承一个抽象类仍然使用:extends ,而且仍然是"单继承"
5.如果一个子类,继承了一个抽象类,那么必须要全部重写父类中的"抽象方法",可以不重写或不全部重写,
那么这个子类也必须是"抽象类"。换句话说:一个抽象类可以继承自一个抽象类;
abstract class Person
{
//成员变量
private int num = 10;
//成员方法
public void show(){
System.out.println("Person --> show()");
}
//构造方法
Person(){
System.out.println("Person的无参构造方法");
}
//抽象方法
public abstract void eat();
public abstract void sleep();
public abstract void method();
}
//一个类,继承自一个抽象类后,必须重写抽象类中的所有抽象方法
class Student extends Person
{
public void eat(){
System.out.println("烤冷面");
}
public void sleep(){
System.out.println("我睡觉");
}
public void method(){
System.out.println("method方法");
}
}
//
abstract class Teacher extends Person
{
//只重写一个方法。那么这个类,也必须是一个抽象类
public void eat(){
}
//其它两个抽象方法没有重写
}
class Demo
{
public static void main(String[] args)
{
// Person p = new Person();
Person p = new Student();
}
}
第三讲 接口
一,定义
1.当一个抽象类中没有实现的方法,而只有抽象方法时,可以将这个类定义为:接口;
使用关键字:interface
2.接口跟抽象类一样,不能被"实例化",用来做父类的;
3.子类是"实现接口",使用关键字:implements
4.如果一个类实现某个接口,那么必须全部重写接口的抽象方法;
5.接口中可以定义什么:JDK8以前:
1.成员变量:必须是全局常量:必须被声明为:public static final,可以不这样声明,但编译器会自动添加
interface IA{
int num = 10;//隐式的自动声明为:public static final int num = 10;
}
2.成员方法(抽象方法):必须是抽象方法,必须被声明为:public abstract。可以不这样声明,但编译器会自动添加
interface IA{
void show();//隐式的自动声明为:public abstract void show();
}
interface IService
{
abstract void add();
abstract void update();
abstract void delete();
abstract void find();
}
class StudentService implements IService
{
//必须全部重写接口中的抽象方法
public void add(){
}
public void update(){
}
public void delete(){
}
public void find(){
}
}
class Demo
{
public static void main(String[] args)
{
//使用接口多态
IService is = new StudentService();
is.add();//子类的
}
}
二,接口的特点
1.定义接口:关键字:interface
格式:interface 接口名
2.子类实现:关键字:implements
3.一个子类,可以同时实现多个接口。格式:
class SubA implements IA,IB,IC{
}
必须要重写三个接口中的所有抽象方法;
4.一个接口,可以"继承自"另一个接口,而且可以"多继承":使用关键字extends
5.一个抽象类,仍然是实现接口,而且可以实现多个接口,而且可以不重写或不全部重写接口中的方法。因为此类本身就是个"抽象的"
6.一个类可以同时继承自一个父类,并同时实现一个或多个接口:一定要先"继承",后"实现"
三,接口与抽象类的区别
相同点:都不能被实例化;
区别:
1.定义关键字:
1).接口:interface
2).抽象类:abstract class
2.子类使用时:
1).接口:implements(实现):可以同时实现多个接口
2).抽象类: extends(继承):单继承
3.内部成员:
1).接口:
A.成员变量:public static final
B.抽象方法:public abstract
2).抽象类:
A.成员变量
B.成员方法
C.构造方法
D.抽象方法;
4.接口和接口之间:继承关键,可以多继承
抽象类和抽象类之间:继承关系,单继承;