-----------android培训、java培训、java学习型技术博客、期待与您交流!------------
黑马程序员——Java基础---面向对象(继承、多态、抽象类、接口、内部类)
-----------android培训、java培训、java学习型技术博客、期待与您交流!------------
一、继承
1、概述
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,
那么多个类无需再定义这些属性和行为,只要继承那个类即可。
通过extends关键字可以实现类与类的继承
class 子类名 extends 父类名 {}
单独的这个类称为父类,基类或者超类;这多个类可以称为子类或者派生类。
有了继承以后,我们定义一个类的时候,可以在一个已经存在的类的基础上,还可以定义自己的新成员。
2、继承的好处和弊端
(1)继承的好处:
A:提高了代码的复用性
B:提高了代码的维护性
C:让类与类之间产生了关系,是多态的前提
(2)继承的弊端
A:类的耦合性增强了。
开发的原则:高内聚,低耦合。
3、Java中类的继承特点
(1)Java只支持单继承,不支持多继承。(一个儿子只能有一个爹)
(2)Java支持多层继承(继承体系)
(3)如果想用这个体系的所有功能用最底层的类创建对象
(4)如果想看这个体系的共性功能,看最顶层的类
继承的注意事项和什么时候使用继承
A:子类只能继承父类所有非私有的成员(成员方法和成员变量)
B:子类不能继承父类的构造方法,但是可以通过super(马上讲)关键字去访问父类构造方法。
C:不要为了部分功能而去继承
4、this和super的区别和应用
Super:子类局部范围访问父类成员变量
this代表本类对象的引用。
super代表父类存储空间的标识(可以理解为父类引用)
(1)调用成员变量
this.成员变量 调用本类的成员变量,也可以调用父类的成员变量
super.成员变量 调用父类的成员变量
(2)调用构造方法
this(...) 调用本类的构造方法
super(...) 调用父类的构造方法
(3)调用成员方法
this.成员方法 调用本类的成员方法,也可以调用父类的方法
super.成员方法 调用父类的成员方法
5、继承中构造方法的关系
子类中所有的构造方法默认都会访问父类中空参数的构造方法
因为子类会继承父类中的数据,可能还会使用父类的数据。
所以,子类初始化之前,一定要先完成父类数据的初始化。
每一个构造方法的第一条语句默认都是:super()在这里简单的提一句,Object类。
否则有人就会针对父类的构造方法有疑问。Object在没有父类了。
继承中构造方法的注意事项
父类没有无参构造方法,子类怎么办:
super解决
this解决
注意: super(…)或者this(….)必须出现在第一条语句上
6、方法重写应用
当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法。
这样,即沿袭了父类的功能,又定义了子类特有的内容。
7、方法重写的注意事项
(1) 父类中私有方法不能被重写
因为父类私有方法子类根本就无法继承
(2) 子类重写父类方法时,访问权限不能更低
最好就一致
(3) 父类静态方法,子类也必须通过静态方法进行重写
其实这个算不上方法重写,但是现象确实如此,至于为什么算不上方法重写,多态中我会讲解(静态只能覆盖静态)
子类重写父类方法的时候,最好声明一模一样。
8、方法重写的面试题
(1) Override和Overload的区别?Overload能改变返回值类型吗?
overload可以改变返回值类型,只看参数列表
方法重写:子类中出现了和父类中方法声明一模一样的方法。与返回值有关,返回值必须是一致的
方法重载:本类中出现的方法名一样,参数列表不同的方法。与返回值无关。
子类对象调用方法的时候:先找子类本身,再找父类。
9、final关键字修饰类,方法以及变量的特点
(1)final修饰特点
A: 修饰类,类不能被继承
B: 修饰变量,变量就变成了常量,只能被赋值一次
C:修饰方法,方法不能被重写
(2)final关键字修饰局部变量
A:基本类型,是值不能被改变
B:引用类型,是地址值不能被改变,对象中的属性可以改变
(3)final修饰变量的初始化时机:S在对象构造完毕前即可
二、多态
1、多态概述
某一个事物,在不同时刻表现出来的不同状态。
2、多态前提和体现
(1)有继承关系
(2)有方法重写
(3)有父类引用指向子类对象
3、成员访问特点
(1)成员变量
编译看左边,运行看左边
(2)成员方法
编译看左边,运行看右边
(1)静态方法
编译看左边,运行看左边
所以前面我说静态方法不能算方法的重写
4、多态的好处和弊端
(1)多态的好处
提高了程序的维护性(由继承保证)
提高了程序的扩展性(由多态保证)
(2)多态的弊端
不能访问子类特有功能
那么我们如何才能访问子类的特有功能呢?
多态中的转型
5、多态中的转型问题
(1)向上转型
从子到父
父类引用指向子类对象
(2)向下转型
从父到子
父类引用转为子类对象
(3)多态成员访问及转型的理解
6、案例演示南方人北方人饮食习惯
/*
南方人,北方人的饮食问题
继承思想,共性抽取出父类
子类对象调用,写成多态形式调用
*/
class Person
{
public void eat(){}
}
class SouthPerson extends Person
{
public void eat(){
System.out.println("南方人吃炒菜米饭");
}
}
class NorthPerson extends Person
{
public void eat(){
System.out.println("北方人吃烩菜馒头");
}
}
class DuoTaiDemo4
{
public static void main(String[] args)
{
//纯子类的调用,没有多态,不需要考虑父类
SouthPerson s = new SouthPerson();
s.eat();
NorthPerson n = new NorthPerson();
n.eat();
//父类引用指向子类对象的多态调用
Person p = new SouthPerson();
p.eat();
p = new NorthPerson();
p.eat();
//Person p1 = new
//System.out.println("Hello World!");
}
}
三、抽象类
1、Java中,一个没有方法体的方法应该定义为抽象方法,
而类中如果有抽象方法,该类必须定义为抽象类。
2、抽象类特点
(1) 抽象类和抽象方法必须用abstract关键字修饰
(2)格式
abstract class 类名 {}
public abstract void eat();
(3)抽象类不一定有抽象方法,有抽象方法的类一定是抽象类
(4) 抽象类不能实例化
那么,抽象类如何实例化呢?
按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
(5)抽象类的子类
要么是抽象类
要么重写抽象类中的所有抽象方法
3、抽象类的成员特点
(1)成员变量
可以是变量
也可以是常量
(2)构造方法
有构造方法,但是不能实例化
那么,构造方法的作用是什么呢?
用于子类访问父类数据的初始化
(3)成员方法
可以有抽象方法 限定子类必须完成某些动作
也可以有非抽象方法 提高代码服用性。
4、abstract不能和哪些关键字共存
private 冲突
final 冲突
static 无意义
5、案例练习
/*
根据要求设计类
员工 : 属性 姓名 工号 工资
经理 : 属性 姓名 工号 工资 奖金
共有的功能: 工作
*/
//定义公司类 包含成员姓名,工号,工资 抽象方法 job
abstract class Company
{
private String name;
private String id;
private double salary;
Company(String name,String id,double salary){
this.name = name;
this.id = id;
this.salary = salary;
}
public void setName(String name){
this.name=name;
}
public void setId(String id){
this.id = id;
}
public void setSalary(double salary){
this.salary = salary;
}
public String getName(){
return name;
}
public String getId(){
return id;
}
public double getSalary(){
return salary;
}
public abstract void job();
}
//定义员工类,继承公司类,重写抽象方法,super语句变量传递到父类构造方法赋值
class Employee extends Company
{
Employee(String name,String id,double salary){
super(name,id,salary);
}
public void job(){
System.out.println(getName()+" "+getId()+" "+getSalary()+" 在写程序");
}
}
//定义经理类,继承公司类,重写抽象方法,super语句变量传递到父类构造方法赋值
//但是,经理自己的奖金数据,不能传递父类
class Manager extends Company
{
private double bonus;//经理的特有成员,奖金
Manager(String name,String id,double salary,double bonus){
super(name,id,salary);
this.bonus=bonus;
}
public void setBonus(double bonus){
this.bonus=bonus;
}
public double getBonus(){
return bonus;
}
public void job(){
System.out.println(getName()+" "+getId()+" "+getSalary()+" "+ bonus+" 经理在指挥写程序");
}
}
class AbstractCompanyTest
{
public static void main(String[] args)
{
Company c = new Employee("张三","开发部001",12345.67);
c.job();
c = new Manager("李四","董事会001",567.89,123678.89);
c.job();
//System.out.println("Hello World!");
}
}
四、接口
1、接口概述
从狭义的角度讲就是指java中的interface
从广义的角度讲对外提供规则的都是接口
2、接口特点
(1)接口用关键字interface表示: interface 接口名 {}
(2)类实现接口用implements表示: class 类名 implements 接口名 {}
(3)接口不能实例化 : 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,接口多态。
(4)接口的子类
A:可以是抽象类。但是意义不大。
B:可以是具体类。要重写接口中的所有抽象方法。(推荐)
3、接口成员特点
(1)成员变量;
只能是常量,并且是静态的。
默认修饰符:public static final
建议:自己手动给出。
(2)构造方法:接口没有构造方法。
(3)成员方法:只能是抽象方法。
默认修饰符:public abstract
建议:自己手动给出。
五、类与类,类与接口以及接口与接口的关系
1、类与类
继承关系,只能单继承,但是可以多层继承
2、类与接口
实现关系,可以单实现,也可以多实现。还可以在继承一个类的同时实现多个接口
3、接口与接口
继承关系,可以单继承,也可以多继承
4、抽象类和接口的区别
(1)成员区别
抽象类 变量,常量;有抽象方法;抽象方法,非抽象方法
接口 常量;抽象方法
(2)关系区别
类与类 继承,单继承
类与接口 实现,单实现,多实现
接口与接口 继承,单继承,多继承
(3)设计理念区别
抽象类 被继承体现的是:”is a”的关系。共性功能
接口 被实现体现的是:”like a”的关系。扩展功能
六、权限修饰符
1、public protected 默认 private
2、类及其组成可以用的修饰符
(1)修饰符:
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
抽象修饰符:abstract
(2)类:
权限修饰符:默认修饰符,public
状态修饰符:final
抽象修饰符:abstract
用的最多的就是:public
(3)成员变量:
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
用的最多的就是:private
(4)构造方法:
权限修饰符:private,默认的,protected,public
用的最多的就是:public
(5)成员方法:
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
抽象修饰符:abstract
用的最多的就是:public
(6)除此以外的组合规则:
成员变量:public static final
成员方法:
public static
public abstract
*public final
七、内部类
1、把类定义在其他类的内部,这个类就被称为内部类。
举例:在类A中定义了一个类B,类B就是内部类。
2、内部类的访问特点:
内部类可以直接访问外部类的成员,包括私有。
外部类要访问内部类的成员,必须创建对象。
3、内部类位置
成员位置(成员内部类)
局部位置(局部内部类)
4、调用内部类成员的三个格式
(1) 内部类,方法全非静态
外部类名.内部类名 对象名 = new 外部类对象().new内部类对象();
(2)内部类,方法全静态
外部类名.内部类名.内部类方法()
(3)内部类静态,方法非静态
外部类名.内部类名 对象名 = new 外部类对象.内部类对象();
5、为什么局部内部类访问局部变量加final
因为局部变量会随着方法的调用完毕而消失,这个时候,局部对象并
没有立马从堆内存中消失,还要使用那个变量。为了让数据还能继续
被使用,就用fianl修饰,这样,在堆内存里面存储的其实是一个常量值。通过反编译工具可以看一下。
八、匿名内部类
1、就是内部类的简化写法。
2、前提:存在一个类或者接口
这里的类可以是具体类也可以是抽象类。
3、格式:
new 类名或者接口名() {重写方法;}
4、本质:
是一个继承了类或者实现了接口的子类匿名对象
-----------android培训、java培训、java学习型技术博客、期待与您交流!------------
一、继承
1、概述
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,
那么多个类无需再定义这些属性和行为,只要继承那个类即可。
通过extends关键字可以实现类与类的继承
class 子类名 extends 父类名 {}
单独的这个类称为父类,基类或者超类;这多个类可以称为子类或者派生类。
有了继承以后,我们定义一个类的时候,可以在一个已经存在的类的基础上,还可以定义自己的新成员。
2、继承的好处和弊端
(1)继承的好处:
A:提高了代码的复用性
B:提高了代码的维护性
C:让类与类之间产生了关系,是多态的前提
(2)继承的弊端
A:类的耦合性增强了。
开发的原则:高内聚,低耦合。
3、Java中类的继承特点
(1)Java只支持单继承,不支持多继承。(一个儿子只能有一个爹)
(2)Java支持多层继承(继承体系)
(3)如果想用这个体系的所有功能用最底层的类创建对象
(4)如果想看这个体系的共性功能,看最顶层的类
继承的注意事项和什么时候使用继承
A:子类只能继承父类所有非私有的成员(成员方法和成员变量)
B:子类不能继承父类的构造方法,但是可以通过super(马上讲)关键字去访问父类构造方法。
C:不要为了部分功能而去继承
4、this和super的区别和应用
Super:子类局部范围访问父类成员变量
this代表本类对象的引用。
super代表父类存储空间的标识(可以理解为父类引用)
(1)调用成员变量
this.成员变量 调用本类的成员变量,也可以调用父类的成员变量
super.成员变量 调用父类的成员变量
(2)调用构造方法
this(...) 调用本类的构造方法
super(...) 调用父类的构造方法
(3)调用成员方法
this.成员方法 调用本类的成员方法,也可以调用父类的方法
super.成员方法 调用父类的成员方法
5、继承中构造方法的关系
子类中所有的构造方法默认都会访问父类中空参数的构造方法
因为子类会继承父类中的数据,可能还会使用父类的数据。
所以,子类初始化之前,一定要先完成父类数据的初始化。
每一个构造方法的第一条语句默认都是:super()在这里简单的提一句,Object类。
否则有人就会针对父类的构造方法有疑问。Object在没有父类了。
继承中构造方法的注意事项
父类没有无参构造方法,子类怎么办:
super解决
this解决
注意: super(…)或者this(….)必须出现在第一条语句上
6、方法重写应用
当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法。
这样,即沿袭了父类的功能,又定义了子类特有的内容。
7、方法重写的注意事项
(1) 父类中私有方法不能被重写
因为父类私有方法子类根本就无法继承
(2) 子类重写父类方法时,访问权限不能更低
最好就一致
(3) 父类静态方法,子类也必须通过静态方法进行重写
其实这个算不上方法重写,但是现象确实如此,至于为什么算不上方法重写,多态中我会讲解(静态只能覆盖静态)
子类重写父类方法的时候,最好声明一模一样。
8、方法重写的面试题
(1) Override和Overload的区别?Overload能改变返回值类型吗?
overload可以改变返回值类型,只看参数列表
方法重写:子类中出现了和父类中方法声明一模一样的方法。与返回值有关,返回值必须是一致的
方法重载:本类中出现的方法名一样,参数列表不同的方法。与返回值无关。
子类对象调用方法的时候:先找子类本身,再找父类。
9、final关键字修饰类,方法以及变量的特点
(1)final修饰特点
A: 修饰类,类不能被继承
B: 修饰变量,变量就变成了常量,只能被赋值一次
C:修饰方法,方法不能被重写
(2)final关键字修饰局部变量
A:基本类型,是值不能被改变
B:引用类型,是地址值不能被改变,对象中的属性可以改变
(3)final修饰变量的初始化时机:S在对象构造完毕前即可
二、多态
1、多态概述
某一个事物,在不同时刻表现出来的不同状态。
2、多态前提和体现
(1)有继承关系
(2)有方法重写
(3)有父类引用指向子类对象
3、成员访问特点
(1)成员变量
编译看左边,运行看左边
(2)成员方法
编译看左边,运行看右边
(1)静态方法
编译看左边,运行看左边
所以前面我说静态方法不能算方法的重写
4、多态的好处和弊端
(1)多态的好处
提高了程序的维护性(由继承保证)
提高了程序的扩展性(由多态保证)
(2)多态的弊端
不能访问子类特有功能
那么我们如何才能访问子类的特有功能呢?
多态中的转型
5、多态中的转型问题
(1)向上转型
从子到父
父类引用指向子类对象
(2)向下转型
从父到子
父类引用转为子类对象
(3)多态成员访问及转型的理解
6、案例演示南方人北方人饮食习惯
/*
南方人,北方人的饮食问题
继承思想,共性抽取出父类
子类对象调用,写成多态形式调用
*/
class Person
{
public void eat(){}
}
class SouthPerson extends Person
{
public void eat(){
System.out.println("南方人吃炒菜米饭");
}
}
class NorthPerson extends Person
{
public void eat(){
System.out.println("北方人吃烩菜馒头");
}
}
class DuoTaiDemo4
{
public static void main(String[] args)
{
//纯子类的调用,没有多态,不需要考虑父类
SouthPerson s = new SouthPerson();
s.eat();
NorthPerson n = new NorthPerson();
n.eat();
//父类引用指向子类对象的多态调用
Person p = new SouthPerson();
p.eat();
p = new NorthPerson();
p.eat();
//Person p1 = new
//System.out.println("Hello World!");
}
}
三、抽象类
1、Java中,一个没有方法体的方法应该定义为抽象方法,
而类中如果有抽象方法,该类必须定义为抽象类。
2、抽象类特点
(1) 抽象类和抽象方法必须用abstract关键字修饰
(2)格式
abstract class 类名 {}
public abstract void eat();
(3)抽象类不一定有抽象方法,有抽象方法的类一定是抽象类
(4) 抽象类不能实例化
那么,抽象类如何实例化呢?
按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
(5)抽象类的子类
要么是抽象类
要么重写抽象类中的所有抽象方法
3、抽象类的成员特点
(1)成员变量
可以是变量
也可以是常量
(2)构造方法
有构造方法,但是不能实例化
那么,构造方法的作用是什么呢?
用于子类访问父类数据的初始化
(3)成员方法
可以有抽象方法 限定子类必须完成某些动作
也可以有非抽象方法 提高代码服用性。
4、abstract不能和哪些关键字共存
private 冲突
final 冲突
static 无意义
5、案例练习
/*
根据要求设计类
员工 : 属性 姓名 工号 工资
经理 : 属性 姓名 工号 工资 奖金
共有的功能: 工作
*/
//定义公司类 包含成员姓名,工号,工资 抽象方法 job
abstract class Company
{
private String name;
private String id;
private double salary;
Company(String name,String id,double salary){
this.name = name;
this.id = id;
this.salary = salary;
}
public void setName(String name){
this.name=name;
}
public void setId(String id){
this.id = id;
}
public void setSalary(double salary){
this.salary = salary;
}
public String getName(){
return name;
}
public String getId(){
return id;
}
public double getSalary(){
return salary;
}
public abstract void job();
}
//定义员工类,继承公司类,重写抽象方法,super语句变量传递到父类构造方法赋值
class Employee extends Company
{
Employee(String name,String id,double salary){
super(name,id,salary);
}
public void job(){
System.out.println(getName()+" "+getId()+" "+getSalary()+" 在写程序");
}
}
//定义经理类,继承公司类,重写抽象方法,super语句变量传递到父类构造方法赋值
//但是,经理自己的奖金数据,不能传递父类
class Manager extends Company
{
private double bonus;//经理的特有成员,奖金
Manager(String name,String id,double salary,double bonus){
super(name,id,salary);
this.bonus=bonus;
}
public void setBonus(double bonus){
this.bonus=bonus;
}
public double getBonus(){
return bonus;
}
public void job(){
System.out.println(getName()+" "+getId()+" "+getSalary()+" "+ bonus+" 经理在指挥写程序");
}
}
class AbstractCompanyTest
{
public static void main(String[] args)
{
Company c = new Employee("张三","开发部001",12345.67);
c.job();
c = new Manager("李四","董事会001",567.89,123678.89);
c.job();
//System.out.println("Hello World!");
}
}
四、接口
1、接口概述
从狭义的角度讲就是指java中的interface
从广义的角度讲对外提供规则的都是接口
2、接口特点
(1)接口用关键字interface表示: interface 接口名 {}
(2)类实现接口用implements表示: class 类名 implements 接口名 {}
(3)接口不能实例化 : 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,接口多态。
(4)接口的子类
A:可以是抽象类。但是意义不大。
B:可以是具体类。要重写接口中的所有抽象方法。(推荐)
3、接口成员特点
(1)成员变量;
只能是常量,并且是静态的。
默认修饰符:public static final
建议:自己手动给出。
(2)构造方法:接口没有构造方法。
(3)成员方法:只能是抽象方法。
默认修饰符:public abstract
建议:自己手动给出。
五、类与类,类与接口以及接口与接口的关系
1、类与类
继承关系,只能单继承,但是可以多层继承
2、类与接口
实现关系,可以单实现,也可以多实现。还可以在继承一个类的同时实现多个接口
3、接口与接口
继承关系,可以单继承,也可以多继承
4、抽象类和接口的区别
(1)成员区别
抽象类 变量,常量;有抽象方法;抽象方法,非抽象方法
接口 常量;抽象方法
(2)关系区别
类与类 继承,单继承
类与接口 实现,单实现,多实现
接口与接口 继承,单继承,多继承
(3)设计理念区别
抽象类 被继承体现的是:”is a”的关系。共性功能
接口 被实现体现的是:”like a”的关系。扩展功能
六、权限修饰符
1、public protected 默认 private
2、类及其组成可以用的修饰符
(1)修饰符:
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
抽象修饰符:abstract
(2)类:
权限修饰符:默认修饰符,public
状态修饰符:final
抽象修饰符:abstract
用的最多的就是:public
(3)成员变量:
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
用的最多的就是:private
(4)构造方法:
权限修饰符:private,默认的,protected,public
用的最多的就是:public
(5)成员方法:
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
抽象修饰符:abstract
用的最多的就是:public
(6)除此以外的组合规则:
成员变量:public static final
成员方法:
public static
public abstract
*public final
七、内部类
1、把类定义在其他类的内部,这个类就被称为内部类。
举例:在类A中定义了一个类B,类B就是内部类。
2、内部类的访问特点:
内部类可以直接访问外部类的成员,包括私有。
外部类要访问内部类的成员,必须创建对象。
3、内部类位置
成员位置(成员内部类)
局部位置(局部内部类)
4、调用内部类成员的三个格式
(1) 内部类,方法全非静态
外部类名.内部类名 对象名 = new 外部类对象().new内部类对象();
(2)内部类,方法全静态
外部类名.内部类名.内部类方法()
(3)内部类静态,方法非静态
外部类名.内部类名 对象名 = new 外部类对象.内部类对象();
5、为什么局部内部类访问局部变量加final
因为局部变量会随着方法的调用完毕而消失,这个时候,局部对象并
没有立马从堆内存中消失,还要使用那个变量。为了让数据还能继续
被使用,就用fianl修饰,这样,在堆内存里面存储的其实是一个常量值。通过反编译工具可以看一下。
八、匿名内部类
1、就是内部类的简化写法。
2、前提:存在一个类或者接口
这里的类可以是具体类也可以是抽象类。
3、格式:
new 类名或者接口名() {重写方法;}
4、本质:
是一个继承了类或者实现了接口的子类匿名对象