----------- android培训、java培训、java学习型技术博客、期待与您交流!------------
什么是继承呢?
我们定义了很多类(猫和狗),发现类里面有很多重复东西,太麻烦了,我们把重复的东西,
抽取出来,封装成一个新的类(Animal),需要让很多个类来继承新的类,也就是Cat和Dog
来继承 Animal .继承之后,类和类直接就发生了关系.就能够使用Animal类中的东西
格式: class 子类名 extends 父类名 {}
class Cat extends Animal{
}
Cat 就是子类
Animal 就是父类
继承:
成员变量
成员方法
但是构造方法不能继承.
好处:
a: 提高了代码复用性
b: 提高了代码维护性
c: 让类于类之前产生了关系,是多态的前提
弊端:
提高了耦合
开发原则: 高内聚 , 低耦合
内聚: 某一个类完成某一件事的能力
耦合: 类于类之间的关系
继承的特点:
在java语言中只支持单继承不支持多继承,但是支持多层继承
继承的注意事项:
a: 子类只能继承父类中非私有的成员
b: 构造方法不能被继承 ,但是可以通过super去访问父类的构造方法
c: 不能为了某一些功能去使用继承
我们什么时候去使用继承?
继承体现的关系: "is a"
举例:
动物
猫
狗
他们满足猫is a动物的关系
狗is a动物
class AnimalTest{
public static void main(String[] args){
Cat c = new Cat();
//使用成员变量 赋值
c.name = "加菲";
System.out.println("我是猫,名字是" + c.getName());
c.eat();
}
}
class Animal {
//成员变量
String color;
private String name;
// int age;
// String sex;
int leg;
//构造方法
Animal(){}
Animal(String color ,String name,int leg){
this.color = color;
this.name = name;
this.leg = leg;
}
//成员方法
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public String getColor(){
return color;
}
public void setColor(String color){
this.color = color;
}
public int getLeg(){
return leg;
}
public void setLeg(int leg){
this.leg = leg;
}
//特有方法
public void eat(){
System.out.println("吃吃吃,吃东西");
}
public void catchSomething(){
System.out.println("抓抓抓,抓东西");
}
}
class Cat extends Animal {
//构造
Cat(){}
Cat(String color ,String name,int leg){
this.color = color;
this.name = name;
this.leg = leg;
}
//成员方法
//get /set 无
//特有方法
//
public void maiMeng(){
System.out.println("喵星人靠卖萌攻占地球...");
}
}
class Dog extends Animal{
//成员变量 无
//构造
Dog(){}
Dog(String color ,String name,int leg){
this.color = color;
this.name = name;
this.leg = leg;
}
//成员方法
//get/ set 无
//特有方法
public void fanEr(){
System.out.println("汪星人靠犯二毁灭自己...");
}
}
继承中的成员方法特点:
成员变量:
变量在访问的时候遵循一个原则"就近原则"
查询顺序:
a: 在本类中的局部位置进行查找
b: 在本类中的成员位置进行查找
c: 在父类的成员位置进行查找
e: 就报错了
构造方法:
我们子类在进行初始化的时候,都需要调用父类的无参的构造方法对父类的数据进行初始化
我们如何一个构造方法的第一条语句默认都是super() ;
Object 类: 其实我们的任何一个类都是间接或者直接的继承自这个类
如果父类中没有无参的构造方法,子类如何进行初始化?
解决方案:
a: 在父类中添加一个构造方法
b: 子类可以使用super关键字去显式的访问父类有参的构造方法
c: 使用this关键字访问本类中其他的构造方法, 但是本类中的其他的构造方法需要使用super显式的访问父类有参的构造方法
this(...) 和 super(...) : 只能是构造方法第一行
this 和 super 区别:
this: 是本类对象的一个引用 , 谁调用我方法中的this就代表谁
super: 是父类存储空间的一个标识(理解: 父类对象的一个引用)
this 和 super 访问成员的格式 :
成员变量:
this.变量名 访问的是本类的成员变量
super.变量名 访问的是父类的成员变量
构造方法:
this(...) 访问的是本类的构造方法
super(...) 访问的是父类的构造方法
成员方法:
this.方法名(...) 访问本类中的成员方法
super.方法名(...) 访问的是父类的成员方法
成员方法的访问的特点:
查找顺序:
a: 在本类中查找
b: 在父类中查找
c: 就报错了
方法重写的注意事项:
a: 父类中私有的方法不能被子类重写
b: 子类在重写父类的方法的时候要求访问权限必须大于或者等于父类的权限
建议: 一致
c: 父类中的静态方法,子类在复写的时候必须使用静态
c.方法重写与方法重载的区别
方法重写(Override): 在子类中出现了和父类一模一样的方法(方法名 , 参数列表 , 返回值类型)
方法重载(Overload): 在同一个类中,允许同时存在一个以上的同名方法, 只有他们的参数列表不同,于返回值类型无关
参数列表不同:
参数的个数不同
参数的类型的不同
class PersonTest{
public static void main(String[] args){
System.out.println();
}
}
//定义Person类
class Person{
//成员变量
private String name;//姓名,年龄
private int age;
//构造
Person(){}
Person(String name,int age){
this.name = name;
this.age = age;
}
//成员方法
//get/set
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("睡好,别在睡觉的是爆炸就好...");
}
}
//定义学生类
class Student extends Person{
//成员变量 可以不写父类中已经有的
//构造
Student(){}
Student(String name ,int age){
super(name,age);//--注意通过super调用父类的构造
}
//特有方法 ,如果你想重写,就写.
public void coding(){
System.out.println("敲,狂敲,死里敲!!!键盘敲烂,薪资过万.....");
}
}
//定义老师类
class Teacher extends Person {
//成员变量 可以不写父类中已经有的
//构造
Teacher(){}
Teacher(String name ,int age){
super(name,age);//--注意通过super调用父类的构造
}
//特有方法 ,如果你想重写,就写.
public void coding(){
System.out.println("敲案例,多多给大家练习");
}
public void teaching(){
System.out.println("教,狂教,死里教!!!希望你们薪资过万.....");
}
}
final关键字
final 的意思表示的是最终的意思
特点:
final 可以修饰类 , 变量 , 方法
被修饰的类: 不能被子类继承
被修饰的变量: 不能被重新赋值 , 其实就是一个常量
被修饰的方法: 不能被子类重写
class Fu{
final int num ;//错误: 可能尚未初始化变量num
final int num =20;
public void show(){
int num =200;
System.out.println(num); //就近原则
System.out.println(this.num);//这是调用的成员方法
}
//final修饰的方法不能被子类重写
public final void show2(){
System.out.println(num); //就近原则
}
}
class Zi extends Fu{
public void show2(){ // 被覆盖的方法为final,无法重写
System.out.println(num); //就近原则
}
}
面试题
final Student s = new Student() ;
s.setName("张三") ;
s.setAge(23) ;
s = new Student() ; // 错误的: 我们这个final修饰引用数据类型的时候,其实指的是地址值不能发生改变
多态(动态绑定机制)
多态的概述:
同一个事物在不同时刻表现出来的多种状态就是多态.
猫 mao = new 猫() ;
动物 d = new 猫() ;
前提:
a: 需要有继承关系
b: 需要有方法重写 , 其实没有方法重写也是可以的,但是没有意义
c: 父类的引用指向子类对象
Fu f = new Zi() ;
多态的成员访问特点:
成员变量:
编译看左边 , 运行看左边
构造方法:
子类在初始化的时候.都要去访问父类中无参的构造方法,对父类的数据进行初始化
成员方法:
非静态的成员方法: 编译看左边 , 运行看右边
静态的成员方法: 编译看左边 , 运行看左边
多态的好处和弊端:
好处:
a: 提高了代码的复用性(靠继承保证的)
b: 提高了代码的扩展性(多态保证)
一般是把父类的名称作为参数传递
弊端:
不能访问子类特有的功能
如果还想访问子类特有的功能,我们需要做一个向下转型.
向上转型和向下转型
向下转型格式: 子类 对象名 = (子类)父类的引用 ;
向上转型格式: 多态的形式就是向上转型
class Fu {
public int num = 100;
public void show() {
System.out.println("show Fu");
}
public static void function() {
System.out.println("function Fu");
}
}
class Zi extends Fu {
public int num = 1000;
public int num2 = 200;
public void show() {
System.out.println("show Zi");
}
public void method() {
System.out.println("method zi");
}
public static void function() {
System.out.println("function Zi");
}
}
class DuoTaiDemo {
public static void main(String[] args) {
//要有父类引用指向子类对象。
//父 f = new 子();
Fu f = new Zi();
System.out.println(f.num);
//找不到符号
//System.out.println(f.num2);
f.show();
//找不到符号
//f.method();
f.function();
}
}
抽象类
抽象类的特点:
a: 抽象类的格式: public abstract class 类名 {}
抽象方法的格式: public abstract 返回值类型 方法名(...) ;
b: 抽象类中有构造方法,但是抽象类有不能被实例化,那么要这个构造方法有何有?
用于子类在访问父类数据的时候,对父类的数据进行初始化
c: 抽象类的子类问题
(1): 子类可以是抽象类
(2): 子类可以是具体的类,但是这个具体的类需要复写父类中的抽象方法
d: 如果一个类中存在抽象方法,那么这个类就必须声明成为抽象类,而一个抽象类中不一定要存在抽象方法
抽象类的成员特点
a: 成员变量: 可以是变量也可以是常量
b: 构造方法: 有构造方法,用于子类在访问父类数据的时候,对父类数据进行初始化
c: 成员方法 可以是抽象方法,可以是非抽象方法
abstract不能和哪些关键字共存?
private 冲突
final 冲突
static 无意义
//定义抽象的动物类
abstract class Animal {
//姓名
private String name;
//年龄
private int age;
public Animal() {}
public Animal(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 abstract void eat();
}
//定义具体的狗类
class Dog extends Animal {
public Dog() {}
public Dog(String name,int age) {
super(name,age);
}
//重写eat方法
public void eat() {
System.out.println("狗吃肉");
}
}
//测试类
class AbstractTest {
public static void main(String[] args) {
//测试狗类
//多态:编译看右边,运行看左边
Animal a = new Dog();
a.setName("旺财");
a.setAge(3);
System.out.println(a.getName()+"---"+a.getAge());
a.eat();
Animal a2 = new Dog("旺财",3);
System.out.println(a2.getName()+"---"+a2.getAge());
a2.eat();
}
}
接口
接口的特点:
a: 接口的定义格式: public interface 接口名 {}
b: 接口中没有构造方法,接口不能被直接实例化,但是可以使用多态的形式对其进行间接的实例化.
c: 子类问题
(1): 可以是抽象类(意义不大)
(2): 可以是具体的类,但是这个具体的类,需要重写接口中所有的抽象方法
接口的成员特点:
成员变量: 只能是常量 ,存在默认的修饰符: public static final
构造方法: 没有构造方法
成员方法: 只能是抽象方法 , 存在默认的修饰符: public abstract
//定义跳高接口
interface Jumpping {
//跳高功能
public abstract void jump();
}
//定义抽象类
abstract class Animal {
//姓名
private String name;
//年龄
private int age;
public Animal() {}
public Animal(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 abstract void eat();
//睡觉(){}
public void sleep() {
System.out.println("睡觉觉了");
}
}
//具体猫类
class Cat extends Animal {
public Cat(){}
public Cat(String name,int age) {
super(name,age);
}
public void eat() {
System.out.println("猫吃鱼");
}
}
//有跳高功能的猫
class JumpCat extends Cat implements Jumpping {
public JumpCat() {}
public JumpCat(String name,int age) {
super(name,age);
}
public void jump() {
System.out.println("跳高猫");
}
}
class InterfaceTest {
public static void main(String[] args) {
//定义跳高猫并测试
JumpCat jc = new JumpCat();
jc.setName("哆啦A梦");
jc.setAge(3);
System.out.println(jc.getName()+"---"+jc.getAge());
jc.eat();
jc.sleep();
jc.jump();
System.out.println("-----------------");
JumpCat jc2 = new JumpCat("加菲猫",2);
System.out.println(jc2.getName()+"---"+jc2.getAge());
jc2.eat();
jc2.sleep();
jc2.jump();
}
}
类与类,类与接口,接口与接口的关系
类与类: 继承的关系,并且是单继承 , 可以是多层继承
类于接口: 实现的关系,可以是单实现,也可以多实现,并且一个类可以在继承一个类的同时,去实现多个接口
接口与接口: 是继承的关系,可以是单继承,也可以是多继承
抽象类与接口的区别:
关系的区别:
类与类: 继承的关系,并且是单继承 , 可以是多层继承
类于接口: 实现的关系,可以是单实现,也可以多实现,并且一个类可以在继承一个类的同时,去实现多个接口
接口与接口: 是继承的关系,可以是单继承,也可以是多继承
成员的区别:
抽象类:
成员变量: 可以是变量也可以是常量
构造方法: 有构造方法,用于子类在访问父类数据的时候,对父类数据进行初始化
成员方法: 可以是抽象方法,也可以是非抽象方法
接口:
成员变量: 只能是常量 ,存在默认的修饰符: public static final
构造方法: 没有构造方法
成员方法: 只能是抽象方法 , 存在默认的修饰符: public abstract
设计理念区别:
抽象类: 需要被继承的体现是一种"is a" 关系 一般定义的都是该继承体系中共性的内容
接口: 需要被实现体现的是一种"like a" 关系 一般定义的都是该继承体系中扩展性的内容