——- android培训、java培训、期待与您交流! ———-
一、继承
1.什么是继承
继承是面向对象最显著的一个特性。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。Java继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。这种技术使得复用以前的代码非常容易,能够大大缩短开发周期,降低开发费用。这样类与类之间就存在了继承的关系。子类可以直接访问父类中的非私有的属性和行为。在代码中通过extends关键字表示继承关系。比如可以先定义一个类叫人,有两个特性,名字和年龄。而又由这个类派生出学生这个类,那么只要让学生去继承Person这个类就可以了,就不用再重新在Student类中重新定义name age 这两个成员了。用代码实现如下:
class Person
{
String name;
int age;
}
class Student extends Person
{
void study()
{
System.out.println("study");
}
}
public class ExtendsDemo
{
public static void main(String[] args)
{
Student st = new Student();
st.name = "zhangsna";
}
}
分析以及注意:
- 将学生和工人的共性描述提取出来,单独的进行描述
- 千万不要为了获取其他类的功能,简化代码而继承
- 必须是类与类之间所属关系才可以继承,,即子类is a 父类
————割———————————–割——————–
2. java中继承的特点
- a,提高了代码的复用性
- b,让类与类之间产生了关系,有了这个关系。才有了多态的特性
- java 语言中 java只支持单继承 不支持多继承。描述:一个父亲只能有一个儿子(但是java支持多实现,多个亲戚)
- 我们可以用代码反证法证明为什么java不支持多继承
class A()
{
void show()
{
System.out.println("a");
}
}
class B()
{
void show()
{
System.out.println("b");
}
}
//如果支持多继承
class C extends A,B
{
}
//为了简便,这里用伪代码
C c = new C();
c.show();//这里就不知道调用谁了,到底是打印a呢还是b?java虚拟机无法辨认
所以说java不支持多继承,因为多继承容易带来安全隐患:
当多个父类中定义了多个相同的功能时,当功能内容不同时,子类对象不确定要运行哪个
java优化了C++ 但是java保留了这种机制,用另一种体现形式来表示,即多实现(多态)
————割———————————–割——————–
3.super关键字
先看一段简单的代码
class Fu
{
Fu()
{
System.out.println("fu run");
}
}
class Zi
{
Zi()
{
//super();
System.out.println("zi run");
System.out.println("zi run");
}
}
class ExtendsDemo
{
public static void main(String[] args)
{
Zi z = new Zi();
}
}
从上面的代码中我们可以得出几点结论
- 子类的所有的构造函数 默认都会访问父类中从参数的构造函数
- 因为子类每一个构造函数内第一行都有一句隐式调用super()
- 当父类中没有控参数的构造函数时,子类必须手动通过super语句来指定访问父类中的构造函数
- 当然 子类的构造函数第一行也可手动指定this语句来访问本类中的构造函数子类中至少会哟与一个构造函数会访问父类中的构造函数
那么为什么子类一定要访问父类的构造函数呢?
原因在于:
- 因为父类中的数据子类可以直接获取 所以子类对象在建立是 要先查看父类是如何对这些数据进行初始化的,所以子类在对象初始化时 要先访问父类的构造函数
- 如果要访问父类中指定的构造函数,可以通过手动定义super()语句来指定要访问那个构造函数
注意 super语句一定必须是子类构造函数的第一行
this()和super()不能出现在同一个构造函数中
————割———————————–割——————–
4. final关键字
final限制了子类访问父类中成员的,final作为一个关键字,有以下几个特点:
- 可以修饰类、函数、变量。
- 被final修饰的类不可以被继承。这样就可以避免被继承、被子类复写功能。
- 被final修饰的方法不可以被复写。
- 被final修饰的变量是一个常量只能赋值一次,既可以修饰成员变量,又可以修饰局部变量。
- 内部类定义在类中的局部位置上时,只能访问该局部被final修饰的局部变量。
————割———————————–割——————–
————割———————————–割——————–
二 抽象类
1.抽象类概述
抽象就是从多个事物中将共性的、 本质的内容抽取出来。
例如:狼和狗共性都是犬科,犬科就是抽象出来的概念。
抽象类:
Java中可以定义没有方法体的方法,该方法的具体实现由子类完成,该方法称为抽象方法,包含抽象方法的类就是抽象类。
抽象方法的由来:
多个对象都具备相同的功能,但是功能具体内容有所不同,那么在抽取过程中,只抽取了功能定义,并未抽取功能主体,那么只有功能声明,没有功能主体的方法称为抽象方法。
————割———————————–割——————–
2.抽象类的特点
- 抽象类和抽象方法必须用abstract关键字来修饰。
- 抽象方法只有方法声明,没有方法体,定义在抽象类中。
- 格式:修饰符 abstract 返回值类型 函数名(参数列表) ;
- 抽象类不可以被实例化,也就是不可以用new创建对象。
示例代码
/*抽象*/
bstract class Demo
{
abstract void show();
}
class DemoA extends Demo
{
void show()
{
System.out.println("demoa show" );
}
}
class DemoB extends Demo
{
void show()
{
System.out.println("demob show" );
}
}
class AbstractDemo{
public static void main(String[] args)
{
DemoA demoA = new DemoA();
demoA.show();
DemoB demoB = new DemoB();
demoB.show();
}
}
运行结果
要注意
该如何描述事物就怎样描述事物 只是不确定的部分也是给事物的功能需要明确. 但是无法定义主体就通过抽象方法来表示
抽象类和一般类的区别:
抽象类比一般类多了抽象方法 就是在类中可以定义抽象方法
抽象类不可以实例化
抽象类中可以不一定有抽象方法 这样做仅仅是不让该类创建对象
看下面一个小程序
/*
需求:获取一段程序的运行时间
原理:获取程序开始的时间 结束时间 并相减
获取时间:System.currentTimeMillis();
当代吗完成优化后 就可以解决这个问题
*/
class TemplateDemo
{
public static void main(String[] args)
{
SubGetTime gt = new SubGetTime();
gt.getTime();
}
}
abstract class GetTime
{
public final void getTime()
{
long start = System.currentTimeMillis();
runCode();
long end = System.currentTimeMillis();
System.out.println((end - start)+"毫秒");
}
//把相同的代码部分抽取出来,由子类去具体实现
public abstract void runCode();
}
class SubGetTime extends GetTime
{
//重写父类的方法
public void runCode()
{
for (int i= 0; i<3000; i++)
{
System.out.println(i);
}
}
}
运行结果
什么是模板方法呢?
在定义功能时,功能的一部分是确定的,但是有一部分功能时不确定的,而确定的部分要使用不确定的部分那么这时就将不确定的部分暴露出去 由该类的子类去实现
————割———————————–割——————–
————割———————————–割——————–
三 接口
1.什么是接口
接口可以认为是一个特殊的抽象类, 当抽象类中的方法都是抽象的,那么该类可以通过接口的形式类表示. 关键字interface声明接口.子类用关键字implements 来实现接口.
class用于定义类
interface用于定义接口
接口定义时,格式特点
1 接口中常见定义:常量 抽象方法
2 接口中的成员都有固定的修饰符
常量:public static final
方法:public abstract
记住:接口中的成员都是public
- 接口:不可以创建对象 因为有抽象方法
- 需要被子类实现 子类对接口中的抽象方法全部覆盖后,子类才可以实例化,否则子类是一个抽象类
- 接口可以被类多实现,也是对多继承不支持的转换形式,java支持多实现
看一个小程序
interface InterA
{
public abstract void method();
}
interface Inter
{
//变成全局常量了
public static final int NUM = 3;
public abstract void show();
//可以编译运行 但是可读性差, 不建议这样写
//int NUM = 3;
//void show();
}
//接口的多实现
class Test implements Inter,InterA
{
public void show(){}
public void method(){}
}
//接口与接口关系:继承
interface A
{
void methodA();
}
interface B
{
void methodB();
}
interface C extends B
{
void methodC();
}
class D implements C
{
//注意 一定要加上public关键字
public void methodA(){}
public void methodB(){}
public void methodC(){}
}
class InterfaceDemo
{
public static void main(String[] args)
{
Test t = new Test();
System.out.println(t.NUM);
System.out.println(Test.NUM);
System.out.println(Inter.NUM);
// t.NUM = 4; error
}
}
————割———————————–割——————–
2.接口的特点
- 接口是对外暴露的规则
- 接口是程序的功能扩展
- 接口可以用来多实现
- 类与接口之间是实现关系,而且来可以继承一个类的同时可以实现多接口
- 接口与接口之间可以有继承关系
看一个小程序以帮助我们理解
//声明抽象类
abstract class Student
{
abstract void study();
void sleep()
{
System.out.println("sleep");
}
}
//声明接口
interface Smoking
{
void smoke();
}
//并不是每个学生都有抽烟的特性,但是每个学生都具有学习和睡觉的功能
class Zhangsan extends Student implements Smoking
{
//张三是一个学生 像一个烟民
//is a like a
//复写抽象类的方法
void study(){}
//实现接口中方法
public void smoke(){}
}
//这是一个不抽烟的学生,好学生.
class Lisi extends Student
{
}
————割———————————–割——————–
3.接口的应用
看下面的程序
abstract class Sporter
{
abstract void play();
}
interface Study
{
}
class wangwu extends Sporter implements Study
{
public void play()
{
System.out.println("踢足球");
}
}
class Inte
{
public static void main(String[] args)
{
new wangwu().play();
}
}
- 基本功能定义在类中
特定功能定义在接口中
用自己的话讲就是找到组织了 那就是继承
- 干点副业 这就是接口
————割———————————–割——————–
4.总结: 接口和抽象类的区别
- 抽象类中有构造方法,而接口中没有.
- 抽象类中可以有普通成员变量 接口中没有
- 抽象类中可以有非抽象普通方法, 接口必须是抽象方法
- 抽象类中的抽象方法访问类型可以是public protected. 但接口只能是public, 并且默认为public abstract
- 抽象类中可以有抽象方法, 接口中不能有,
- 抽象类和接口中都可以包含静态成员变量,但是接口中的变量只能是public static (final),不能被修改.
- 一个类只能继承一个抽象类,但是接口可以多实现
- 若一个类只实现了一个接口的部分方法,那么这个类必须为抽象类.